]> andersk Git - splint.git/blob - src/macrocache.c
Fixed all /*@i...@*/ tags (except 1).
[splint.git] / src / macrocache.c
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.
19 **
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
23 */
24 /*
25 ** macrocache.c
26 **
27 ** rep Invariant:
28 **     no two fileloc's may be equal
29 **
30 */
31
32 # include "splintMacros.nf"
33 # include "basic.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 /*:open:*/ /*@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   DPRINTF (("Macrocache add comment: %s / %s", fileloc_unparse (fl), def));
183   macrocache_addGenEntry (s, fl, def, TRUE);
184 }
185
186 static int
187 macrocache_exists (macrocache s, fileloc fl)
188 {
189   int i;
190
191   for (i = 0; i < s->entries; i++)
192     {
193         if (fileloc_equal (s->contents[i]->fl, fl))
194         return (i);
195     }
196
197   return (DNE);
198 }
199
200 /*@only@*/ cstring
201 macrocache_unparse (macrocache m)
202 {
203   cstring s = cstring_undefined;
204   int i;
205
206   for (i = 0; i < m->entries; i++)
207     {
208         fileloc fl = m->contents[i]->fl;
209       cstring def = m->contents[i]->def;
210       bool defined = m->contents[i]->defined;
211       
212       s = message ("%q%q: %s [%s]\n", s, fileloc_unparse (fl), def, 
213                    bool_unparse (defined));
214     }
215   
216   return (s);
217 }
218
219 /*
220 ** needs to call lex by hand...yuk!
221 **
222 ** modifies gc fileloc!
223 */
224
225 /*
226 ** there's gotta be a better way of doing this!
227 */
228
229 static void pushString (/*@only@*/ cstring s)
230 {
231   static fileId mtid = fileId_invalid;
232   long floc;
233
234   if (s_macFile == NULL)
235     {
236       cstring fname;
237       mtid = fileTable_addMacrosFile (context_fileTable ());
238       
239       fname = fileTable_fileName (mtid);
240       s_macFile = fileTable_createMacrosFile (context_fileTable (), fname); /* , "wb+"); ? **/
241       
242       if (s_macFile == NULL)
243         {
244           llcontbug (message ("Cannot open tmp file %s needed to process macro: %s", 
245                               fname, s));
246           cstring_free (s);
247           return;
248         }
249     }
250
251   llassert (s_macFile != NULL);
252
253   /* SunOS, others? don't define SEEK_CUR and SEEK_SET */
254 # ifndef SEEK_CUR 
255 # define SEEK_CUR 1
256 # endif
257   check (fseek (s_macFile, 0, SEEK_CUR) == 0);
258
259   floc = ftell (s_macFile);
260
261   if (cstring_length (s) > 0) {
262     check (fputs (cstring_toCharsSafe (s), s_macFile) != EOF);
263   }
264
265   check (fputc ('\n', s_macFile) == (int) '\n');
266
267 # ifndef SEEK_SET 
268 # define SEEK_SET 0
269 # endif
270   check (fseek (s_macFile, floc, SEEK_SET) == 0);
271
272   yyin = s_macFile;
273   (void) yyrestart (yyin);
274   cstring_free (s);
275 }
276
277 static void
278 macrocache_processMacro (macrocache m, int i)
279 {
280     fileloc fl = m->contents[i]->fl;
281    
282     m->contents[i]->defined = TRUE;
283
284   if (!fileId_equal (currentFile (), fileloc_fileId (fl)))
285     {
286       g_currentloc = fileloc_update (g_currentloc, fl);
287       context_enterMacroFile ();
288     }
289   else
290     {
291       setLine (fileloc_lineno (fl));
292     }
293
294   beginLine ();
295
296   DPRINTF (("Process macro: %s", m->contents[i]->def));
297
298   if (m->contents[i]->scomment)
299     {
300       pushString (message ("%s%s%s", 
301                            cstring_fromChars (BEFORE_COMMENT_MARKER),
302                            m->contents[i]->def,
303                            cstring_fromChars (AFTER_COMMENT_MARKER)));
304       (void) yyparse ();
305     }
306   else
307     {
308       bool insup = context_inSuppressRegion ();
309
310       pushString (message ("%s %s", 
311                            cstring_makeLiteralTemp (PPMRCODE),
312                            m->contents[i]->def));
313       (void) yyparse ();
314
315       if (context_inSuppressRegion () && !insup)
316         {
317           voptgenerror
318             (FLG_SYNTAX, 
319              message ("Macro ends in ignore region: %s", m->contents[i]->def),
320              fl);
321         }
322     }
323   
324   incLine ();  
325   context_exitAllClauses ();
326   context_exitMacroCache ();
327 }
328
329 extern void macrocache_processUndefinedElements (macrocache m)
330 {
331   fileloc lastfl = fileloc_undefined;
332   int i;
333  
334   mcDisable = TRUE;
335
336   DPRINTF (("Processing undefined elements"));
337
338   if (!context_getFlag (FLG_PARTIAL))
339     {
340       for (i = 0; i < m->entries; i++) 
341         {
342             if (m->contents[i]->defined)
343             {
344               ;
345             }
346           else 
347             { 
348               fileloc fl = m->contents[i]->fl; 
349               
350               if (fileloc_isDefined (lastfl) && fileloc_sameFile (fl, lastfl)) 
351                 {
352                   ;
353                 }
354               else
355                 {
356                   if (!fileloc_isLib (fl))
357                     {
358                       displayScan (message ("checking macros %q",
359                                             fileloc_outputFilename (fl)));
360                     }
361                   
362                   lastfl = fl;
363                   cleanupMessages ();
364                 }
365               
366               macrocache_processMacro (m, i);   
367             }
368         }
369     }
370
371   mcDisable = FALSE;
372 }
373
374 extern /*@observer@*/ fileloc macrocache_processFileElements (macrocache m, cstring base)
375 {
376   fileloc lastfl = fileloc_undefined;
377   int i;
378  
379   mcDisable = TRUE;
380
381   for (i = 0; i < m->entries; i++) 
382     {
383         if (m->contents[i]->defined)
384         {
385           ;
386         }
387       else 
388         { 
389           fileloc fl = m->contents[i]->fl;  /* should be dependent! */
390           cstring fb = fileloc_getBase (fl);
391
392           if (cstring_equal (fb, base))
393             {
394               lastfl = fl;
395               macrocache_processMacro (m, i);   
396             }
397         }
398     }
399
400   mcDisable = FALSE;
401   return lastfl;
402 }
403
404 void macrocache_finalize (void)
405 {
406   if (s_macFile != NULL)
407     {
408       check (fileTable_closeFile (context_fileTable (), s_macFile));
409       s_macFile = NULL;
410     }
411 }
This page took 0.072323 seconds and 5 git commands to generate.