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