2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 ** no two fileloc's may be equal
32 # include "splintMacros.nf"
36 /*@constant int MCEBASESIZE;@*/
37 # define MCEBASESIZE 8
39 /*@constant int DNE;@*/
43 ** Temporary file used for processing macros.
46 static /*:open:*/ /*@null@*/ FILE *s_macFile = NULL;
49 ** mcDisable is set to TRUE when a macro is being processed, so
50 ** its contents are not added to the macrocache again, creating
51 ** a nasty infinite loop.
54 static bool mcDisable = TRUE;
55 static void macrocache_grow (macrocache p_s);
56 static int macrocache_exists (macrocache p_s, fileloc p_fl);
57 static void macrocache_processMacro (macrocache p_m, int p_i);
60 mce_create (/*@only@*/ fileloc fl, /*@only@*/ cstring def, bool comment)
62 mce m = (mce) dmalloc (sizeof (*m));
64 m->def = def; /*< had a copy here! check this carefully */
66 m->scomment = comment;
70 static void mce_free (/*@only@*/ mce m)
73 cstring_free (m->def);
78 macrocache_create (void)
80 macrocache s = (macrocache) dmalloc (sizeof (*s));
83 s->nspace = MCEBASESIZE;
84 s->contents = (mce *) dmalloc (sizeof (*s->contents) * MCEBASESIZE);
92 macrocache_free (macrocache s)
96 llassert (s_macFile == NULL);
98 for (i = 0; i < s->entries; i++)
100 /*drl bee: si*/ mce_free (s->contents[i]);
108 macrocache_grow (macrocache s)
111 o_mce *oldcontents = s->contents;
113 s->nspace = MCEBASESIZE;
114 s->contents = (mce *) dmalloc (sizeof (*s->contents) * (s->entries + s->nspace));
116 for (i = 0; i < s->entries; i++)
118 /*drl bee: dm*/ /*drl bee: si*/ s->contents[i] = oldcontents[i];
125 macrocache_addGenEntry (macrocache s, /*@only@*/ fileloc fl,
126 /*@only@*/ cstring def, bool sup)
137 if ((i = macrocache_exists (s, fl)) != DNE)
139 /*drl bee: si*/ if (cstring_equal (def, s->contents[i]->def))
149 ** macro definition contained macro that is expanded
152 ** how do we know which is better??
155 cstring_free (s->contents[i]->def);
156 /*drl bee: si*/ s->contents[i]->def = def;
163 if (s->nspace <= 0) {
168 /*drl bee: si*/ s->contents[s->entries] = mce_create (fl, def, sup);
173 macrocache_addEntry (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
175 macrocache_addGenEntry (s, fl, def, FALSE);
180 macrocache_addComment (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
182 DPRINTF (("Macrocache add comment: %s / %s", fileloc_unparse (fl), def));
183 macrocache_addGenEntry (s, fl, def, TRUE);
187 macrocache_exists (macrocache s, fileloc fl)
191 for (i = 0; i < s->entries; i++)
193 /*drl bee: si*/ if (fileloc_equal (s->contents[i]->fl, fl))
201 macrocache_unparse (macrocache m)
203 cstring s = cstring_undefined;
206 for (i = 0; i < m->entries; i++)
208 /*drl bee: si*/ fileloc fl = m->contents[i]->fl;
209 cstring def = m->contents[i]->def;
210 bool defined = m->contents[i]->defined;
212 s = message ("%q%q: %s [%s]\n", s, fileloc_unparse (fl), def,
213 bool_unparse (defined));
220 ** needs to call lex by hand...yuk!
222 ** modifies gc fileloc!
226 ** there's gotta be a better way of doing this!
229 static void pushString (/*@only@*/ cstring s)
231 static fileId mtid = fileId_invalid;
234 if (s_macFile == NULL)
237 mtid = fileTable_addMacrosFile (context_fileTable ());
239 fname = fileTable_fileName (mtid);
240 s_macFile = fileTable_openFile (context_fileTable (), fname, "wb+");
242 if (s_macFile == NULL)
244 llcontbug (message ("Cannot open tmp file %s needed to process macro: %s",
251 llassert (s_macFile != NULL);
253 /* SunOS, others? don't define SEEK_CUR and SEEK_SET */
257 check (fseek (s_macFile, 0, SEEK_CUR) == 0);
259 floc = ftell (s_macFile);
261 if (cstring_length (s) > 0) {
262 check (fputs (cstring_toCharsSafe (s), s_macFile) != EOF);
265 check (fputc ('\n', s_macFile) == (int) '\n');
270 check (fseek (s_macFile, floc, SEEK_SET) == 0);
273 (void) yyrestart (yyin);
278 macrocache_processMacro (macrocache m, int i)
280 /*drl bee: si*/ fileloc fl = m->contents[i]->fl;
282 /*drl bee: si*/ m->contents[i]->defined = TRUE;
284 if (!fileId_equal (currentFile (), fileloc_fileId (fl)))
286 g_currentloc = fileloc_update (g_currentloc, fl);
287 context_enterMacroFile ();
291 setLine (fileloc_lineno (fl));
296 DPRINTF (("Process macro: %s", m->contents[i]->def));
298 if (m->contents[i]->scomment)
300 pushString (message ("%s%s%s",
301 cstring_fromChars (BEFORE_COMMENT_MARKER),
303 cstring_fromChars (AFTER_COMMENT_MARKER)));
308 bool insup = context_inSuppressRegion ();
310 pushString (message ("%s %s",
311 cstring_makeLiteralTemp (PPMRCODE),
312 m->contents[i]->def));
315 if (context_inSuppressRegion () && !insup)
319 message ("Macro ends in ignore region: %s", m->contents[i]->def),
325 context_exitAllClauses ();
326 context_exitMacroCache ();
329 extern void macrocache_processUndefinedElements (macrocache m)
331 fileloc lastfl = fileloc_undefined;
336 DPRINTF (("Processing undefined elements"));
338 if (!context_getFlag (FLG_PARTIAL))
340 for (i = 0; i < m->entries; i++)
342 /*drl bee: si*/ if (m->contents[i]->defined)
348 fileloc fl = m->contents[i]->fl;
350 if (fileloc_isDefined (lastfl) && fileloc_sameFile (fl, lastfl))
356 if (!fileloc_isLib (fl))
358 displayScan (message ("checking macros %q",
359 fileloc_outputFilename (fl)));
366 macrocache_processMacro (m, i);
374 extern /*@observer@*/ fileloc macrocache_processFileElements (macrocache m, cstring base)
376 fileloc lastfl = fileloc_undefined;
381 for (i = 0; i < m->entries; i++)
383 /*drl bee: si*/ if (m->contents[i]->defined)
389 fileloc fl = m->contents[i]->fl; /* should be dependent! */
390 cstring fb = fileloc_getBase (fl);
392 if (cstring_equal (fb, base))
395 macrocache_processMacro (m, i);
404 void macrocache_finalize (void)
406 if (s_macFile != NULL)
408 check (fileTable_closeFile (context_fileTable (), s_macFile));