2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 # include "lclintMacros.nf"
31 /* patch for linux? solaris? */
33 static char strbuf[64];
39 XCHAR, XSTRING, XSTRINGFREE, XTSTRINGFREE, XINT, XFLOAT, XBOOL, XUENTRY,
40 XPERCENT, XCTYPE, XPLURAL, XREPREFIX, XFILELOC
43 /* char *s, anytype v */
45 # define GETPRINTF(s,v) (sprintf (strbuf, s, v), mstring_copy (strbuf))
48 ** returns control code indicated by *c, and
49 ** advances *c to next character.
53 identify_control (char **s)
65 if (c >= '0' && c <= '9')
75 ** handle single-char codes
94 return (XINT); /* unsigned */
96 return (XINT); /* unsigned long */
110 llcontbug (message ("Message: invalid code: %h (%s)", c,
111 cstring_fromChars (*s)));
119 ** returns a cstring containing the message, as formated by s.
121 ** the format codes are similar to printf:
123 ** %s cstring (don't free after print)
124 ** %q cstring (free after print)
127 ** %b bool (uses bool_unparse)
136 message (fmt, va_alist)
140 /*@messagelike@*/ /*@only@*/ cstring
141 message (/*@temp@*/ char *fmt, ...)
146 char *ret = mstring_createEmpty ();
153 va_start (pvar, fmt);
156 while ((c = *fmt++) != '\0')
160 /*@-loopswitchbreak@*/
162 switch (identify_control (&fmt))
166 ret = mstring_concatFree1 (ret, "%");
172 ** some systems don't handle char va_arg correctly, so it must be
173 ** passed as an int here
176 char lc = (char) va_arg (pvar, int);
178 ret = mstring_append (ret, lc);
183 cstring s = va_arg (pvar, cstring);
187 ret = mstring_concatFree (ret, cstring_toCharsSafe
188 (cstring_fill (s, modcode)));
192 if (cstring_isDefined (s))
194 ret = mstring_concatFree1 (ret, cstring_toCharsSafe (s));
202 cstring s = va_arg (pvar, cstring);
206 ret = mstring_concatFree (ret, cstring_toCharsSafe
207 (cstring_fill (s, modcode)));
211 if (cstring_isDefined (s))
213 ret = mstring_concatFree
214 (ret, cstring_toCharsSafe (s));
220 lastint = va_arg (pvar, int);
224 ret = mstring_concatFree1 (ret, "re");
230 ret = mstring_concatFree1 (ret, "s");
234 lastint = va_arg (pvar, int);
235 ret = mstring_concatFree (ret, GETPRINTF ("%d", lastint));
238 ret = mstring_concatFree (ret, GETPRINTF ("%e", va_arg (pvar, double)));
241 ret = mstring_concatFree1 (ret, cstring_toCharsSafe
242 (bool_unparse (va_arg (pvar, bool))));
245 ret = mstring_concatFree (ret, cstring_toCharsSafe
246 (uentry_unparse (va_arg (pvar, uentry))));
249 /* cannot free ctype_unparse */
250 ret = mstring_concatFree1 (ret, cstring_toCharsSafe
251 (ctype_unparse (va_arg (pvar, ctype))));
254 ret = mstring_concatFree (ret, cstring_toCharsSafe
255 (fileloc_unparse (va_arg (pvar, fileloc))));
259 llcontbug (cstring_makeLiteral ("message: bad control flag"));
260 fprintf (stdout, "\tFormat string: %s", ofmt);
262 /*@=loopswitchbreak@*/
266 ret = mstring_append (ret, c);
273 ** cstring_fromChars returns the same storage (exposed)
276 /*@-mustfree@*/ return (cstring_fromChars (ret)); /*@=mustfree@*/