Some consistency changes to library & headers flags.
[splint-patched.git] / src / macrocache.c
blob6865f8ed7349b90c147de619f050d2721ed42325
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 ** macrocache.c
27 ** rep Invariant:
28 ** no two fileloc's may be equal
32 # include "splintMacros.nf"
33 # include "basic.h"
34 # include "cscanner.h"
35 # include "cgrammar.h"
37 /*@constant int MCEBASESIZE;@*/
38 # define MCEBASESIZE 8
40 /*@constant int DNE;@*/
41 # define DNE -1
44 ** Temporary file used for processing macros.
47 static /*:open:*/ /*@null@*/ FILE *s_macFile = NULL;
50 ** mcDisable is set to TRUE when a macro is being processed, so
51 ** its contents are not added to the macrocache again, creating
52 ** a nasty infinite loop.
55 static bool mcDisable = TRUE;
56 static void macrocache_grow (macrocache p_s);
57 static int macrocache_exists (macrocache p_s, fileloc p_fl);
58 static void macrocache_processMacro (macrocache p_m, int p_i);
60 static /*@only@*/ mce
61 mce_create (/*@only@*/ fileloc fl, /*@only@*/ cstring def, bool comment)
63 mce m = (mce) dmalloc (sizeof (*m));
64 m->fl = fl;
65 m->def = def; /*< had a copy here! check this carefully */
66 m->defined = FALSE;
67 m->scomment = comment;
68 return m;
71 static void mce_free (/*@only@*/ mce m)
73 fileloc_free (m->fl);
74 cstring_free (m->def);
75 sfree (m);
78 /*@only@*/ macrocache
79 macrocache_create (void)
81 macrocache s = (macrocache) dmalloc (sizeof (*s));
83 s->entries = 0;
84 s->nspace = MCEBASESIZE;
85 s->contents = (mce *) dmalloc (sizeof (*s->contents) * MCEBASESIZE);
87 mcDisable = FALSE;
89 return (s);
92 void
93 macrocache_free (macrocache s)
95 int i;
97 llassert (s_macFile == NULL);
99 for (i = 0; i < s->entries; i++)
101 mce_free (s->contents[i]);
104 sfree (s->contents);
105 sfree (s);
108 static void
109 macrocache_grow (macrocache s)
111 int i;
112 o_mce *oldcontents = s->contents;
114 s->nspace = MCEBASESIZE;
115 s->contents = (mce *) dmalloc (sizeof (*s->contents) * (s->entries + s->nspace));
117 for (i = 0; i < s->entries; i++)
119 s->contents[i] = oldcontents[i];
122 sfree (oldcontents);
125 static void
126 macrocache_addGenEntry (macrocache s, /*@only@*/ fileloc fl,
127 /*@only@*/ cstring def, bool sup)
129 int i;
131 if (mcDisable)
133 fileloc_free (fl);
134 cstring_free (def);
135 return;
138 if ((i = macrocache_exists (s, fl)) != DNE)
140 if (cstring_equal (def, s->contents[i]->def))
142 fileloc_free (fl);
143 cstring_free (def);
145 return;
147 else
150 ** macro definition contained macro that is expanded
151 ** replace with def
153 ** how do we know which is better??
156 cstring_free (s->contents[i]->def);
157 s->contents[i]->def = def;
159 fileloc_free (fl);
160 return;
164 if (s->nspace <= 0) {
165 macrocache_grow (s);
168 s->nspace--;
169 s->contents[s->entries] = mce_create (fl, def, sup);
170 s->entries++;
173 void
174 macrocache_addEntry (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
176 macrocache_addGenEntry (s, fl, def, FALSE);
180 void
181 macrocache_addComment (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
183 DPRINTF (("Macrocache add comment: %s / %s", fileloc_unparse (fl), def));
184 macrocache_addGenEntry (s, fl, def, TRUE);
187 static int
188 macrocache_exists (macrocache s, fileloc fl)
190 int i;
192 for (i = 0; i < s->entries; i++)
194 if (fileloc_equal (s->contents[i]->fl, fl))
195 return (i);
198 return (DNE);
201 # ifdef DEADCODE
202 /*@only@*/ cstring
203 macrocache_unparse (macrocache m)
205 cstring s = cstring_undefined;
206 int i;
208 for (i = 0; i < m->entries; i++)
210 fileloc fl = m->contents[i]->fl;
211 cstring def = m->contents[i]->def;
212 bool defined = m->contents[i]->defined;
214 s = message ("%q%q: %s [%s]\n", s, fileloc_unparse (fl), def,
215 bool_unparse (defined));
218 return (s);
220 # endif /* DEADCODE */
223 ** needs to call lex by hand...yuk!
225 ** modifies gc fileloc!
229 ** there's gotta be a better way of doing this!
232 static void pushString (/*@only@*/ cstring s)
234 static fileId mtid = fileId_invalid;
235 long floc;
237 if (s_macFile == NULL)
239 cstring fname;
240 mtid = fileTable_addTempFile (context_fileTable (), FILE_MACROS, fileId_invalid);
242 fname = fileTable_fileName (mtid);
243 s_macFile = fileTable_createTempFile (context_fileTable (), fname, TRUE);
245 if (s_macFile == NULL)
247 llfatalerror (message ("Cannot open tmp file %s needed to process macro: %s",
248 fname, s));
249 cstring_free (s);
250 return;
254 llassert (s_macFile != NULL);
256 check (fseek (s_macFile, 0, SEEK_CUR) == 0);
258 floc = ftell (s_macFile);
260 if (cstring_length (s) > 0) {
261 check (fputs (cstring_toCharsSafe (s), s_macFile) != EOF);
264 check (fputc ('\n', s_macFile) == (int) '\n');
266 check (fseek (s_macFile, floc, SEEK_SET) == 0);
268 c_in = s_macFile;
269 (void) c_restart (c_in);
270 cstring_free (s);
273 static void
274 macrocache_processMacro (macrocache m, int i)
276 fileloc fl = m->contents[i]->fl;
278 m->contents[i]->defined = TRUE;
280 if (!fileId_equal (currentFile (), fileloc_fileId (fl)))
282 g_currentloc = fileloc_update (g_currentloc, fl);
283 context_enterMacroFile ();
285 else
287 setLine (fileloc_lineno (fl));
290 beginLine ();
292 DPRINTF (("Process macro: %s", m->contents[i]->def));
294 if (m->contents[i]->scomment)
296 pushString (message ("%s%s%s",
297 cstring_fromChars (BEFORE_COMMENT_MARKER),
298 m->contents[i]->def,
299 cstring_fromChars (AFTER_COMMENT_MARKER)));
300 (void) c_parse ();
302 else
304 bool insup = context_inSuppressRegion ();
306 pushString (message ("%s %s",
307 cstring_makeLiteralTemp (PPMRCODE),
308 m->contents[i]->def));
309 (void) c_parse ();
311 if (context_inSuppressRegion () && !insup)
313 voptgenerror
314 (FLG_SYNTAX,
315 message ("Macro ends in ignore region: %s", m->contents[i]->def),
316 fl);
320 incLine ();
321 context_exitAllClauses ();
322 context_exitMacroCache ();
325 extern void macrocache_processUndefinedElements (macrocache m)
327 fileloc lastfl = fileloc_undefined;
328 int i;
330 mcDisable = TRUE;
332 DPRINTF (("Processing undefined elements"));
334 if (!context_getFlag (FLG_PARTIAL))
336 for (i = 0; i < m->entries; i++)
338 if (m->contents[i]->defined)
342 else
344 fileloc fl = m->contents[i]->fl;
346 if (fileloc_isDefined (lastfl) && fileloc_sameFile (fl, lastfl))
350 else
352 if (!fileloc_isLib (fl))
354 displayScan (message ("checking macros %q",
355 fileloc_outputFilename (fl)));
358 lastfl = fl;
359 cleanupMessages ();
362 macrocache_processMacro (m, i);
367 mcDisable = FALSE;
370 extern /*@observer@*/ fileloc macrocache_processFileElements (macrocache m, cstring base)
372 fileloc lastfl = fileloc_undefined;
373 int i;
375 mcDisable = TRUE;
377 for (i = 0; i < m->entries; i++)
379 if (m->contents[i]->defined)
383 else
385 fileloc fl = m->contents[i]->fl; /* should be dependent! */
386 cstring fb = fileloc_getBase (fl);
388 if (cstring_equal (fb, base))
390 lastfl = fl;
391 macrocache_processMacro (m, i);
396 mcDisable = FALSE;
397 return lastfl;
400 void macrocache_finalize (void)
402 if (s_macFile != NULL)
404 check (fileTable_closeFile (context_fileTable (), s_macFile));
405 s_macFile = NULL;