]> andersk Git - splint.git/blame - src/macrocache.c
Readded files.
[splint.git] / src / macrocache.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** macrocache.c
26**
27** rep Invariant:
28** no two fileloc's may be equal
29**
30*/
31
32# include "lclintMacros.nf"
33# include "llbasic.h"
34# include "llmain.h"
35
36/*@constant int MCEBASESIZE;@*/
37# define MCEBASESIZE 8
38
39/*@constant int DNE;@*/
40# define DNE -1
41
42/*
43** Temporary file used for processing macros.
44*/
45
46static /*@null@*/ FILE *s_macFile = NULL;
47
48/*
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.
52*/
53
54static bool mcDisable = TRUE;
55static void macrocache_grow (macrocache p_s);
56static int macrocache_exists (macrocache p_s, fileloc p_fl);
57static void macrocache_processMacro (macrocache p_m, int p_i);
58
59static /*@only@*/ mce
60 mce_create (/*@only@*/ fileloc fl, /*@only@*/ cstring def, bool comment)
61{
62 mce m = (mce) dmalloc (sizeof (*m));
63 m->fl = fl;
64 m->def = def; /*< had a copy here! check this carefully */
65 m->defined = FALSE;
66 m->scomment = comment;
67 return m;
68}
69
70static void mce_free (/*@only@*/ mce m)
71{
72 fileloc_free (m->fl);
73 cstring_free (m->def);
74 sfree (m);
75}
76
77/*@only@*/ macrocache
78macrocache_create (void)
79{
80 macrocache s = (macrocache) dmalloc (sizeof (*s));
81
82 s->entries = 0;
83 s->nspace = MCEBASESIZE;
84 s->contents = (mce *) dmalloc (sizeof (*s->contents) * MCEBASESIZE);
85
86 mcDisable = FALSE;
87
88 return (s);
89}
90
91void
92macrocache_free (macrocache s)
93{
94 int i;
95
96 llassert (s_macFile == NULL);
97
98 for (i = 0; i < s->entries; i++)
99 {
100 mce_free (s->contents[i]);
101 }
102
103 sfree (s->contents);
104 sfree (s);
105}
106
107static void
108macrocache_grow (macrocache s)
109{
110 int i;
111 o_mce *oldcontents = s->contents;
112
113 s->nspace = MCEBASESIZE;
114 s->contents = (mce *) dmalloc (sizeof (*s->contents) * (s->entries + s->nspace));
115
116 for (i = 0; i < s->entries; i++)
117 {
118 s->contents[i] = oldcontents[i];
119 }
120
121 sfree (oldcontents);
122}
123
124static void
125macrocache_addGenEntry (macrocache s, /*@only@*/ fileloc fl,
126 /*@only@*/ cstring def, bool sup)
127{
128 int i;
129
130 if (mcDisable)
131 {
132 fileloc_free (fl);
133 cstring_free (def);
134 return;
135 }
136
137 if ((i = macrocache_exists (s, fl)) != DNE)
138 {
139 if (cstring_equal (def, s->contents[i]->def))
140 {
141 fileloc_free (fl);
142 cstring_free (def);
143
144 return;
145 }
146 else
147 {
148 /*
149 ** macro definition contained macro that is expanded
150 ** replace with def
151 **
152 ** how do we know which is better??
153 */
154
155 cstring_free (s->contents[i]->def);
156 s->contents[i]->def = def;
157
158 fileloc_free (fl);
159 return;
160 }
161 }
162
163 if (s->nspace <= 0) {
164 macrocache_grow (s);
165 }
166
167 s->nspace--;
168 s->contents[s->entries] = mce_create (fl, def, sup);
169 s->entries++;
170}
171
172void
173macrocache_addEntry (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
174{
175 macrocache_addGenEntry (s, fl, def, FALSE);
176}
177
178
179void
180macrocache_addComment (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
181{
182 macrocache_addGenEntry (s, fl, def, TRUE);
183}
184
185static int
186macrocache_exists (macrocache s, fileloc fl)
187{
188 int i;
189
190 for (i = 0; i < s->entries; i++)
191 {
192 if (fileloc_equal (s->contents[i]->fl, fl))
193 return (i);
194 }
195
196 return (DNE);
197}
198
199/*@only@*/ cstring
200macrocache_unparse (macrocache m)
201{
202 cstring s = cstring_undefined;
203 int i;
204
205 for (i = 0; i < m->entries; i++)
206 {
207 fileloc fl = m->contents[i]->fl;
208 cstring def = m->contents[i]->def;
209 bool defined = m->contents[i]->defined;
210
211 s = message ("%q%q: %s [%s]\n", s, fileloc_unparse (fl), def,
212 bool_unparse (defined));
213 }
214
215 return (s);
216}
217
218/*
219** needs to call lex by hand...yuk!
220**
221** modifies gc fileloc!
222*/
223
224/*
225** there's gotta be a better way of doing this!
226*/
227
228static void pushString (/*@only@*/ cstring s)
229{
230 static fileId mtid = fileId_invalid;
231 long floc;
232
233 if (s_macFile == NULL)
234 {
235 cstring fname;
236 mtid = fileTable_addMacrosFile (context_fileTable ());
237
238 fname = fileName (mtid);
239 s_macFile = fopen (cstring_toCharsSafe (fname), "wb+");
240
241 if (s_macFile == NULL)
242 {
243 llcontbug (message ("Cannot open tmp file %s needed to process macro: %s",
244 fname, s));
245 cstring_free (s);
246 return;
247 }
248 }
249
250 llassert (s_macFile != NULL);
251
252 /* SunOS, others? don't define SEEK_CUR and SEEK_SET */
253# ifndef SEEK_CUR
254# define SEEK_CUR 1
255# endif
256 check (fseek (s_macFile, 0, SEEK_CUR) == 0);
257
258 floc = ftell (s_macFile);
259
260 if (cstring_length (s) > 0) {
261 check (fputs (cstring_toCharsSafe (s), s_macFile) != EOF);
262 }
263
264 check (fputc ('\n', s_macFile) == (int) '\n');
265
266# ifndef SEEK_SET
267# define SEEK_SET 0
268# endif
269 check (fseek (s_macFile, floc, SEEK_SET) == 0);
270
271 yyin = s_macFile;
272 (void) yyrestart (yyin);
273 cstring_free (s);
274}
275
276static void
277macrocache_processMacro (macrocache m, int i)
278{
279 fileloc fl = m->contents[i]->fl;
280
281 m->contents[i]->defined = TRUE;
282
283 if (!fileId_equal (currentFile (), fileloc_fileId (fl)))
284 {
285 g_currentloc = fileloc_update (g_currentloc, fl);
286 context_enterMacroFile ();
287 }
288 else
289 {
290 setLine (fileloc_lineno (fl));
291 }
292
293 beginLine ();
294
295 DPRINTF (("Process macro: %s", m->contents[i]->def));
296
297 if (m->contents[i]->scomment)
298 {
299 pushString (message ("%s%s%s",
300 cstring_fromChars (BEFORE_COMMENT_MARKER),
301 m->contents[i]->def,
302 cstring_fromChars (AFTER_COMMENT_MARKER)));
303 (void) yyparse ();
304 }
305 else
306 {
307 bool insup = context_inSuppressRegion ();
308
309 pushString (message ("%s %s",
310 cstring_makeLiteralTemp (PPMRCODE),
311 m->contents[i]->def));
312 (void) yyparse ();
313
314 if (context_inSuppressRegion () && !insup)
315 {
316 llerrorlit (FLG_SYNTAX, "Macro ends in ignore region");
317 }
318 }
319
320 incLine ();
321 context_exitMacroCache ();
322}
323
324extern void macrocache_processUndefinedElements (macrocache m)
325{
326 fileloc lastfl = fileloc_undefined;
327 int i;
328
329 mcDisable = TRUE;
330
331 DPRINTF (("Processing undefined elements"));
332
333 if (!context_getFlag (FLG_PARTIAL))
334 {
335 for (i = 0; i < m->entries; i++)
336 {
337 if (m->contents[i]->defined)
338 {
339 ;
340 }
341 else
342 {
343 fileloc fl = m->contents[i]->fl;
344
345 if (fileloc_isDefined (lastfl) && fileloc_sameFile (fl, lastfl))
346 {
347 ;
348 }
349 else
350 {
351 if (context_getFlag (FLG_SHOWSCAN))
352 {
353 if (!fileloc_isLib (fl))
354 {
355 lldiagmsg (message ("< checking macros %s >", fileloc_filename (fl)));
356 }
357 }
358
359 lastfl = fl;
360 cleanupMessages ();
361 }
362
363 macrocache_processMacro (m, i);
364 }
365 }
366 }
367
368 mcDisable = FALSE;
369}
370
371extern /*@observer@*/ fileloc macrocache_processFileElements (macrocache m, cstring base)
372{
373 fileloc lastfl = fileloc_undefined;
374 int i;
375
376 mcDisable = TRUE;
377
378 for (i = 0; i < m->entries; i++)
379 {
380 if (m->contents[i]->defined)
381 {
382 ;
383 }
384 else
385 {
386 fileloc fl = m->contents[i]->fl; /* should be dependent! */
387 cstring fb = fileloc_getBase (fl);
388
389 if (cstring_equal (fb, base))
390 {
391 lastfl = fl;
392 macrocache_processMacro (m, i);
393 }
394 }
395 }
396
397 mcDisable = FALSE;
398 return lastfl;
399}
400
401void macrocache_finalize (void)
402{
403 if (s_macFile != NULL)
404 {
405 check (fclose (s_macFile) == 0);
406 s_macFile = NULL;
407 }
408}
This page took 0.136191 seconds and 5 git commands to generate.