Convert the first character
of a
If the message is a string, we use str::downcase-first on the string.
Otherwise, if the format string of the message does not start with a tilde-directive (see fmt), we use str::downcase-first on the format string.
Otherwise, we need to look at the tilde-directive that starts the format string of the message, and possibly modify the tilde-directive and the corresponding value in the alist, in order to suitably convert the first character of the resulting formatted string to lower case. This is done as follows:
Since msgp is a weak recognizer for messages, there is no guarantee that the format string is followed by an alist, and that the values in the alist have the appropriate types. This function leaves the message unchanged if some of these properties do not hold.
Function:
(defun msg-downcase-first (msg) (declare (xargs :guard (msgp msg))) (let ((__function__ 'msg-downcase-first)) (declare (ignorable __function__)) (b* (((when (stringp msg)) (str::downcase-first msg)) ((cons string alist) msg) ((unless (and (> (length string) 0) (eql (char string 0) #\~))) (cons (str::downcase-first string) alist)) ((unless (and (>= (length string) 3) (member (char string 1) (list #\@ #\# #\* #\& #\v #\N #\s #\S)))) msg)) (case (char string 1) (#\@ (b* (((unless (alistp alist)) msg) (value (cdr (assoc (char string 2) alist))) ((unless (msgp value)) msg) (new-alist (acons (char string 2) (msg-downcase-first value) alist))) (cons string new-alist))) (#\N (b* ((new-string (concatenate 'string "~n" (subseq string 2 nil)))) (cons new-string alist))) ((#\s #\S) (b* (((unless (alistp alist)) msg) (value (cdr (assoc (char string 2) alist))) ((unless (stringp value)) msg) (new-alist (acons (char string 2) (str::downcase-first value) alist))) (cons string new-alist))) (otherwise (prog2$ (raise "Message not supported: ~x0" msg) msg))))))
Theorem:
(defthm msgp-of-msg-downcase-first (implies (and (msgp msg)) (b* ((new-msg (msg-downcase-first msg))) (msgp new-msg))) :rule-classes :rewrite)