1
/* mp4h -- A macro processor for HTML documents
2
Copyright 2000-2003, Denis Barbier
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2, or (at your option)
10
This program is a work based on GNU m4 version 1.4n. Below is the
13
/* GNU m4 -- A simple macro processor
14
Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
16
This program is free software; you can redistribute it and/or modify
17
it under the terms of the GNU General Public License as published by
18
the Free Software Foundation; either version 2, or (at your option)
21
This program is distributed in the hope that it will be useful,
22
but WITHOUT ANY WARRANTY; without even the implied warranty of
23
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
GNU General Public License for more details.
26
You should have received a copy of the GNU General Public License
27
along with this program; if not, write to the Free Software
28
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
/* This file handles all the low level work around the symbol table. The
32
symbol table is a simple chained hash table. Each symbol is described
33
by a struct symbol, which is placed in the hash table based upon the
34
symbol name. Symbols that hash to the same entry in the table are
35
kept on a list, sorted by name. As a special case, to facilitate the
36
"pushdef" and "popdef" builtins, a symbol can be several times in the
37
symbol table, one for each definition. Since the name is the same,
38
all the entries for the symbol will be on the same list, and will
39
also, because the list is sorted, be adjacent. All the entries for a
40
name are simply ordered on the list by age. The current definition
41
will then always be the first found. */
45
/*----------------------------------------------------------------------.
46
| Initialise the symbol table, by allocating the necessary storage, and |
47
| zeroing all the entries. |
48
`----------------------------------------------------------------------*/
50
/* Pointer to symbol table. */
53
/* Pointer to entity table. */
56
/* Pointer to variable table. */
59
/* Pointer to file table. */
62
/* Any of previous pointers. */
65
/* True if tags are case insensitive */
68
/* True if variables are case insensitive */
71
/* True if entities are case insensitive */
75
hash_table_init (symbol **s)
78
for (i = hash_table_size; --i >= 0;)
85
var_tab = (symbol **) xmalloc (hash_table_size * sizeof (symbol *));
86
file_tab = (symbol **) xmalloc (hash_table_size * sizeof (symbol *));
87
entity_tab = (symbol **) xmalloc (hash_table_size * sizeof (symbol *));
88
sym_tab = (symbol **) xmalloc (hash_table_size * sizeof (symbol *));
89
hash_table_init (var_tab);
90
hash_table_init (file_tab);
91
hash_table_init (entity_tab);
92
hash_table_init (sym_tab);
97
caseless_init (int caseless)
99
caseless_tag = ((caseless & 1) == 1);
100
caseless_var = ((caseless & 2) == 2);
101
caseless_ent = ((caseless & 4) == 4);
104
/*--------------------------------------------.
105
| Free all storage associated with a symbol. |
106
`--------------------------------------------*/
109
free_symbol (symbol *sym)
111
xfree ((voidstar) SYMBOL_NAME (sym));
112
xfree ((voidstar) SYMBOL_HOOK_BEGIN (sym));
113
xfree ((voidstar) SYMBOL_HOOK_END (sym));
114
if (SYMBOL_TYPE (sym) == TOKEN_TEXT)
115
xfree ((voidstar) SYMBOL_TEXT (sym));
116
xfree ((voidstar) sym);
120
hash_table_free (symbol **s)
125
for (h = 0; h < hash_table_size; h++)
127
for (sym = s[h]; sym != NULL; )
129
next = SYMBOL_NEXT (sym);
135
xfree ((voidstar) s);
139
symtab_deallocate (void)
141
hash_table_free (var_tab);
142
hash_table_free (file_tab);
143
hash_table_free (entity_tab);
144
hash_table_free (sym_tab);
147
/*--------------------------------------------------.
148
| Return a hashvalue for a string, from GNU-emacs. |
149
`--------------------------------------------------*/
154
register int val = 0;
156
register const char *ptr = s;
159
while ((ch = *ptr++) != '\0')
163
val = ((val << 3) + (val >> 28) + ch);
165
val = (val < 0) ? -val : val;
166
return val % hash_table_size;
169
/*------------------------------------------------------------------------.
170
| Search in, and manipulation of the symbol table, are all done by |
171
| lookup_symbol (). It basically hashes NAME to a list in the symbol |
172
| table, and searched this list for the first occurence of a symbol with |
175
| The MODE parameter determines what lookup_symbol () will do. It can |
176
| either just do a lookup, do a lookup and insert if not present, do an |
177
| insertion even if the name is already in the list, delete the first |
178
| occurrence of the name on the list or delete all occurences of the name |
180
`------------------------------------------------------------------------*/
183
generic_lookup (const char *name, symbol_lookup mode, boolean caseless)
191
lcname = xstrdup (name);
194
for (cp=lcname; *cp != '\0'; cp++)
201
for (prev = NULL; sym != NULL; prev = sym, sym = sym->next)
203
cmp = strcmp (SYMBOL_NAME (sym), lcname);
208
/* If just searching, return status of search. */
210
if (mode == SYMBOL_LOOKUP)
212
xfree ((voidstar) lcname);
213
return cmp == 0 ? sym : NULL;
216
/* Symbol not found. */
218
spp = (prev != NULL) ? &prev->next : &symtab[h];
225
/* Return the symbol, if the name was found in the table.
226
Otherwise, just insert the name, and return the new symbol. */
228
if (cmp == 0 && sym != NULL)
231
/* Insert a name in the symbol table. */
232
sym = (symbol *) xmalloc (sizeof (symbol));
233
initialize_builtin (sym);
234
SYMBOL_NAME (sym) = xstrdup (lcname);
236
SYMBOL_NEXT (sym) = *spp;
243
/* Delete all occurences of symbols with NAME. */
251
*spp = SYMBOL_NEXT (sym);
255
while (sym != NULL && strcmp (lcname, SYMBOL_NAME (sym)) == 0);
260
MP4HERROR ((warning_status, 0,
261
"INTERNAL ERROR: Illegal mode to symbol_lookup ()"));
264
xfree ((voidstar) lcname);
269
lookup_symbol (const char *name, symbol_lookup mode)
272
return generic_lookup (name, mode, caseless_tag);
276
lookup_entity (const char *name, symbol_lookup mode)
279
return generic_lookup (name, mode, caseless_ent);
283
lookup_variable (const char *name, symbol_lookup mode)
286
return generic_lookup (name, mode, caseless_var);
290
lookup_file (const char *name, symbol_lookup mode)
293
return generic_lookup (name, mode, FALSE);
296
/*----------------------------------------------------------------------.
297
| The following function is used for the cases, where we want to do |
298
| something to each and every symbol in the table. The function |
299
| hack_all_symbols () traverses the symbol table, and calls a specified |
300
| function FUNC for each symbol in the table. FUNC is called with a |
301
| pointer to the symbol, and the DATA argument. |
302
`----------------------------------------------------------------------*/
305
hack_all_symbols (hack_symbol *func, const char *data)
310
for (h = 0; h < hash_table_size; h++)
312
for (sym = symtab[h]; sym != NULL; sym = SYMBOL_NEXT (sym))
321
dump_symbol (symbol *sym, const char *data)
323
printf ("\tname %s, addr 0x%p, next 0x%p, flags%s\n",
324
SYMBOL_NAME (sym), sym, sym->next,
325
SYMBOL_TRACED (sym) ? " traced" : "");
337
while ((t = next_token (&td, READ_NORMAL, FALSE)) != TOKEN_EOF)
341
text = TOKEN_DATA_TEXT (&td);
350
s = lookup_symbol (text, SYMBOL_LOOKUP);
354
printf (_("Name `%s' is unknown"), text);
359
(void) lookup_symbol (text, SYMBOL_DELETE);
361
(void) lookup_symbol (text, SYMBOL_INSERT);
363
hack_all_symbols (dump_symbol, "");
367
symtab_print_list (int i)
371
printf ("Symbol dump %d:\n", i);
372
for (sym = symtab[0]; sym != NULL; sym = sym->next)
373
printf ("\tname %s, addr 0x%p, next 0x%p, flags%s\n",
374
SYMBOL_NAME (sym), sym, sym->next,
375
SYMBOL_TRACED (sym) ? " traced" : "");
378
#endif /* DEBUG_SYM */