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

cpphash.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 ** cpphash.c
00026 **
00027 ** Pre-processor hash table.  Derived from gnu cpp.
00028 */
00029 
00030 /* Part of CPP library.  (Macro hash table support.)
00031    Copyright (C) 1986, 87, 89, 92-95, 1996 Free Software Foundation, Inc.
00032    Written by Per Bothner, 1994.
00033    Based on CCCP program by by Paul Rubin, June 1986
00034    Adapted to ANSI C, Richard Stallman, Jan 1987
00035 
00036 This program is free software; you can redistribute it and/or modify it
00037 under the terms of the GNU General Public License as published by the
00038 Free Software Foundation; either version 2, or (at your option) any
00039 later version.
00040 
00041 This program is distributed in the hope that it will be useful,
00042 but WITHOUT ANY WARRANTY; without even the implied warranty of
00043 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00044 GNU General Public License for more details.
00045 
00046 You should have received a copy of the GNU General Public License
00047 along with this program; if not, write to the Free Software
00048 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00049 
00050  In other words, you are welcome to use, share and improve this program.
00051  You are forbidden to forbid anyone else to use, share and improve
00052  what you give them.   Help stamp out software-hoarding!  */
00053 
00054 # include "lclintMacros.nf"
00055 # include "llbasic.h"
00056 # include <string.h>
00057 # include "cpp.h"
00058 # include "cpplib.h"
00059 # include "cpphash.h"
00060 
00061 typedef /*@only@*/ HASHNODE *o_HASHNODE;
00062 
00063 static o_HASHNODE hashtab[CPP_HASHSIZE]; 
00064 static o_HASHNODE ohashtab[CPP_HASHSIZE];
00065 
00066 static void HashNode_delete (/*@null@*/ /*@only@*/ HASHNODE *);
00067 
00068 /* p_prev need not be defined, but isn't defined by HashNode_copy */
00069 
00070 /*@function static unsigned int hashStep (unsigned, char) modifies nothing ; @*/
00071 # define hashStep(old, c) (((old) << 2) + (unsigned int) (c))
00072 
00073 /*@function static unsigned int makePositive (unsigned int) modifies nothing ; @*/
00074 # define makePositive(v) ((v) & 0x7fffffff) /* make number positive */
00075 
00076 static /*@null@*/ HASHNODE *
00077    HashNode_copy (/*@null@*/ HASHNODE *, 
00078                   /*@dependent@*/ HASHNODE **p_hdr, 
00079                   /*@dependent@*/ /*@null@*/ /*@special@*/ HASHNODE *p_prev) 
00080      /*@*/ ;
00081 
00082 void cppReader_saveHashtab ()
00083 {
00084   int i;
00085 
00086   for (i = 0; i < CPP_HASHSIZE; i++) 
00087     {
00088       ohashtab[i] = HashNode_copy (hashtab[i], &ohashtab[i], NULL);
00089     }
00090 }
00091 
00092 void cppReader_restoreHashtab ()
00093 {
00094   int i;
00095 
00096   for (i = 0; i < CPP_HASHSIZE; i++) {
00097     /* HashNode_delete (hashtab[i]); */
00098     hashtab[i] = HashNode_copy (ohashtab[i], &hashtab[i], NULL);
00099   }  
00100 }
00101 
00102 static void HashNode_delete (/*@only@*/ /*@null@*/ HASHNODE *node) 
00103 {
00104   if (node == NULL) 
00105     {
00106       ;
00107     } 
00108   else 
00109     {
00110       HashNode_delete (node->next);
00111       
00112       if (node->type == T_MACRO)
00113         {
00114           DEFINITION *d = node->value.defn;
00115           struct reflist *ap, *nextap;
00116           
00117           for (ap = d->pattern; ap != NULL; ap = nextap)
00118             {
00119               nextap = ap->next;
00120               sfree (ap);
00121             }
00122           
00123           if (d->nargs >= 0) 
00124             {
00125               sfree (d->args.argnames);
00126             }
00127           
00128           sfree (d);
00129         }
00130       
00131       cstring_free (node->name);
00132       sfree (node); 
00133     }
00134 }
00135 
00136 /*@null@*/ HASHNODE *HashNode_copy (HASHNODE *node, HASHNODE **hdr, 
00137                                     /*@dependent@*/ HASHNODE *prev)
00138 {
00139   if (node == NULL) 
00140     {
00141       return NULL;
00142     } 
00143   else 
00144     {
00145       HASHNODE *res = dmalloc (sizeof (*res));
00146       
00147       res->next = HashNode_copy (node->next, hdr, res);
00148       res->prev = prev;
00149       
00150       res->bucket_hdr = hdr;
00151       res->type = node->type;
00152       res->length = node->length;
00153       res->name = cstring_copy (node->name);
00154       
00155       if (node->type == T_MACRO)
00156         {
00157           DEFINITION *d = node->value.defn;
00158           DEFINITION *nd = dmalloc (sizeof (*nd));
00159           
00160           res->value.defn = nd;
00161           nd->nargs = d->nargs;
00162           
00163           nd->length = d->length;
00164           nd->predefined = d->predefined;
00165           nd->expansion = d->expansion; 
00166           nd->line = d->line;
00167           nd->file = d->file; 
00168           
00169           if (d->pattern != NULL) 
00170             {
00171               struct reflist *ap, *nextap;
00172               struct reflist **last = &nd->pattern;
00173               
00174               for (ap = d->pattern; ap != NULL; ap = nextap) 
00175                 {
00176                   struct reflist *npattern = dmalloc (sizeof (*(nd->pattern)));
00177                   
00178                   nextap = ap->next;
00179                   
00180                   if (ap == d->pattern) 
00181                     {
00182                       *last = npattern;
00183                       /*@-branchstate@*/ 
00184                     } /*@=branchstate@*/ /* npattern is propagated through loop */
00185                   
00186                   last = &(npattern->next);
00187                   npattern->next = NULL; /* will get filled in */
00188                   npattern->stringify = d->pattern->stringify;
00189                   npattern->raw_before = d->pattern->raw_before;
00190                   npattern->raw_after = d->pattern->raw_after;
00191                   npattern->rest_args = d->pattern->rest_args;
00192                   npattern->argno = d->pattern->argno;
00193                   /*@-mustfree@*/ 
00194                 }
00195               /*@=mustfree@*/
00196             } 
00197           else 
00198             {
00199               nd->pattern = NULL;
00200             }
00201           
00202           if (d->nargs >= 0) 
00203             {
00204               llassert (d->args.argnames != NULL);
00205               
00206               nd->args.argnames = mstring_copy (d->args.argnames);
00207             } 
00208           else 
00209             {
00210               /*
00211               ** This fix found by:
00212               **
00213               **    Date: Mon, 31 May 1999 15:10:50 +0900 (JST)
00214               **    From: "N.Komazaki" <koma@focs.sei.co.jp>
00215               */
00216 
00218               nd->args.argnames = mstring_createEmpty ();
00219             }
00220         } 
00221       else 
00222         {
00223           if (node->type == T_CONST) 
00224             {
00225               res->value.ival = node->value.ival;
00226             } 
00227           else if (node->type == T_PCSTRING) 
00228             {
00229               res->value.cpval = mstring_copy (node->value.cpval);
00230                   llassert (res->value.cpval != NULL);
00231             } 
00232           else 
00233             {
00234               res->value = node->value;
00235             }
00236         }
00237       
00238       /*@-uniondef@*/ /*@-compdef@*/ /* res->prev is not defined */
00239       return res;
00240       /*@=uniondef@*/ /*@=compdef@*/
00241     }
00242 }
00243 
00244 /* Return hash function on name.  must be compatible with the one
00245    computed a step at a time, elsewhere  */
00246 
00247 int
00248 hashf (const char *name, int len, int hashsize)
00249 {
00250   unsigned int r = 0;
00251 
00252   while (len-- != 0)
00253     {
00254       r = hashStep (r, *name++);
00255     }
00256 
00257   return (int) (makePositive (r) % hashsize);
00258 }
00259 
00260 /*
00261 ** Find the most recent hash node for name name (ending with first
00262 ** non-identifier char) cppReader_installed by install
00263 **
00264 ** If LEN is >= 0, it is the length of the name.
00265 ** Otherwise, compute the length by scanning the entire name.
00266 **
00267 ** If HASH is >= 0, it is the precomputed hash code.
00268 ** Otherwise, compute the hash code.  
00269 */
00270 
00271 /*@null@*/ HASHNODE *cppReader_lookup (char *name, int len, int hash)
00272 {
00273   const char *bp;
00274   HASHNODE *bucket;
00275 
00276   if (len < 0)
00277     {
00278       for (bp = name; isIdentifierChar (*bp); bp++) 
00279         {
00280           ;
00281         }
00282 
00283       len = bp - name;
00284     }
00285 
00286   if (hash < 0)
00287     {
00288       hash = hashf (name, len, CPP_HASHSIZE);
00289     }
00290 
00291   bucket = hashtab[hash];
00292 
00293   while (bucket != NULL) 
00294     {
00295       if (bucket->length == len && 
00296           cstring_equalLen (bucket->name, cstring_fromChars (name), len)) 
00297         {
00298           return bucket;
00299         }
00300       
00301       bucket = bucket->next;
00302     }
00303 
00304   return NULL;
00305 }
00306 
00307 /*@null@*/ HASHNODE *cppReader_lookupExpand (char *name, int len, int hash)
00308 {
00309   HASHNODE *node = cppReader_lookup (name, len, hash);
00310 
00311   DPRINTF (("Lookup expand: %s", name));
00312 
00313   if (node != NULL) 
00314     {
00315       if (node->type == T_MACRO)
00316         {
00317           DEFINITION *defn = (DEFINITION *) node->value.defn;
00318         
00319           DPRINTF (("Check macro..."));
00320 
00321           if (defn->noExpand) {
00322             DPRINTF (("No expand!"));
00323             return NULL;
00324           }
00325         }
00326     }
00327   
00328   return node;
00329 }
00330 
00331 /*
00332  * Delete a hash node.  Some weirdness to free junk from macros.
00333  * More such weirdness will have to be added if you define more hash
00334  * types that need it.
00335  */
00336 
00337 /* Note that the DEFINITION of a macro is removed from the hash table
00338    but its storage is not freed.  This would be a storage leak
00339    except that it is not reasonable to keep undefining and redefining
00340    large numbers of macros many times.
00341    In any case, this is necessary, because a macro can be #undef'd
00342    in the middle of reading the arguments to a call to it.
00343    If #undef freed the DEFINITION, that would crash.  */
00344 
00345 void
00346 cppReader_deleteMacro (HASHNODE *hp)
00347 {
00348   if (hp->prev != NULL) 
00349     {
00350       /*@-mustfree@*/
00351       hp->prev->next = hp->next;
00352       /*@=mustfree@*/
00353       /*@-branchstate@*/ 
00354     } /*@=branchstate@*/ 
00355   
00356   if (hp->next != NULL) 
00357     {
00358       hp->next->prev = hp->prev;
00359     }
00360   
00361   /* make sure that the bucket chain header that
00362      the deleted guy was on points to the right thing afterwards.  */
00363   if (hp == *hp->bucket_hdr) {
00364     *hp->bucket_hdr = hp->next;
00365   }
00366   
00367   if (hp->type == T_MACRO)
00368     {
00369       DEFINITION *d = hp->value.defn;
00370       struct reflist *ap, *nextap;
00371 
00372       for (ap = d->pattern; ap != NULL; ap = nextap)
00373         {
00374           nextap = ap->next;
00375           sfree (ap);
00376         }
00377 
00378       if (d->nargs >= 0)
00379         {
00380           sfree (d->args.argnames);
00381         }
00382     }
00383 
00384   /*@-dependenttrans@*/ /*@-exposetrans@*/ /*@-compdestroy@*/ 
00385   sfree (hp); 
00386   /*@=dependenttrans@*/ /*@=exposetrans@*/ /*@=compdestroy@*/
00387 }
00388 
00389 /* Install a name in the main hash table, even if it is already there.
00390      name stops with first non alphanumeric, except leading '#'.
00391    caller must check against redefinition if that is desired.
00392    cppReader_deleteMacro () removes things installed by install () in fifo order.
00393    this is important because of the `defined' special symbol used
00394    in #if, and also if pushdef/popdef directives are ever implemented.
00395 
00396    If LEN is >= 0, it is the length of the name.
00397    Otherwise, compute the length by scanning the entire name.
00398 
00399    If HASH is >= 0, it is the precomputed hash code.
00400    Otherwise, compute the hash code.  */
00401 
00402 HASHNODE *cppReader_install (char *name, int len, enum node_type type, 
00403                              int ivalue, char *value, int hash)
00404 {
00405   HASHNODE *hp;
00406   int i, bucket;
00407   char *p, *q;
00408 
00409   if (len < 0) {
00410     p = name;
00411 
00412     while (isIdentifierChar (*p))
00413       {
00414         p++;
00415       }
00416 
00417     len = p - name;
00418   }
00419 
00420   if (hash < 0) 
00421     {
00422       hash = hashf (name, len, CPP_HASHSIZE);
00423     }
00424 
00425   i = sizeof (*hp) + len + 1;
00426 
00427   
00428   hp = (HASHNODE *) dmalloc (size_fromInt (i));
00429   bucket = hash;
00430   hp->bucket_hdr = &hashtab[bucket];
00431 
00432   hp->next = hashtab[bucket];
00433   hp->prev = NULL;
00434 
00435   if (hp->next != NULL) 
00436     {
00437       hp->next->prev = hp;
00438     }
00439 
00440   hashtab[bucket] = hp;
00441 
00442   hp->type = type;
00443   hp->length = len;
00444 
00445   if (hp->type == T_CONST)
00446     {
00447       hp->value.ival = ivalue;
00448       llassert (value == NULL);
00449     }
00450   else
00451     {
00452       hp->value.cpval = value;
00453     }
00454   
00455   {
00456     char *tmp = ((char *) hp) + sizeof (*hp);
00457     p = tmp;
00458     q = name;
00459 
00460     for (i = 0; i < len; i++)
00461       {
00462         *p++ = *q++;
00463       }
00464     
00465     tmp[len] = '\0';
00466     hp->name = cstring_fromChars (tmp);
00467   }
00468 
00469   /*@-mustfree@*/ /*@-uniondef@*/ /*@-compdef@*/
00470   return hp;
00471   /*@=mustfree@*/ /*@=uniondef@*/ /*@=compdef@*/
00472 }
00473 
00474 HASHNODE *cppReader_installMacro (char *name, int len, 
00475                                   struct definition *defn, int hash)
00476 {
00477   return cppReader_install (name, len, T_MACRO, 0, (char  *) defn, hash);
00478 }
00479 
00480 void
00481 cppReader_hashCleanup (void)
00482 {
00483   int i;
00484 
00485   for (i = CPP_HASHSIZE; --i >= 0; )
00486     {
00487       while (hashtab[i] != NULL)
00488         {
00489           cppReader_deleteMacro (hashtab[i]);
00490         }
00491     }
00492 }

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