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

lsymbol.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 ** lsymbol.c
00026 **
00027 ** String manager
00028 **
00029 **      This module implements an abstraction for efficiently managing
00030 **      string comparisons.  It alloctes and manages a string context,
00031 **      which consists of three major data structures:
00032 **       - a StringEntry table
00033 **       - a character-string table
00034 **       - a hash table
00035 **
00036 **      A StringEntry table is made of of StringEntries. StringEntries
00037 **      are linked in hash-chains to support fast lookup. Every
00038 **      allocated StringEntry corresponds to a unique character-string
00039 **      in the character-string table. StringEntries can be referenced
00040 **      via Symbol values.
00041 **
00042 **      A character-string table is composed of character-strings. A
00043 **      character-string is a variable length byte array that is always
00044 **      null-terminated ('\0').
00045 **
00046 **      A hash table manages the start of each hash-list of StringEntries.
00047 **      StringEntries are entered into the hash-list by hashing on its
00048 **      character-string representation.
00049 **
00050 **      This module provides routines for retrieving a unique Symbol for a
00051 **      given character-string, and returning the character-string given its
00052 **      corresponding Symbol. An item is allocated in both tables whenever a
00053 **      new character-string is encountered, otherwise the Symbol for the
00054 **      character-string is found and returned.
00055 **
00056 **  AUTHORS:
00057 **
00058 **      Shota Aki
00059 **
00060 **  MODIFICATION HISTORY:
00061 **
00062 **      {0} Aki      at Digital -- 89.08.07 -- original
00063 **      {1} Aki      at Digital -- 89.11.13 -- context switchable
00064 **      {2} Aki      at Digital -- 89.11.28 -- removed use of TABLES interface
00065 **      {3} Aki      at Digital -- 89.11.29 -- moved to RC
00066 **      {4} Aki      at Digital -- 90.04.10 -- support primary-context
00067 **      {5} McKeeman at Digital -- 90.05.08 -- C to Larch SL
00068 **      {6} Wild     at Digital -- 91.06.26 -- Update copyright notice.
00069 **      {n} Who      at Where   -- yy.mm.dd -- what
00070 */
00071 
00072 # include "lclintMacros.nf"
00073 # include "basic.h"
00074 
00075 /*@+ignorequals@*/
00076 
00077 /*@constant int NULLFACTOR; @*/
00078 # define NULLFACTOR 1
00079 
00080 typedef Handle CharIndex;     
00081 
00082 typedef struct
00083 {
00084   lsymbol HashNext;     
00085   CharIndex i;                  
00086 } StringEntry;
00087 
00088 static void AllocCharSpace (unsigned p_newSize) /*@modifies internalState@*/ ;
00089 static CharIndex AllocChar (/*@unique@*/ char *p_name) /*@modifies internalState@*/ ;
00090 static void AllocEntrySpace (unsigned p_newSize) /*@modifies internalState@*/ ;
00091 static lsymbol AllocEntry (char *p_name, long unsigned p_hashValue)
00092    /*@modifies internalState@*/ ;
00093 
00094 static /*@only@*/ /*@null@*/ lsymbol *hashArray = NULL; 
00095 
00096 static long unsigned MaxChar;   
00097 static CharIndex FreeChar;      
00098 static /*@only@*/ /*@null@*/ char *CharString;
00099 
00100 static long unsigned MaxEntry;  
00101 static lsymbol FreeEntry;       
00102 static /*@only@*/ /*@null@*/ StringEntry *Entry;        
00103 
00104 lsymbol
00105 lsymbol_fromString (cstring s)
00106 {
00107   if (cstring_isUndefined (s))
00108     {
00109       return lsymbol_undefined;
00110     }
00111   else
00112     {
00113       return (lsymbol_fromChars (cstring_toCharsSafe (s)));
00114     }
00115 }
00116 
00117 lsymbol
00118 lsymbol_fromChars (/*@temp@*/ char *name)
00119 {
00120   lsymbol ss;
00121   long unsigned hashValue;      
00122   unsigned h = 0;            
00123   char *p = name;
00124 
00125   while (*p != '\0')
00126     { 
00127       h = (h << 1) + (unsigned) (*p++); 
00128     } 
00129   
00130   hashValue = h & HASHMASK;         
00131 
00132   if (hashArray == NULL) /* evs - was MaxIndex == 0 */
00133     {
00134       /* nothing initialized */
00135       ss = AllocEntry (name, hashValue);        
00136     }
00137   else
00138     {
00139       ss = hashArray[hashValue]; /* start of hash chain */
00140 
00141       if (ss == lsymbol_undefined)
00142         {
00143           /* hash not initialized */
00144           ss = AllocEntry (name, hashValue);
00145         }
00146       else
00147         {
00148          /*
00149           * Traverse hash-chain. Loop terminates when
00150           * a match is found or end of chain is encountered.
00151           */
00152 
00153           llassert (Entry != NULL);
00154           llassert (CharString != NULL);
00155 
00156           while (strcmp (&CharString[Entry[ss].i], name) != 0)
00157             {
00158               if (lsymbol_undefined == (ss = Entry[ss].HashNext))
00159                 {
00160                   ss = AllocEntry (name, hashValue);
00161                   break;
00162                 }
00163             }
00164         }
00165     }
00166 
00167   return ss;
00168 }
00169 
00170 cstring lsymbol_toString (lsymbol ss)
00171 {
00172   return (cstring_fromChars (lsymbol_toChars (ss)));
00173 }
00174 
00175 char *
00176 lsymbol_toCharsSafe (lsymbol ss)
00177 {
00178   char *ret = lsymbol_toChars (ss);
00179 
00180   if (ret == NULL) 
00181     {
00182       ret = mstring_create (0);
00183     } 
00184 
00185   return ret;
00186 }
00187 
00188 char *lsymbol_toChars (lsymbol ss)
00189 {
00190   if (lsymbol_isDefined (ss))
00191     {
00192       if (ss >= FreeEntry)
00193         {
00194           llcontbug (message ("lsymbol_toChars: invalid lsymbol: %d", ss));
00195           return NULL;
00196         }
00197       
00198       llassert (Entry != NULL);
00199       llassert (CharString != NULL);
00200       
00201       return &CharString[Entry[ss].i];
00202     }
00203   else
00204     {
00205       return NULL;
00206     }
00207 }
00208 
00209 static void
00210 AllocCharSpace (unsigned newSize)
00211 {
00212   llassert (newSize > MaxChar);
00213   
00214   CharString = (char *) drealloc ((void *) CharString, newSize * sizeof (*CharString));
00215   MaxChar = newSize;
00216 /*@-compdef@*/
00217 } /*@=compdef@*/
00218 
00219 static CharIndex
00220 AllocChar (/*@unique@*/ char *name)
00221 {
00222   int namelength;
00223   CharIndex retVal;
00224   long unsigned size;
00225   CharIndex unused;
00226 
00227   namelength = size_toInt (strlen (name));
00228   unused = FreeChar;
00229   size = MaxChar;
00230 
00231   if ((unused + namelength + NULLFACTOR) > size)
00232     {
00233       if (size == 0)
00234         size = INITCHARSTRING;
00235       else
00236         size = (unsigned) (DELTACHARSTRING * size);
00237 
00238       AllocCharSpace (size);
00239     }
00240 
00241   llassert (CharString != NULL);
00242 
00243   retVal = unused;              
00244   strcpy (&CharString[unused], name);   
00245   unused += namelength;
00246   CharString[unused] = '\0';    
00247   unused += 1;
00248 
00249   FreeChar = unused;
00250   return retVal;
00251 }
00252 
00253 static void
00254 AllocEntrySpace (unsigned newSize)
00255 {
00256   llassert (newSize > MaxEntry);
00257 
00258   /* Casts mess up checking here. */
00259   /*@-mustfree@*/
00260   Entry = (StringEntry *) drealloc ((void *) Entry, newSize * sizeof (*Entry));
00261   /*@=mustfree@*/
00262 
00263   if (MaxEntry == 0) MaxEntry = 1;
00264 
00265   FreeEntry = MaxEntry;
00266   MaxEntry = newSize;
00267 /*@-compdef@*/
00268 } /*@=compdef@*/
00269 
00270 static lsymbol AllocEntry (char *name, long unsigned hashValue)
00271 {
00272   lsymbol retVal;
00273   long unsigned size;
00274 
00275   size = MaxEntry;
00276 
00277   if ((retVal = FreeEntry) == size)
00278     {
00279       if (size == 0)
00280         {
00281           size = INITSTRINGENTRY;
00282         }
00283       else
00284         {
00285           size = (unsigned) (DELTASTRINGENTRY * size);
00286         }
00287 
00288       AllocEntrySpace (size);
00289       retVal = FreeEntry;
00290     }
00291   
00292   FreeEntry = retVal + 1;
00293 
00294   llassert (hashArray != NULL);
00295   llassert (Entry != NULL);
00296   
00297   Entry[retVal].HashNext = hashArray[hashValue];
00298   hashArray[hashValue] = retVal;
00299   Entry[retVal].i = AllocChar (name);
00300   
00301   return retVal;
00302 }
00303 
00304 void
00305 lsymbol_initMod (void)
00306    /*@globals undef CharString, undef Entry; @*/
00307 {
00308   int i;
00309 
00310   if (hashArray != NULL)
00311     {
00312       sfree (hashArray); 
00313     }
00314   
00315   hashArray = (lsymbol *) dmalloc (HASHSIZE * sizeof (*hashArray));
00316 
00317   for (i = 0; i < HASHSIZE; i++)
00318     {
00319       hashArray[i] = lsymbol_undefined;
00320     } 
00321 
00322   MaxChar = 0;
00323   MaxEntry = 0;
00324 
00325   FreeChar = 0;
00326   FreeEntry = 0; 
00327 
00328   CharString = (char *) 0;
00329   Entry = (StringEntry *) 0;
00330 /*@-compdef@*/ 
00331 } 
00332 /*@=compdef@*/ 
00333 
00334 void
00335 lsymbol_destroyMod (void)
00336    /*@globals killed Entry, killed CharString, killed hashArray@*/
00337 {
00338    sfree (Entry);      
00339    sfree (CharString); 
00340    sfree (hashArray); 
00341 }
00342 
00343 void
00344 lsymbol_printStats (void)
00345 {
00346   /* only for debugging */
00347   printf ("Number of lsymbols generated = %d\n", (int) FreeEntry);
00348 }
00349 
00350 /*
00351 ** note lsymbol_setbool, etc. defined in abstract.c
00352 */
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 

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