~ubuntu-branches/ubuntu/feisty/mp4h/feisty

« back to all changes in this revision

Viewing changes to src/symtab.c

  • Committer: Bazaar Package Importer
  • Author(s): Denis Barbier
  • Date: 2003-11-06 20:34:24 UTC
  • Revision ID: james.westby@ubuntu.com-20031106203424-nqx14tkfeirx01r3
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* mp4h -- A macro processor for HTML documents
 
2
   Copyright 2000-2003, Denis Barbier
 
3
   All rights reserved.
 
4
 
 
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)
 
8
   any later version.
 
9
 
 
10
   This program is a work based on GNU m4 version 1.4n. Below is the
 
11
   original copyright.
 
12
*/
 
13
/* GNU m4 -- A simple macro processor
 
14
   Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
 
15
  
 
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)
 
19
   any later version.
 
20
  
 
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.
 
25
  
 
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.
 
29
*/
 
30
 
 
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.  */
 
42
 
 
43
#include "mp4h.h"
 
44
 
 
45
/*----------------------------------------------------------------------.
 
46
| Initialise the symbol table, by allocating the necessary storage, and |
 
47
| zeroing all the entries.                                              |
 
48
`----------------------------------------------------------------------*/
 
49
 
 
50
/* Pointer to symbol table.  */
 
51
symbol **sym_tab;
 
52
 
 
53
/* Pointer to entity table.  */
 
54
symbol **entity_tab;
 
55
 
 
56
/* Pointer to variable table.  */
 
57
symbol **var_tab;
 
58
 
 
59
/* Pointer to file table.  */
 
60
symbol **file_tab;
 
61
 
 
62
/* Any of previous pointers.  */
 
63
symbol **symtab;
 
64
 
 
65
/* True if tags are case insensitive  */
 
66
boolean caseless_tag;
 
67
 
 
68
/* True if variables are case insensitive  */
 
69
boolean caseless_var;
 
70
 
 
71
/* True if entities are case insensitive  */
 
72
boolean caseless_ent;
 
73
 
 
74
static void
 
75
hash_table_init (symbol **s)
 
76
{
 
77
  int i;
 
78
  for (i = hash_table_size; --i >= 0;)
 
79
    *s++ = NULL;
 
80
}
 
81
 
 
82
void
 
83
symtab_init (void)
 
84
{
 
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);
 
93
  symtab = sym_tab;
 
94
}
 
95
 
 
96
void
 
97
caseless_init (int caseless)
 
98
{
 
99
  caseless_tag = ((caseless & 1) == 1);
 
100
  caseless_var = ((caseless & 2) == 2);
 
101
  caseless_ent = ((caseless & 4) == 4);
 
102
}
 
103
 
 
104
/*--------------------------------------------.
 
105
| Free all storage associated with a symbol.  |
 
106
`--------------------------------------------*/
 
107
 
 
108
static void
 
109
free_symbol (symbol *sym)
 
110
{
 
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);
 
117
}
 
118
 
 
119
static void
 
120
hash_table_free (symbol **s)
 
121
{
 
122
  int h;
 
123
  symbol *sym, *next;
 
124
 
 
125
  for (h = 0; h < hash_table_size; h++)
 
126
    {
 
127
      for (sym = s[h]; sym != NULL; )
 
128
        {
 
129
          next = SYMBOL_NEXT (sym);
 
130
          free_symbol (sym);
 
131
          sym = next;
 
132
        }
 
133
    }
 
134
 
 
135
  xfree ((voidstar) s);
 
136
}
 
137
 
 
138
void
 
139
symtab_deallocate (void)
 
140
{
 
141
  hash_table_free (var_tab);
 
142
  hash_table_free (file_tab);
 
143
  hash_table_free (entity_tab);
 
144
  hash_table_free (sym_tab);
 
145
}
 
146
 
 
147
/*--------------------------------------------------.
 
148
| Return a hashvalue for a string, from GNU-emacs.  |
 
149
`--------------------------------------------------*/
 
150
 
 
151
static int
 
152
hash (const char *s)
 
153
{
 
154
  register int val = 0;
 
155
 
 
156
  register const char *ptr = s;
 
157
  register char ch;
 
158
 
 
159
  while ((ch = *ptr++) != '\0')
 
160
    {
 
161
      if (ch >= 0140)
 
162
        ch -= 40;
 
163
      val = ((val << 3) + (val >> 28) + ch);
 
164
    };
 
165
  val = (val < 0) ? -val : val;
 
166
  return val % hash_table_size;
 
167
}
 
168
 
 
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  |
 
173
| the name.                                                               |
 
174
|                                                                         |
 
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 |
 
179
| on the list.                                                            |
 
180
`------------------------------------------------------------------------*/
 
181
 
 
182
static symbol *
 
183
generic_lookup (const char *name, symbol_lookup mode, boolean caseless)
 
184
{
 
185
  int h, cmp = 1;
 
186
  symbol *sym, *prev;
 
187
  symbol **spp;
 
188
  char *lcname;
 
189
  char *cp;
 
190
 
 
191
  lcname = xstrdup (name);
 
192
  if (caseless)
 
193
    {
 
194
      for (cp=lcname; *cp != '\0'; cp++)
 
195
        *cp = tolower (*cp);
 
196
    }
 
197
 
 
198
  h = hash (lcname);
 
199
  sym = symtab[h];
 
200
 
 
201
  for (prev = NULL; sym != NULL; prev = sym, sym = sym->next)
 
202
    {
 
203
      cmp = strcmp (SYMBOL_NAME (sym), lcname);
 
204
      if (cmp >= 0)
 
205
        break;
 
206
    }
 
207
 
 
208
  /* If just searching, return status of search.  */
 
209
 
 
210
  if (mode == SYMBOL_LOOKUP)
 
211
    {
 
212
      xfree ((voidstar) lcname);
 
213
      return cmp == 0 ? sym : NULL;
 
214
    }
 
215
 
 
216
  /* Symbol not found.  */
 
217
 
 
218
  spp = (prev != NULL) ?  &prev->next : &symtab[h];
 
219
 
 
220
  switch (mode)
 
221
    {
 
222
 
 
223
    case SYMBOL_INSERT:
 
224
 
 
225
      /* Return the symbol, if the name was found in the table.
 
226
         Otherwise, just insert the name, and return the new symbol.  */
 
227
 
 
228
      if (cmp == 0 && sym != NULL)
 
229
        break;
 
230
 
 
231
      /* Insert a name in the symbol table.  */
 
232
      sym = (symbol *) xmalloc (sizeof (symbol));
 
233
      initialize_builtin (sym);
 
234
      SYMBOL_NAME (sym) = xstrdup (lcname);
 
235
 
 
236
      SYMBOL_NEXT (sym) = *spp;
 
237
      (*spp) = sym;
 
238
 
 
239
      break;
 
240
 
 
241
    case SYMBOL_DELETE:
 
242
 
 
243
      /* Delete all occurences of symbols with NAME.  */
 
244
 
 
245
      if (cmp != 0)
 
246
        sym = NULL;
 
247
      if (sym == NULL)
 
248
        break;
 
249
      do
 
250
        {
 
251
          *spp = SYMBOL_NEXT (sym);
 
252
          free_symbol (sym);
 
253
          sym = *spp;
 
254
        }
 
255
      while (sym != NULL && strcmp (lcname, SYMBOL_NAME (sym)) == 0);
 
256
      sym = NULL;
 
257
      break;
 
258
 
 
259
    default:
 
260
      MP4HERROR ((warning_status, 0,
 
261
        "INTERNAL ERROR: Illegal mode to symbol_lookup ()"));
 
262
      exit (1);
 
263
    }
 
264
  xfree ((voidstar) lcname);
 
265
  return sym;
 
266
}
 
267
 
 
268
symbol *
 
269
lookup_symbol (const char *name, symbol_lookup mode)
 
270
{
 
271
  symtab = sym_tab;
 
272
  return generic_lookup (name, mode, caseless_tag);
 
273
}
 
274
 
 
275
symbol *
 
276
lookup_entity (const char *name, symbol_lookup mode)
 
277
{
 
278
  symtab = entity_tab;
 
279
  return generic_lookup (name, mode, caseless_ent);
 
280
}
 
281
 
 
282
symbol *
 
283
lookup_variable (const char *name, symbol_lookup mode)
 
284
{
 
285
  symtab = var_tab;
 
286
  return generic_lookup (name, mode, caseless_var);
 
287
}
 
288
 
 
289
symbol *
 
290
lookup_file (const char *name, symbol_lookup mode)
 
291
{
 
292
  symtab = file_tab;
 
293
  return generic_lookup (name, mode, FALSE);
 
294
}
 
295
 
 
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
`----------------------------------------------------------------------*/
 
303
 
 
304
void
 
305
hack_all_symbols (hack_symbol *func, const char *data)
 
306
{
 
307
  int h;
 
308
  symbol *sym;
 
309
 
 
310
  for (h = 0; h < hash_table_size; h++)
 
311
    {
 
312
      for (sym = symtab[h]; sym != NULL; sym = SYMBOL_NEXT (sym))
 
313
        (*func) (sym, data);
 
314
    }
 
315
}
 
316
 
 
317
 
 
318
#ifdef DEBUG_SYM
 
319
 
 
320
static void
 
321
dump_symbol (symbol *sym, const char *data)
 
322
{
 
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" : "");
 
326
}
 
327
 
 
328
static void
 
329
symtab_debug (void)
 
330
{
 
331
  token_type t;
 
332
  token_data td;
 
333
  const char *text;
 
334
  symbol *s;
 
335
  int delete;
 
336
 
 
337
  while ((t = next_token (&td, READ_NORMAL, FALSE)) != TOKEN_EOF)
 
338
    {
 
339
      if (t != TOKEN_WORD)
 
340
        continue;
 
341
      text = TOKEN_DATA_TEXT (&td);
 
342
      if (*text == '_')
 
343
        {
 
344
          delete = 1;
 
345
          text++;
 
346
        }
 
347
      else
 
348
        delete = 0;
 
349
 
 
350
      s = lookup_symbol (text, SYMBOL_LOOKUP);
 
351
 
 
352
      if (s == NULL)
 
353
        {
 
354
          printf (_("Name `%s' is unknown"), text);
 
355
          printf ("\n");
 
356
        }
 
357
 
 
358
      if (delete)
 
359
        (void) lookup_symbol (text, SYMBOL_DELETE);
 
360
      else
 
361
        (void) lookup_symbol (text, SYMBOL_INSERT);
 
362
    }
 
363
  hack_all_symbols (dump_symbol, "");
 
364
}
 
365
 
 
366
static void
 
367
symtab_print_list (int i)
 
368
{
 
369
  symbol *sym;
 
370
 
 
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" : "");
 
376
}
 
377
 
 
378
#endif /* DEBUG_SYM */