2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
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
29 ** This module implements an abstraction for efficiently managing
30 ** string comparisons. It alloctes and manages a string context,
31 ** which consists of three major data structures:
32 ** - a StringEntry table
33 ** - a character-string table
36 ** A StringEntry table is made of of StringEntries. StringEntries
37 ** are linked in hash-chains to support fast lookup. Every
38 ** allocated StringEntry corresponds to a unique character-string
39 ** in the character-string table. StringEntries can be referenced
42 ** A character-string table is composed of character-strings. A
43 ** character-string is a variable length byte array that is always
44 ** null-terminated ('\0').
46 ** A hash table manages the start of each hash-list of StringEntries.
47 ** StringEntries are entered into the hash-list by hashing on its
48 ** character-string representation.
50 ** This module provides routines for retrieving a unique Symbol for a
51 ** given character-string, and returning the character-string given its
52 ** corresponding Symbol. An item is allocated in both tables whenever a
53 ** new character-string is encountered, otherwise the Symbol for the
54 ** character-string is found and returned.
60 ** MODIFICATION HISTORY:
62 ** {0} Aki at Digital -- 89.08.07 -- original
63 ** {1} Aki at Digital -- 89.11.13 -- context switchable
64 ** {2} Aki at Digital -- 89.11.28 -- removed use of TABLES interface
65 ** {3} Aki at Digital -- 89.11.29 -- moved to RC
66 ** {4} Aki at Digital -- 90.04.10 -- support primary-context
67 ** {5} McKeeman at Digital -- 90.05.08 -- C to Larch SL
68 ** {6} Wild at Digital -- 91.06.26 -- Update copyright notice.
69 ** {n} Who at Where -- yy.mm.dd -- what
72 # include "splintMacros.nf"
77 /*@constant int NULLFACTOR; @*/
80 typedef Handle CharIndex
;
88 static void AllocCharSpace (unsigned p_newSize
) /*@modifies internalState@*/ ;
89 static CharIndex
AllocChar (/*@unique@*/ const char *p_name
) /*@modifies internalState@*/ ;
90 static void AllocEntrySpace (unsigned p_newSize
) /*@modifies internalState@*/ ;
91 static lsymbol
AllocEntry (const char *p_name
, long unsigned p_hashValue
)
92 /*@modifies internalState@*/ ;
94 static /*@only@*/ /*@null@*/ lsymbol
*hashArray
= NULL
;
96 static long unsigned MaxChar
;
97 static CharIndex FreeChar
;
98 static /*@only@*/ /*@null@*/ char *CharString
;
100 static long unsigned MaxEntry
;
101 static lsymbol FreeEntry
;
102 static /*@only@*/ /*@null@*/ StringEntry
*Entry
;
105 lsymbol_fromString (cstring s
)
107 if (cstring_isUndefined (s
))
109 return lsymbol_undefined
;
113 return (lsymbol_fromChars (cstring_toCharsSafe (s
)));
118 lsymbol_fromChars (/*@temp@*/ const char *name
)
121 long unsigned hashValue
;
123 const char *p
= name
;
127 h
= (h
<< 1) + (unsigned) (*p
);
131 hashValue
= h
& HASHMASK
;
133 if (hashArray
== NULL
) /* evs - was MaxIndex == 0 */
135 /* nothing initialized */
136 ss
= AllocEntry (name
, hashValue
);
140 ss
= hashArray
[hashValue
]; /* start of hash chain */
142 if (ss
== lsymbol_undefined
)
144 /* hash not initialized */
145 ss
= AllocEntry (name
, hashValue
);
150 * Traverse hash-chain. Loop terminates when
151 * a match is found or end of chain is encountered.
154 llassert (Entry
!= NULL
);
155 llassert (CharString
!= NULL
);
157 while (strcmp (&CharString
[Entry
[ss
].i
], name
) != 0)
159 if (lsymbol_undefined
== (ss
= Entry
[ss
].HashNext
))
161 ss
= AllocEntry (name
, hashValue
);
171 cstring
lsymbol_toString (lsymbol ss
)
173 return (cstring_fromChars (lsymbol_toChars (ss
)));
177 lsymbol_toCharsSafe (lsymbol ss
)
179 char *ret
= lsymbol_toChars (ss
);
183 ret
= mstring_create (0);
189 char *lsymbol_toChars (lsymbol ss
)
191 if (lsymbol_isDefined (ss
))
195 llcontbug (message ("lsymbol_toChars: invalid lsymbol: %d", ss
));
199 llassert (Entry
!= NULL
);
200 llassert (CharString
!= NULL
);
202 return &CharString
[Entry
[ss
].i
];
211 AllocCharSpace (unsigned newSize
)
213 llassert (newSize
> MaxChar
);
215 CharString
= (char *) drealloc ((void *) CharString
, newSize
* sizeof (*CharString
));
221 AllocChar (/*@unique@*/ const char *name
)
228 namelength
= size_toInt (strlen (name
));
232 if ((unused
+ namelength
+ NULLFACTOR
) > size
)
235 size
= INITCHARSTRING
;
237 size
= (unsigned) (DELTACHARSTRING
* size
);
239 AllocCharSpace (size
);
242 llassert (CharString
!= NULL
);
245 strcpy (&CharString
[unused
], name
);
246 unused
+= namelength
;
247 CharString
[unused
] = '\0';
255 AllocEntrySpace (unsigned newSize
)
257 llassert (newSize
> MaxEntry
);
259 /* Casts mess up checking here. */
261 Entry
= (StringEntry
*) drealloc ((void *) Entry
, newSize
* sizeof (*Entry
));
264 if (MaxEntry
== 0) MaxEntry
= 1;
266 FreeEntry
= MaxEntry
;
271 static lsymbol
AllocEntry (const char *name
, long unsigned hashValue
)
278 if ((retVal
= FreeEntry
) == size
)
282 size
= INITSTRINGENTRY
;
286 size
= (unsigned) (DELTASTRINGENTRY
* size
);
289 AllocEntrySpace (size
);
293 FreeEntry
= retVal
+ 1;
295 llassert (hashArray
!= NULL
);
296 llassert (Entry
!= NULL
);
298 Entry
[retVal
].HashNext
= hashArray
[hashValue
];
299 hashArray
[hashValue
] = retVal
;
300 Entry
[retVal
].i
= AllocChar (name
);
306 lsymbol_initMod (void)
307 /*@globals undef CharString, undef Entry; @*/
311 if (hashArray
!= NULL
)
316 hashArray
= (lsymbol
*) dmalloc (HASHSIZE
* sizeof (*hashArray
));
318 for (i
= 0; i
< HASHSIZE
; i
++)
320 hashArray
[i
] = lsymbol_undefined
;
329 CharString
= (char *) 0;
330 Entry
= (StringEntry
*) 0;
336 lsymbol_destroyMod (void)
337 /*@globals killed Entry, killed CharString, killed hashArray@*/
346 lsymbol_printStats (void)
348 /* only for debugging */
349 printf ("Number of lsymbols generated = %d\n", (int) FreeEntry
);
351 # endif /* DEADCODE */
354 ** note lsymbol_setbool, etc. defined in abstract.c