]> andersk Git - splint.git/blob - src/message.c
Merged code tree with Dave Evans's version. Many changes to numberous to list....
[splint.git] / src / message.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
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.
10 ** 
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.
15 ** 
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.
19 **
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
23 */
24 /*
25 ** message.c
26 */
27
28 # include "lclintMacros.nf"
29 # include "basic.h"
30  
31 /* patch for linux? solaris? */
32
33 static char strbuf[64];
34 static int modcode;
35
36 typedef enum
37 {
38   XINVALID, 
39   XCHAR, XSTRING, XSTRINGFREE, XTSTRINGFREE, XINT, XFLOAT, XBOOL, XUENTRY,
40   XPERCENT, XCTYPE, XPLURAL, XREPREFIX, XFILELOC
41 } ccode;
42
43 /* char *s, anytype v */
44 /*@notfunction@*/
45 # define GETPRINTF(s,v) (sprintf (strbuf, s, v), mstring_copy (strbuf))
46
47 /*
48 ** returns control code indicated by *c, and
49 ** advances *c to next character.
50 */
51
52 static ccode identify_control (char **s)
53 {
54   char c;
55
56   modcode = 0;
57
58   c = **s;
59   if (c == '\0')
60     {
61       return (XINVALID);
62     }
63
64   if (c >= '0' && c <= '9')
65     {
66       modcode = reader_getInt (s);
67     }
68
69   c = **s;
70
71   (*s)++;
72
73  /*
74  ** handle single-char codes
75  */
76
77   switch (c)
78     {
79     case '%':
80       return (XPERCENT);
81     case 'h':
82     case 'c':
83       return (XCHAR);
84     case 's':
85       return (XSTRING);
86     case 'q':
87       return (XSTRINGFREE);
88     case 'x':
89       return (XSTRINGFREE);
90     case 'd':
91       return (XINT);
92     case 'u':
93       return (XINT); /* unsigned */
94     case 'w':
95       return (XINT); /* unsigned long */
96     case 'f':
97       return (XFLOAT);
98     case 'b':
99       return (XBOOL);
100     case 't':
101       return (XCTYPE);
102     case 'l':
103       return (XFILELOC);
104     case '&':
105       return (XPLURAL);
106     case 'r':
107       return (XREPREFIX);
108     default:
109       llcontbug (message ("Message: invalid code: %h (%s)", c, 
110                           cstring_fromChars (*s)));
111       return (XINVALID);
112     }
113 }
114
115 /*
116 ** message
117 **
118 ** returns a cstring containing the message, as formated by s.
119 **
120 ** the format codes are similar to printf:
121 **
122 **         %s    cstring (don't free after print)
123 **         %q    cstring (free after print)
124 **         %d    int
125 **         %f    float
126 **         %b    bool     (uses bool_unparse)
127 **         %u    uentry
128 **         %l    fileloc
129 **         %t    ctype
130 */
131
132
133 # if USEVARARGS
134 cstring
135 message (fmt, va_alist)
136      char *fmt;
137      va_dcl
138 # else
139 /*@messagelike@*/ /*@only@*/ cstring
140 message (/*@temp@*/ char *fmt, ...)
141 # endif
142 {
143   char c;
144   int lastint = 0;
145   char *ret = mstring_createEmpty ();
146   char *ofmt = fmt;
147   va_list pvar;
148
149 # if USEVARARGS
150   va_start (pvar);
151 # else
152   va_start (pvar, fmt);
153 # endif  
154
155   while ((c = *fmt++) != '\0')
156     {
157       if (c == '%')
158         {
159           /*@-loopswitchbreak@*/
160
161           switch (identify_control (&fmt))
162             {
163             case XPERCENT:
164               {
165                 ret = mstring_concatFree1 (ret, "%");
166                 break;
167               }
168             case XCHAR:
169               {
170                 /*
171                 ** some systems don't handle char va_arg correctly, so it must be
172                 ** passed as an int here
173                 */
174
175                 char lc = (char) va_arg (pvar, int);
176
177                 ret = mstring_append (ret, lc);
178                 break;
179               }
180             case XSTRING:
181               {
182                 cstring s = va_arg (pvar, cstring);
183                 
184                 if (modcode != 0)
185                   {
186                     ret = mstring_concatFree (ret, cstring_toCharsSafe 
187                                           (cstring_fill (s, modcode)));
188                   }
189                 else
190                   {
191                     if (cstring_isDefined (s))
192                       {
193                         ret = mstring_concatFree1 (ret, cstring_toCharsSafe (s));
194                       }
195                   }
196               }
197               break;
198             case XSTRINGFREE:
199             case XTSTRINGFREE:
200               {
201                 cstring s = va_arg (pvar, cstring);
202                 
203                 if (modcode != 0)
204                   {
205                     ret = mstring_concatFree (ret, cstring_toCharsSafe 
206                                               (cstring_fill (s, modcode)));
207                   }
208                 else
209                   {
210                     if (cstring_isDefined (s))
211                       {
212                         ret = mstring_concatFree 
213                           (ret, cstring_toCharsSafe (s));
214                       }
215                   }
216               }
217               break;
218             case XREPREFIX:
219               lastint = va_arg (pvar, int);
220
221               if (lastint != 0)
222                 {
223                   ret = mstring_concatFree1 (ret, "re");
224                 }
225               break;
226             case XPLURAL:
227               if (lastint != 1)
228                 {
229                   ret = mstring_concatFree1 (ret, "s");
230                 }
231               break;
232             case XINT:
233               lastint = va_arg (pvar, int);
234               ret = mstring_concatFree (ret, GETPRINTF ("%d", lastint));
235               break;
236             case XFLOAT:
237               ret = mstring_concatFree (ret, GETPRINTF ("%e", va_arg (pvar, double)));
238               break;
239             case XBOOL:
240               ret = mstring_concatFree1 (ret, cstring_toCharsSafe 
241                                     (bool_unparse (va_arg (pvar, bool))));
242               break;
243             case XUENTRY:
244               ret = mstring_concatFree (ret, cstring_toCharsSafe 
245                                    (uentry_unparse (va_arg (pvar, uentry))));
246               break;
247             case XCTYPE:
248               /* cannot free ctype_unparse */
249               ret = mstring_concatFree1 (ret, cstring_toCharsSafe 
250                                    (ctype_unparse (va_arg (pvar, ctype)))); 
251               break;
252             case XFILELOC:
253               ret = mstring_concatFree (ret, cstring_toCharsSafe 
254                                    (fileloc_unparse (va_arg (pvar, fileloc))));
255               break;
256             case XINVALID:
257             default:
258               llcontbug (cstring_makeLiteral ("message: bad control flag"));
259               fprintf (stdout, "\tFormat string: %s", ofmt);
260             }
261           /*@=loopswitchbreak@*/
262         }
263       else
264         {
265           ret = mstring_append (ret, c);
266         }
267     }
268
269   va_end (pvar);
270
271   /*
272   ** cstring_fromChars returns the same storage (exposed)
273   */
274
275   /*@-mustfree@*/ return (cstring_fromChars (ret)); /*@=mustfree@*/
276 }
This page took 0.123683 seconds and 5 git commands to generate.