]> andersk Git - splint.git/blob - src/macrocache.c
Initial revision
[splint.git] / src / macrocache.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 ** 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
46 static /*@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
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);
58
59 static /*@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
70 static 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
78 macrocache_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
91 void
92 macrocache_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
107 static void
108 macrocache_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
124 static void
125 macrocache_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
172 void
173 macrocache_addEntry (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
174 {
175   macrocache_addGenEntry (s, fl, def, FALSE);
176 }
177
178
179 void
180 macrocache_addComment (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
181 {
182   macrocache_addGenEntry (s, fl, def, TRUE);
183 }
184
185 static int
186 macrocache_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
200 macrocache_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
228 static 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
276 static void
277 macrocache_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
324 extern 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
371 extern /*@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
401 void 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.088488 seconds and 5 git commands to generate.