]> andersk Git - splint.git/blame - src/message.c
Updating for cert move
[splint.git] / src / message.c
CommitLineData
616915dd 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
33static char strbuf[64];
34static int modcode;
35
36typedef 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
52static 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
135cstring
136message (fmt, va_alist)
137 char *fmt;
138 va_dcl
139# else
140/*@messagelike@*/ /*@only@*/ cstring
141message (/*@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.110966 seconds and 5 git commands to generate.