cfad47cfa3/t2compiler/tads2/tokth.c

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
1
#ifdef RCSID
2
static char RCSid[] =
3
"$Header: d:/cvsroot/tads/TADS2/TOKTH.C,v 1.2 1999/05/17 02:52:13 MJRoberts Exp $";
4
#endif
5
6
/* 
7
 *   Copyright (c) 1992, 2002 Michael J. Roberts.  All Rights Reserved.
8
 *   
9
 *   Please see the accompanying license file, LICENSE.TXT, for information
10
 *   on using and copying this software.  
11
 */
12
/*
13
Name
14
  tokth.c - hashed symbol table manipulation functions
15
Function
16
  Implements hashed symbol tables.  A hashed symbol table stores
17
  a table of pointers to linked lists of symbols; each entry in
18
  the table corresponds to a hash value, allowing a large table
19
  to be searched for a symbol rapidly.
20
Notes
21
  Separated from tok.c to allow the run-time to link the hashed
22
  symbol table functions without needing to link the rest of the
23
  lexical analysis subsystem.
24
Modified
25
  04/11/92 MJRoberts     - creation
26
*/
27
28
#include <ctype.h>
29
#include <string.h>
30
#include <stdlib.h>
31
#include "os.h"
32
#include "std.h"
33
#include "mcm.h"
34
#include "tok.h"
35
#include "lin.h"
36
#include "linf.h"
37
38
/* compute a hash value */
39
uint tokhsh(char *nam)
40
{
41
    uint hash = 0;
42
    
43
    while (*nam) hash = ((hash + *nam++) & (TOKHASHSIZE - 1));
44
    return(hash);
45
}
46
47
/* for allocation - size of tokshdef without name portion */
48
struct toksh1def
49
{
50
    tokthpdef tokshnxt;
51
    toks1def  tokshsc;
52
};
53
typedef struct toksh1def toksh1def;
54
55
/* initialize a hashed symbol table */
56
void tokthini(errcxdef *errctx, mcmcxdef *memctx, toktdef *toktab1)
57
{
58
    tokthdef *toktab = (tokthdef *)toktab1;      /* convert to correct type */
59
    int       i;
60
61
    CLRSTRUCT(*toktab);
62
    toktab->tokthsc.toktfadd = tokthadd;           /* set add-symbol method */
63
    toktab->tokthsc.toktfsea = tokthsea;         /* set search-table method */
64
    toktab->tokthsc.toktfset = tokthset;                   /* update symbol */
65
    toktab->tokthsc.toktfeach = toktheach;       /* call fn for all symbols */
66
    toktab->tokthsc.tokterr = errctx;         /* set error handling context */
67
    toktab->tokthmem = memctx;                    /* memory manager context */
68
    toktab->tokthcpool = mcmalo(memctx, (ushort)TOKTHSIZE,
69
                                &toktab->tokthpool[0]);
70
    toktab->tokthpcnt = 0;
71
    toktab->tokthsize = TOKTHSIZE;
72
73
    /* set hash table entries to point to nothing (MCMONINV) */
74
    for (i = 0 ; i < TOKHASHSIZE ; ++i)
75
        toktab->tokthhsh[i].tokthpobj = MCMONINV;
76
}
77
78
/* add a symbol to a hashed symbol table */
79
void tokthadd(toktdef *toktab1, char *name, int namel,
80
              int typ, int val, int hash)
81
{
82
    int       siz = sizeof(toksh1def) + namel;
83
    toksdef  *sym;
84
    tokshdef *symh;
85
    tokthdef *toktab = (tokthdef *)toktab1;
86
    
87
    if (toktab->tokthsize < siz)
88
    {
89
        mcmcxdef *mctx = toktab->tokthmem;
90
        
91
        /* insufficient space in current pool; add a new pool */
92
        if (toktab->tokthpcnt >= TOKPOOLMAX)
93
            errsig(toktab->tokthsc.tokterr, ERR_MANYSYM);
94
95
        /* unlock current pool page, and note its final size */
96
        mcmunlck(mctx, toktab->tokthpool[toktab->tokthpcnt]);
97
        toktab->tokthfinal[toktab->tokthpcnt] = toktab->tokthofs;
98
99
        /* allocate a new pool page, and leave it locked */
100
        toktab->tokthcpool = mcmalo(mctx, (ushort)TOKTHSIZE,
101
                                   &toktab->tokthpool[++(toktab->tokthpcnt)]);
102
        toktab->tokthsize = TOKTHSIZE;
103
        toktab->tokthofs = 0;
104
    }
105
    symh = (tokshdef *)(toktab->tokthcpool + toktab->tokthofs);
106
    sym = &symh->tokshsc;
107
    
108
    /* link into list for this hash value */
109
    OSCPYSTRUCT(symh->tokshnxt, toktab->tokthhsh[hash]);
110
    toktab->tokthhsh[hash].tokthpobj = toktab->tokthpool[toktab->tokthpcnt];
111
    toktab->tokthhsh[hash].tokthpofs = toktab->tokthofs;
112
    
113
    /* fill in rest of toksdef */
114
    sym->toksval = val;
115
    sym->tokslen = namel;
116
    sym->tokstyp = typ;
117
    sym->tokshsh = hash;
118
    sym->toksfr  = 0;
119
    memcpy(sym->toksnam, name, (size_t)namel);
120
    
121
    /* update free pool pointer */
122
    siz = osrndsz(siz);
123
    toktab->tokthofs += siz;
124
    if (siz > toktab->tokthsize) toktab->tokthsize = 0;
125
    else toktab->tokthsize -= siz;
126
}
127
128
/*
129
 *   Scan a hash chain, calling a callback for each entry.  If the
130
 *   callback returns TRUE for any symbol, we stop there, and return TRUE.
131
 *   If the callback returns FALSE for a symbol, we keep going.  If the
132
 *   callback returns FALSE for all symbols, we return FALSE.  
133
 */
134
static int tokthscan(tokthdef *tab, uint hash,
135
                     int (*cb)(void *, toksdef *, mcmon), 
136
                     void *cbctx)
137
{
138
    tokshdef  *symh;
139
    toksdef   *sym;
140
    tokthpdef  p;
141
    tokthpdef  nxt;
142
    uchar     *pg;
143
    mcmcxdef  *mctx = tab->tokthmem;
144
    mcmon      curobj;
145
146
    /* get first object, and lock its page if there is one */
147
    OSCPYSTRUCT(p, tab->tokthhsh[hash]);
148
    if ((curobj = p.tokthpobj) != MCMONINV)
149
        pg = mcmlck(mctx, curobj);
150
151
    /* look for a match using the callback */
152
    for ( ; p.tokthpobj != MCMONINV ; OSCPYSTRUCT(p, nxt))
153
    {
154
        symh = (tokshdef *)(pg + p.tokthpofs);
155
        sym = &symh->tokshsc;
156
        OSCPYSTRUCT(nxt, symh->tokshnxt);
157
158
        /* check for a match; copy to return buffer if found */
159
        if ((*cb)(cbctx, sym, p.tokthpobj))
160
        {
161
            mcmunlck(mctx, p.tokthpobj);
162
            return(TRUE);
163
        }
164
        
165
        /* if the next page is different from this one, get new lock */
166
        if (nxt.tokthpobj != curobj && nxt.tokthpobj != MCMONINV)
167
        {
168
            mcmunlck(mctx, curobj);
169
            curobj = nxt.tokthpobj;
170
            pg = mcmlck(mctx, curobj);
171
        }
172
    }
173
174
    /* unlock last object, if we had a lock at all */
175
    if (curobj != MCMONINV) mcmunlck(mctx, curobj);
176
    return(FALSE);
177
}
178
179
struct tokseadef
180
{
181
    char     *tokseanam;
182
    toksdef   tokseasym;
183
    toksdef  *toksearet;
184
    mcmcxdef *tokseamctx;
185
};
186
typedef struct tokseadef tokseadef;
187
188
/* search callback */
189
static int tokthsea1(void *ctx0, toksdef *sym, mcmon objn)
190
{
191
    tokseadef *ctx = (tokseadef *)ctx0;
192
    
193
    VARUSED(objn);
194
    
195
    if (sym->tokslen == ctx->tokseasym.tokslen &&
196
        !memcmp(sym->toksnam, ctx->tokseanam, ctx->tokseasym.tokslen))
197
    {
198
        memcpy(ctx->toksearet, sym,
199
               (size_t)(sizeof(toks1def) + ctx->tokseasym.tokslen));
200
        return(TRUE);
201
    }
202
    else
203
        return(FALSE);
204
}
205
206
/* search a hashed symbol table for a symbol */
207
int tokthsea(toktdef *tab1, char *name, int namel, int hash, toksdef *ret)
208
{
209
    tokseadef ctx;
210
211
    ctx.tokseanam = name;
212
    ctx.tokseasym.tokslen = namel;
213
    ctx.toksearet = ret;
214
    return(tokthscan((tokthdef *)tab1, hash, tokthsea1, &ctx));
215
}
216
217
/* callback for tokthset */
218
static int tokthset1(void *ctx0, toksdef *sym, mcmon objn)
219
{
220
    tokseadef *ctx = (tokseadef *)ctx0;
221
    
222
    if (sym->tokslen == ctx->tokseasym.tokslen
223
        && !memcmp(sym->toksnam, ctx->tokseasym.toksnam,
224
                   ctx->tokseasym.tokslen))
225
    {
226
        sym->toksval = ctx->tokseasym.toksval;
227
        sym->tokstyp = ctx->tokseasym.tokstyp;
228
            
229
        /* touch object, since it's been changed */
230
        mcmtch(ctx->tokseamctx, objn);
231
        return(TRUE);
232
    }
233
    else
234
        return(FALSE);
235
}
236
237
/* update a symbol in a hashed symbol table */
238
void tokthset(toktdef *tab1, toksdef *newsym)
239
{
240
    tokseadef  ctx;
241
    tokthdef  *tab = (tokthdef *)tab1;
242
    
243
    OSCPYSTRUCT(ctx.tokseasym, *newsym);
244
    ctx.tokseamctx = tab->tokthmem;
245
    tokthscan((tokthdef *)tab1, newsym->tokshsh, tokthset1, &ctx);
246
}
247
248
/* callback for tokthfind */
249
static int tokthfind1(void *ctx0, toksdef *sym, mcmon objn)
250
{
251
    tokseadef *ctx = (tokseadef *)ctx0;
252
    
253
    VARUSED(objn);
254
    
255
    if (sym->toksval == ctx->tokseasym.toksval
256
        && sym->tokstyp == ctx->tokseasym.tokstyp)
257
    {
258
        memcpy(ctx->toksearet, sym,
259
               (size_t)(sizeof(toks1def) + sym->tokslen));
260
        return(TRUE);
261
    }
262
    else
263
        return(FALSE);
264
}
265
266
/* find a symbol of a particular type and value */
267
int tokthfind(toktdef *tab1, int typ, uint val, toksdef *ret)
268
{
269
    tokseadef ctx;
270
    int       i;
271
    
272
    ctx.tokseasym.tokstyp = typ;
273
    ctx.tokseasym.toksval = val;
274
    ctx.toksearet = ret;
275
    
276
    for (i = 0 ; i < TOKHASHSIZE ; ++i)
277
    {
278
        if (tokthscan((tokthdef *)tab1, i, tokthfind1, &ctx))
279
            return(TRUE);
280
    }
281
    return(FALSE);
282
}
283
284
/* call a callback for each function in a hashed symbol table */
285
void toktheach(toktdef *tab1,
286
               void (*cb)(void *, toksdef *), void *ctx)
287
{
288
    tokthdef *tab = (tokthdef *)tab1;
289
    uchar    *p;
290
    uint      max;
291
    uint      ofs;
292
    tokshdef *symh;
293
    toksdef  *sym;
294
    uint      siz;
295
    uint      i;
296
    
297
    for (i = 0 ; i <= tab->tokthpcnt ; ++i)
298
    {
299
        /* lock the current page */
300
        p = mcmlck(tab->tokthmem, tab->tokthpool[i]);
301
        
302
        ERRBEGIN(tab1->tokterr)
303
304
        max = (i == tab->tokthpcnt ? tab->tokthofs : tab->tokthfinal[i]);
305
        for (ofs = 0 ; ofs < max ; )
306
        {
307
            /* get this symbol */
308
            symh = (tokshdef *)(p + ofs);
309
            sym = &symh->tokshsc;
310
            
311
            /* call the user callback */
312
            (*cb)(ctx, sym);
313
            
314
            /* advance to the next symbol on this page */
315
            siz = sizeof(toksh1def) + sym->tokslen;
316
            ofs += osrndsz(siz);
317
        }
318
            
319
        ERRCLEAN(tab1->tokterr)
320
            mcmunlck(tab->tokthmem, tab->tokthpool[i]);
321
        ERRENDCLN(tab1->tokterr)
322
            
323
        /* done with current page; unlock it */
324
        mcmunlck(tab->tokthmem, tab->tokthpool[i]);
325
    }
326
}
327