Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

macrocache.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** macrocache.c
00026 **
00027 ** rep Invariant:
00028 **     no two fileloc's may be equal
00029 **
00030 */
00031 
00032 # include "lclintMacros.nf"
00033 # include "llbasic.h"
00034 # include "llmain.h"
00035 
00036 /*@constant int MCEBASESIZE;@*/
00037 # define MCEBASESIZE 8
00038 
00039 /*@constant int DNE;@*/
00040 # define DNE -1
00041 
00042 /*
00043 ** Temporary file used for processing macros.
00044 */
00045 
00046 static /*@null@*/ FILE *s_macFile = NULL;
00047 
00048 /*
00049 ** mcDisable is set to TRUE when a macro is being processed, so
00050 ** its contents are not added to the macrocache again, creating
00051 ** a nasty infinite loop.
00052 */
00053 
00054 static bool mcDisable = TRUE;
00055 static void macrocache_grow (macrocache p_s);
00056 static int macrocache_exists (macrocache p_s, fileloc p_fl);
00057 static void macrocache_processMacro (macrocache p_m, int p_i);
00058 
00059 static /*@only@*/ mce
00060   mce_create (/*@only@*/ fileloc fl, /*@only@*/ cstring def, bool comment)
00061 {
00062   mce m = (mce) dmalloc (sizeof (*m));
00063   m->fl = fl;
00064   m->def = def; /*< had a copy here! check this carefully */
00065   m->defined = FALSE;
00066   m->scomment = comment;
00067   return m;
00068 }
00069 
00070 static void mce_free (/*@only@*/ mce m)
00071 {
00072   fileloc_free (m->fl);
00073   cstring_free (m->def);
00074   sfree (m);
00075 }
00076 
00077 /*@only@*/ macrocache
00078 macrocache_create (void)
00079 {
00080   macrocache s = (macrocache) dmalloc (sizeof (*s));
00081 
00082   s->entries = 0;
00083   s->nspace = MCEBASESIZE;
00084   s->contents = (mce *) dmalloc (sizeof (*s->contents) * MCEBASESIZE);
00085 
00086   mcDisable = FALSE;
00087 
00088   return (s);
00089 }
00090 
00091 void
00092 macrocache_free (macrocache s)
00093 {
00094   int i;
00095 
00096   llassert (s_macFile == NULL);
00097 
00098   for (i = 0; i < s->entries; i++)
00099     {
00100       mce_free (s->contents[i]);
00101     }
00102 
00103   sfree (s->contents);
00104   sfree (s);
00105 }
00106 
00107 static void
00108 macrocache_grow (macrocache s)
00109 {
00110   int i;
00111   o_mce *oldcontents = s->contents;
00112 
00113   s->nspace = MCEBASESIZE;
00114   s->contents = (mce *) dmalloc (sizeof (*s->contents) * (s->entries + s->nspace)); 
00115 
00116   for (i = 0; i < s->entries; i++)
00117     {
00118       s->contents[i] = oldcontents[i];
00119     }
00120 
00121   sfree (oldcontents);
00122 }
00123 
00124 static void
00125 macrocache_addGenEntry (macrocache s, /*@only@*/ fileloc fl,
00126                         /*@only@*/ cstring def, bool sup)
00127 {
00128   int i;
00129 
00130   if (mcDisable)
00131     {
00132       fileloc_free (fl);
00133       cstring_free (def);
00134       return;
00135     }
00136 
00137   if ((i = macrocache_exists (s, fl)) != DNE)
00138     {
00139       if (cstring_equal (def, s->contents[i]->def))
00140         {
00141           fileloc_free (fl);
00142           cstring_free (def);
00143 
00144           return;
00145         }
00146       else
00147         {
00148           /*
00149           ** macro definition contained macro that is expanded
00150           ** replace with def
00151           **
00152           ** how do we know which is better??
00153           */
00154           
00155           cstring_free (s->contents[i]->def);
00156           s->contents[i]->def = def;
00157 
00158           fileloc_free (fl);
00159           return;
00160         }
00161     }
00162 
00163   if (s->nspace <= 0) {
00164     macrocache_grow (s);
00165   }
00166 
00167   s->nspace--;
00168   s->contents[s->entries] = mce_create (fl, def, sup);
00169   s->entries++;
00170 }
00171 
00172 void
00173 macrocache_addEntry (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
00174 {
00175   macrocache_addGenEntry (s, fl, def, FALSE);
00176 }
00177 
00178 
00179 void
00180 macrocache_addComment (macrocache s, /*@only@*/ fileloc fl, /*@only@*/ cstring def)
00181 {
00182   macrocache_addGenEntry (s, fl, def, TRUE);
00183 }
00184 
00185 static int
00186 macrocache_exists (macrocache s, fileloc fl)
00187 {
00188   int i;
00189 
00190   for (i = 0; i < s->entries; i++)
00191     {
00192       if (fileloc_equal (s->contents[i]->fl, fl))
00193         return (i);
00194     }
00195 
00196   return (DNE);
00197 }
00198 
00199 /*@only@*/ cstring
00200 macrocache_unparse (macrocache m)
00201 {
00202   cstring s = cstring_undefined;
00203   int i;
00204 
00205   for (i = 0; i < m->entries; i++)
00206     {
00207       fileloc fl = m->contents[i]->fl;
00208       cstring def = m->contents[i]->def;
00209       bool defined = m->contents[i]->defined;
00210       
00211       s = message ("%q%q: %s [%s]\n", s, fileloc_unparse (fl), def, 
00212                    bool_unparse (defined));
00213     }
00214   
00215   return (s);
00216 }
00217 
00218 /*
00219 ** needs to call lex by hand...yuk!
00220 **
00221 ** modifies gc fileloc!
00222 */
00223 
00224 /*
00225 ** there's gotta be a better way of doing this!
00226 */
00227 
00228 static void pushString (/*@only@*/ cstring s)
00229 {
00230   static fileId mtid = fileId_invalid;
00231   long floc;
00232 
00233   if (s_macFile == NULL)
00234     {
00235       cstring fname;
00236       mtid = fileTable_addMacrosFile (context_fileTable ());
00237       
00238       fname = fileName (mtid);
00239       s_macFile = fopen (cstring_toCharsSafe (fname), "wb+");
00240       
00241       if (s_macFile == NULL)
00242         {
00243           llcontbug (message ("Cannot open tmp file %s needed to process macro: %s", 
00244                               fname, s));
00245           cstring_free (s);
00246           return;
00247         }
00248     }
00249 
00250   llassert (s_macFile != NULL);
00251 
00252   /* SunOS, others? don't define SEEK_CUR and SEEK_SET */
00253 # ifndef SEEK_CUR 
00254 # define SEEK_CUR 1
00255 # endif
00256   check (fseek (s_macFile, 0, SEEK_CUR) == 0);
00257 
00258   floc = ftell (s_macFile);
00259 
00260   if (cstring_length (s) > 0) {
00261     check (fputs (cstring_toCharsSafe (s), s_macFile) != EOF);
00262   }
00263 
00264   check (fputc ('\n', s_macFile) == (int) '\n');
00265 
00266 # ifndef SEEK_SET 
00267 # define SEEK_SET 0
00268 # endif
00269   check (fseek (s_macFile, floc, SEEK_SET) == 0);
00270 
00271   yyin = s_macFile;
00272   (void) yyrestart (yyin);
00273   cstring_free (s);
00274 }
00275 
00276 static void
00277 macrocache_processMacro (macrocache m, int i)
00278 {
00279   fileloc fl = m->contents[i]->fl;
00280    
00281   m->contents[i]->defined = TRUE;
00282 
00283   if (!fileId_equal (currentFile (), fileloc_fileId (fl)))
00284     {
00285       g_currentloc = fileloc_update (g_currentloc, fl);
00286       context_enterMacroFile ();
00287     }
00288   else
00289     {
00290       setLine (fileloc_lineno (fl));
00291     }
00292 
00293   beginLine ();
00294 
00295   DPRINTF (("Process macro: %s", m->contents[i]->def));
00296 
00297   if (m->contents[i]->scomment)
00298     {
00299       pushString (message ("%s%s%s", 
00300                            cstring_fromChars (BEFORE_COMMENT_MARKER),
00301                            m->contents[i]->def,
00302                            cstring_fromChars (AFTER_COMMENT_MARKER)));
00303       (void) yyparse ();
00304     }
00305   else
00306     {
00307       bool insup = context_inSuppressRegion ();
00308 
00309       pushString (message ("%s %s", 
00310                            cstring_makeLiteralTemp (PPMRCODE),
00311                            m->contents[i]->def));
00312       (void) yyparse ();
00313 
00314       if (context_inSuppressRegion () && !insup)
00315         {
00316           llerrorlit (FLG_SYNTAX, "Macro ends in ignore region");
00317         }
00318     }
00319   
00320   incLine ();  
00321   context_exitMacroCache ();
00322 }
00323 
00324 extern void macrocache_processUndefinedElements (macrocache m)
00325 {
00326   fileloc lastfl = fileloc_undefined;
00327   int i;
00328  
00329   mcDisable = TRUE;
00330 
00331   DPRINTF (("Processing undefined elements"));
00332 
00333   if (!context_getFlag (FLG_PARTIAL))
00334     {
00335       for (i = 0; i < m->entries; i++) 
00336         {
00337           if (m->contents[i]->defined)
00338             {
00339               ;
00340             }
00341           else 
00342             { 
00343               fileloc fl = m->contents[i]->fl; 
00344               
00345               if (fileloc_isDefined (lastfl) && fileloc_sameFile (fl, lastfl)) 
00346                 {
00347                   ;
00348                 }
00349               else
00350                 {
00351                   if (context_getFlag (FLG_SHOWSCAN))
00352                     {
00353                       if (!fileloc_isLib (fl))
00354                         {
00355                           lldiagmsg (message ("< checking macros %s >", fileloc_filename (fl)));
00356                         }
00357                     }
00358                   
00359                   lastfl = fl;
00360                   cleanupMessages ();
00361                 }
00362               
00363               macrocache_processMacro (m, i);   
00364             }
00365         }
00366     }
00367 
00368   mcDisable = FALSE;
00369 }
00370 
00371 extern /*@observer@*/ fileloc macrocache_processFileElements (macrocache m, cstring base)
00372 {
00373   fileloc lastfl = fileloc_undefined;
00374   int i;
00375  
00376   mcDisable = TRUE;
00377 
00378   for (i = 0; i < m->entries; i++) 
00379     {
00380       if (m->contents[i]->defined)
00381         {
00382           ;
00383         }
00384       else 
00385         { 
00386           fileloc fl = m->contents[i]->fl;  /* should be dependent! */
00387           cstring fb = fileloc_getBase (fl);
00388 
00389           if (cstring_equal (fb, base))
00390             {
00391               lastfl = fl;
00392               macrocache_processMacro (m, i);   
00393             }
00394         }
00395     }
00396 
00397   mcDisable = FALSE;
00398   return lastfl;
00399 }
00400 
00401 void macrocache_finalize (void)
00402 {
00403   if (s_macFile != NULL)
00404     {
00405       check (fclose (s_macFile) == 0);
00406       s_macFile = NULL;
00407     }
00408 }

Generated at Fri Nov 3 18:57:43 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000