~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to src/mesa/shader/slang/MachineIndependent/preprocessor/atom.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* */
2
 
/*Copyright (C) 2002-2005  3Dlabs Inc. Ltd. */
3
 
/*All rights reserved. */
4
 
/* */
5
 
/*Redistribution and use in source and binary forms, with or without */
6
 
/*modification, are permitted provided that the following conditions */
7
 
/*are met: */
8
 
/* */
9
 
/*    Redistributions of source code must retain the above copyright */
10
 
/*    notice, this list of conditions and the following disclaimer. */
11
 
/* */
12
 
/*    Redistributions in binary form must reproduce the above */
13
 
/*    copyright notice, this list of conditions and the following */
14
 
/*    disclaimer in the documentation and/or other materials provided */
15
 
/*    with the distribution. */
16
 
/* */
17
 
/*    Neither the name of 3Dlabs Inc. Ltd. nor the names of its */
18
 
/*    contributors may be used to endorse or promote products derived */
19
 
/*    from this software without specific prior written permission. */
20
 
/* */
21
 
/*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
22
 
/*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
23
 
/*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
24
 
/*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE */
25
 
/*COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
26
 
/*INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, */
27
 
/*BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
28
 
/*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER */
29
 
/*CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT */
30
 
/*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN */
31
 
/*ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
32
 
/*POSSIBILITY OF SUCH DAMAGE. */
33
 
/* */
34
 
/****************************************************************************\
35
 
Copyright (c) 2002, NVIDIA Corporation.
36
 
 
37
 
NVIDIA Corporation("NVIDIA") supplies this software to you in
38
 
consideration of your agreement to the following terms, and your use,
39
 
installation, modification or redistribution of this NVIDIA software
40
 
constitutes acceptance of these terms.  If you do not agree with these
41
 
terms, please do not use, install, modify or redistribute this NVIDIA
42
 
software.
43
 
 
44
 
In consideration of your agreement to abide by the following terms, and
45
 
subject to these terms, NVIDIA grants you a personal, non-exclusive
46
 
license, under NVIDIA's copyrights in this original NVIDIA software (the
47
 
"NVIDIA Software"), to use, reproduce, modify and redistribute the
48
 
NVIDIA Software, with or without modifications, in source and/or binary
49
 
forms; provided that if you redistribute the NVIDIA Software, you must
50
 
retain the copyright notice of NVIDIA, this notice and the following
51
 
text and disclaimers in all such redistributions of the NVIDIA Software.
52
 
Neither the name, trademarks, service marks nor logos of NVIDIA
53
 
Corporation may be used to endorse or promote products derived from the
54
 
NVIDIA Software without specific prior written permission from NVIDIA.
55
 
Except as expressly stated in this notice, no other rights or licenses
56
 
express or implied, are granted by NVIDIA herein, including but not
57
 
limited to any patent rights that may be infringed by your derivative
58
 
works or by other works in which the NVIDIA Software may be
59
 
incorporated. No hardware is licensed hereunder. 
60
 
 
61
 
THE NVIDIA SOFTWARE IS BEING PROVIDED ON AN "AS IS" BASIS, WITHOUT
62
 
WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED,
63
 
INCLUDING WITHOUT LIMITATION, WARRANTIES OR CONDITIONS OF TITLE,
64
 
NON-INFRINGEMENT, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
65
 
ITS USE AND OPERATION EITHER ALONE OR IN COMBINATION WITH OTHER
66
 
PRODUCTS.
67
 
 
68
 
IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT,
69
 
INCIDENTAL, EXEMPLARY, CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
70
 
TO, LOST PROFITS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
71
 
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) OR ARISING IN ANY WAY
72
 
OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE
73
 
NVIDIA SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT,
74
 
TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF
75
 
NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76
 
\****************************************************************************/
77
 
 
78
 
/* */
79
 
/* atom.c */
80
 
/* */
81
 
 
82
 
#include <assert.h>
83
 
#include <stdlib.h>
84
 
#include <stdio.h>
85
 
#include <string.h>
86
 
 
87
 
#include "slglobals.h"
88
 
 
89
 
#undef malloc
90
 
#undef realloc
91
 
#undef free
92
 
 
93
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
94
 
/*//////////////////////////////////////// String table: ////////////////////////////////////// */
95
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
96
 
 
97
 
static const struct {
98
 
    int val;
99
 
    const char *str;
100
 
} tokens[] = {
101
 
    { CPP_AND_OP,         "&&" },
102
 
    { CPP_AND_ASSIGN,     "&=" },
103
 
    { CPP_SUB_ASSIGN,     "-=" },
104
 
    { CPP_MOD_ASSIGN,     "%=" },
105
 
    { CPP_ADD_ASSIGN,     "+=" },
106
 
    { CPP_DIV_ASSIGN,     "/=" },
107
 
    { CPP_MUL_ASSIGN,     "*=" },
108
 
    { CPP_RIGHT_BRACKET,  ":>" },
109
 
    { CPP_EQ_OP,          "==" },
110
 
    { CPP_XOR_OP,         "^^" }, 
111
 
    { CPP_XOR_ASSIGN,     "^=" }, 
112
 
    { CPP_FLOATCONSTANT,  "<float-const>" },
113
 
    { CPP_GE_OP,          ">=" },
114
 
    { CPP_RIGHT_OP,       ">>" },
115
 
    { CPP_RIGHT_ASSIGN,   ">>=" }, 
116
 
    { CPP_IDENTIFIER,     "<ident>" },
117
 
    { CPP_INTCONSTANT,    "<int-const>" },
118
 
    { CPP_LE_OP,          "<=" },
119
 
    { CPP_LEFT_OP,        "<<" },
120
 
    { CPP_LEFT_ASSIGN,    "<<=" },
121
 
    { CPP_LEFT_BRACKET,   "<:" },
122
 
    { CPP_LEFT_BRACE,     "<%" }, 
123
 
    { CPP_DEC_OP,         "--" },
124
 
    { CPP_RIGHT_BRACE,    "%>" }, 
125
 
    { CPP_NE_OP,          "!=" },
126
 
    { CPP_OR_OP,          "||" },
127
 
    { CPP_OR_ASSIGN,      "|=" }, 
128
 
    { CPP_INC_OP,         "++" },
129
 
    { CPP_STRCONSTANT,    "<string-const>" },
130
 
    { CPP_TYPEIDENTIFIER, "<type-ident>" },
131
 
};
132
 
 
133
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
134
 
/*//////////////////////////////////////// String table: ////////////////////////////////////// */
135
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
136
 
 
137
 
#define INIT_STRING_TABLE_SIZE 16384
138
 
 
139
 
typedef struct StringTable_Rec {
140
 
    char *strings;
141
 
    int nextFree;
142
 
    int size;
143
 
} StringTable;
144
 
 
145
 
/*
146
 
 * InitStringTable() - Initialize the string table.
147
 
 *
148
 
 */
149
 
 
150
 
static int InitStringTable(StringTable *stable)
151
 
{
152
 
    stable->strings = (char *) malloc(INIT_STRING_TABLE_SIZE);
153
 
    if (!stable->strings)
154
 
        return 0;
155
 
    /* Zero-th offset means "empty" so don't use it. */
156
 
    stable->nextFree = 1;
157
 
    stable->size = INIT_STRING_TABLE_SIZE;
158
 
    return 1;
159
 
} /* InitStringTable */
160
 
 
161
 
/*
162
 
 * FreeStringTable() - Free the string table.
163
 
 *
164
 
 */
165
 
 
166
 
static void FreeStringTable(StringTable *stable)
167
 
{
168
 
    if (stable->strings)
169
 
        free(stable->strings);
170
 
    stable->strings = NULL;
171
 
    stable->nextFree = 0;
172
 
    stable->size = 0;
173
 
} /* FreeStringTable */
174
 
 
175
 
/*
176
 
 * HashString() - Hash a string with the base hash function.
177
 
 *
178
 
 */
179
 
 
180
 
static int HashString(const char *s)
181
 
{
182
 
    int hval = 0;
183
 
 
184
 
    while (*s) {
185
 
        hval = (hval*13507 + *s*197) ^ (hval >> 2);
186
 
        s++;
187
 
    }
188
 
    return hval & 0x7fffffff;
189
 
} /* HashString */
190
 
 
191
 
/*
192
 
 * HashString2() - Hash a string with the incrimenting hash function.
193
 
 *
194
 
 */
195
 
 
196
 
static int HashString2(const char *s)
197
 
{
198
 
    int hval = 0;
199
 
 
200
 
    while (*s) {
201
 
        hval = (hval*729 + *s*37) ^ (hval >> 1);
202
 
        s++;
203
 
    }
204
 
    return hval;
205
 
} /* HashString2 */
206
 
 
207
 
/*
208
 
 * AddString() - Add a string to a string table.  Return it's offset.
209
 
 *
210
 
 */
211
 
 
212
 
static int AddString(StringTable *stable, const char *s)
213
 
{
214
 
    int len, loc;
215
 
    char *str;
216
 
 
217
 
    len = (int) strlen(s);
218
 
    if (stable->nextFree + len + 1 >= stable->size) {
219
 
        assert(stable->size < 1000000);
220
 
        str = (char *) malloc(stable->size*2);
221
 
        memcpy(str, stable->strings, stable->size);
222
 
        free(stable->strings);
223
 
        stable->strings = str;
224
 
    }
225
 
    loc = stable->nextFree;
226
 
    strcpy(&stable->strings[loc], s);
227
 
    stable->nextFree += len + 1;
228
 
    return loc;
229
 
} /* AddString */
230
 
 
231
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
232
 
/*///////////////////////////////////////// Hash table: /////////////////////////////////////// */
233
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
234
 
 
235
 
#define INIT_HASH_TABLE_SIZE 2047
236
 
#define HASH_TABLE_MAX_COLLISIONS 3
237
 
 
238
 
typedef struct HashEntry_Rec {
239
 
    int index;      /* String table offset of string representation */
240
 
    int value;      /* Atom (symbol) value */
241
 
} HashEntry;
242
 
 
243
 
typedef struct HashTable_Rec {
244
 
    HashEntry *entry;
245
 
    int size;
246
 
    int entries;
247
 
    int counts[HASH_TABLE_MAX_COLLISIONS + 1];
248
 
} HashTable;
249
 
 
250
 
/*
251
 
 * InitHashTable() - Initialize the hash table.
252
 
 *
253
 
 */
254
 
 
255
 
static int InitHashTable(HashTable *htable, int fsize)
256
 
{
257
 
    int ii;
258
 
 
259
 
    htable->entry = (HashEntry *) malloc(sizeof(HashEntry)*fsize);
260
 
    if (!htable->entry)
261
 
        return 0;
262
 
    htable->size = fsize;
263
 
    for (ii = 0; ii < fsize; ii++) {
264
 
        htable->entry[ii].index = 0;
265
 
        htable->entry[ii].value = 0;
266
 
    }
267
 
    htable->entries = 0;
268
 
    for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++)
269
 
        htable->counts[ii] = 0;
270
 
    return 1;
271
 
} /* InitHashTable */
272
 
 
273
 
/*
274
 
 * FreeHashTable() - Free the hash table.
275
 
 *
276
 
 */
277
 
 
278
 
static void FreeHashTable(HashTable *htable)
279
 
{
280
 
    if (htable->entry)
281
 
        free(htable->entry);
282
 
    htable->entry = NULL;
283
 
    htable->size = 0;
284
 
    htable->entries = 0;
285
 
} /* FreeHashTable */
286
 
 
287
 
/*
288
 
 * Empty() - See if a hash table entry is empty.
289
 
 *
290
 
 */
291
 
 
292
 
static int Empty(HashTable *htable, int hashloc)
293
 
{
294
 
    assert(hashloc >= 0 && hashloc < htable->size);
295
 
    if (htable->entry[hashloc].index == 0) {
296
 
        return 1;
297
 
    } else {
298
 
        return 0;
299
 
    }
300
 
} /* Empty */
301
 
 
302
 
/*
303
 
 * Match() - See if a hash table entry is matches a string.
304
 
 *
305
 
 */
306
 
 
307
 
static int Match(HashTable *htable, StringTable *stable, const char *s, int hashloc)
308
 
{
309
 
    int strloc;
310
 
 
311
 
    strloc = htable->entry[hashloc].index;
312
 
    if (!strcmp(s, &stable->strings[strloc])) {
313
 
        return 1;
314
 
    } else {
315
 
        return 0;
316
 
    }
317
 
} /* Match */
318
 
 
319
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
320
 
/*///////////////////////////////////////// Atom table: /////////////////////////////////////// */
321
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
322
 
 
323
 
#define INIT_ATOM_TABLE_SIZE 1024
324
 
 
325
 
 
326
 
struct AtomTable_Rec {
327
 
    StringTable stable; /* String table. */
328
 
    HashTable htable;   /* Hashes string to atom number and token value.  Multiple strings can */
329
 
                        /* have the same token value but each unique string is a unique atom. */
330
 
    int *amap;          /* Maps atom value to offset in string table.  Atoms all map to unique */
331
 
                        /* strings except for some undefined values in the lower, fixed part */
332
 
                        /* of the atom table that map to "<undefined>".  The lowest 256 atoms */
333
 
                        /* correspond to single character ASCII values except for alphanumeric */
334
 
                        /* characters and '_', which can be other tokens.  Next come the */
335
 
                        /* language tokens with their atom values equal to the token value. */
336
 
                        /* Then come predefined atoms, followed by user specified identifiers. */
337
 
    int *arev;          /* Reversed atom for symbol table use. */
338
 
    int nextFree;
339
 
    int size;
340
 
};
341
 
 
342
 
static AtomTable latable = { { 0 } };
343
 
AtomTable *atable = &latable;
344
 
 
345
 
static int AddAtomFixed(AtomTable *atable, const char *s, int atom);
346
 
 
347
 
/*
348
 
 * GrowAtomTable() - Grow the atom table to at least "size" if it's smaller.
349
 
 *
350
 
 */
351
 
 
352
 
static int GrowAtomTable(AtomTable *atable, int size)
353
 
{
354
 
    int *newmap, *newrev;
355
 
 
356
 
    if (atable->size < size) {
357
 
        if (atable->amap) {
358
 
            newmap = realloc(atable->amap, sizeof(int)*size);
359
 
            newrev = realloc(atable->arev, sizeof(int)*size);
360
 
        } else {
361
 
            newmap = malloc(sizeof(int)*size);
362
 
            newrev = malloc(sizeof(int)*size);
363
 
            atable->size = 0;
364
 
        }
365
 
        if (!newmap || !newrev) {
366
 
            /* failed to grow -- error */
367
 
            if (newmap)
368
 
                atable->amap = newmap;
369
 
            if (newrev)
370
 
                atable->amap = newrev;
371
 
            return -1;
372
 
        }
373
 
        memset(&newmap[atable->size], 0, (size - atable->size) * sizeof(int));
374
 
        memset(&newrev[atable->size], 0, (size - atable->size) * sizeof(int));
375
 
        atable->amap = newmap;
376
 
        atable->arev = newrev;
377
 
        atable->size = size;
378
 
    }
379
 
    return 0;
380
 
} /* GrowAtomTable */
381
 
 
382
 
/*
383
 
 * lReverse() - Reverse the bottom 20 bits of a 32 bit int.
384
 
 *
385
 
 */
386
 
 
387
 
static int lReverse(int fval)
388
 
{
389
 
    unsigned int in = fval;
390
 
    int result = 0, cnt = 0;
391
 
 
392
 
    while(in) {
393
 
        result <<= 1;
394
 
        result |= in&1;
395
 
        in >>= 1;
396
 
        cnt++;
397
 
    }
398
 
 
399
 
    /* Don't use all 31 bits.  One million atoms is plenty and sometimes the */
400
 
    /* upper bits are used for other things. */
401
 
 
402
 
    if (cnt < 20)
403
 
        result <<= 20 - cnt;
404
 
    return result;
405
 
} /* lReverse */
406
 
 
407
 
/*
408
 
 * AllocateAtom() - Allocate a new atom.  Associated with the "undefined" value of -1.
409
 
 *
410
 
 */
411
 
 
412
 
static int AllocateAtom(AtomTable *atable)
413
 
{
414
 
    if (atable->nextFree >= atable->size)
415
 
        GrowAtomTable(atable, atable->nextFree*2);
416
 
    atable->amap[atable->nextFree] = -1;
417
 
    atable->arev[atable->nextFree] = lReverse(atable->nextFree);
418
 
    atable->nextFree++;
419
 
    return atable->nextFree - 1;
420
 
} /* AllocateAtom */
421
 
 
422
 
/*
423
 
 * SetAtomValue() - Allocate a new atom associated with "hashindex".
424
 
 *
425
 
 */
426
 
 
427
 
static void SetAtomValue(AtomTable *atable, int atomnumber, int hashindex)
428
 
{
429
 
    atable->amap[atomnumber] = atable->htable.entry[hashindex].index;
430
 
    atable->htable.entry[hashindex].value = atomnumber;
431
 
} /* SetAtomValue */
432
 
 
433
 
/*
434
 
 * FindHashLoc() - Find the hash location for this string.  Return -1 it hash table is full.
435
 
 *
436
 
 */
437
 
 
438
 
static int FindHashLoc(AtomTable *atable, const char *s)
439
 
{
440
 
    int hashloc, hashdelta, count;
441
 
    int FoundEmptySlot = 0;
442
 
    int collision[HASH_TABLE_MAX_COLLISIONS + 1];
443
 
 
444
 
    hashloc = HashString(s) % atable->htable.size;
445
 
    if (!Empty(&atable->htable, hashloc)) {
446
 
        if (Match(&atable->htable, &atable->stable, s, hashloc))
447
 
            return hashloc;
448
 
        collision[0] = hashloc;
449
 
        hashdelta = HashString2(s);
450
 
        count = 0;
451
 
        while (count < HASH_TABLE_MAX_COLLISIONS) {
452
 
            hashloc = ((hashloc + hashdelta) & 0x7fffffff) % atable->htable.size;
453
 
            if (!Empty(&atable->htable, hashloc)) {
454
 
                if (Match(&atable->htable, &atable->stable, s, hashloc)) {
455
 
                    return hashloc;
456
 
                }
457
 
            } else {
458
 
                FoundEmptySlot = 1;
459
 
                break;
460
 
            }
461
 
            count++;
462
 
            collision[count] = hashloc;
463
 
        }
464
 
 
465
 
        if (!FoundEmptySlot) {
466
 
            if (cpp->options.DumpAtomTable) {
467
 
                int ii;
468
 
                char str[200];
469
 
                sprintf(str, "*** Hash failed with more than %d collisions. Must increase hash table size. ***",
470
 
                       HASH_TABLE_MAX_COLLISIONS);
471
 
                CPPShInfoLogMsg(str);
472
 
 
473
 
                sprintf(str, "*** New string \"%s\", hash=%04x, delta=%04x", s, collision[0], hashdelta);
474
 
                CPPShInfoLogMsg(str);
475
 
                for (ii = 0; ii <= HASH_TABLE_MAX_COLLISIONS; ii++) {
476
 
                    sprintf(str, "*** Collides on try %d at hash entry %04x with \"%s\"",
477
 
                           ii + 1, collision[ii], GetAtomString(atable, atable->htable.entry[collision[ii]].value));
478
 
                    CPPShInfoLogMsg(str);
479
 
                }
480
 
            }
481
 
            return -1;
482
 
        } else {
483
 
            atable->htable.counts[count]++;
484
 
        }
485
 
    }
486
 
    return hashloc;
487
 
} /* FindHashLoc */
488
 
 
489
 
/*
490
 
 * IncreaseHashTableSize()
491
 
 *
492
 
 */
493
 
 
494
 
static int IncreaseHashTableSize(AtomTable *atable)
495
 
{
496
 
    int ii, strloc, oldhashloc, value, size;
497
 
    AtomTable oldtable;
498
 
    char *s;
499
 
 
500
 
    /* Save the old atom table and create a new one: */
501
 
 
502
 
    oldtable = *atable;
503
 
    size = oldtable.htable.size*2 + 1;
504
 
    if (!InitAtomTable(atable, size))
505
 
        return 0;
506
 
 
507
 
    /* Add all the existing values to the new atom table preserving their atom values: */
508
 
 
509
 
    for (ii = atable->nextFree; ii < oldtable.nextFree; ii++) {
510
 
        strloc = oldtable.amap[ii];
511
 
        s = &oldtable.stable.strings[strloc];
512
 
        oldhashloc = FindHashLoc(&oldtable, s);
513
 
        assert(oldhashloc >= 0);
514
 
        value = oldtable.htable.entry[oldhashloc].value;
515
 
        AddAtomFixed(atable, s, value);
516
 
    }
517
 
    FreeAtomTable(&oldtable);
518
 
    return 1;
519
 
} /* IncreaseHashTableSize */
520
 
 
521
 
/*
522
 
 * LookUpAddStringHash() - Lookup a string in the hash table.  If it's not there, add it and
523
 
 *        initialize the atom value in the hash table to 0.  Return the hash table index.
524
 
 */
525
 
 
526
 
static int LookUpAddStringHash(AtomTable *atable, const char *s)
527
 
{
528
 
    int hashloc, strloc;
529
 
 
530
 
    while(1) {
531
 
        hashloc = FindHashLoc(atable, s);
532
 
        if (hashloc >= 0)
533
 
            break;
534
 
        IncreaseHashTableSize(atable);
535
 
    }
536
 
 
537
 
    if (Empty(&atable->htable, hashloc)) {
538
 
        atable->htable.entries++;
539
 
        strloc = AddString(&atable->stable, s);
540
 
        atable->htable.entry[hashloc].index = strloc;
541
 
        atable->htable.entry[hashloc].value = 0;
542
 
    }
543
 
    return hashloc;
544
 
} /* LookUpAddStringHash */
545
 
 
546
 
/*
547
 
 * LookUpAddString() - Lookup a string in the hash table.  If it's not there, add it and
548
 
 *        initialize the atom value in the hash table to the next atom number.
549
 
 *        Return the atom value of string.
550
 
 */
551
 
 
552
 
int LookUpAddString(AtomTable *atable, const char *s)
553
 
{
554
 
    int hashindex, atom;
555
 
 
556
 
    hashindex = LookUpAddStringHash(atable, s);
557
 
    atom = atable->htable.entry[hashindex].value;
558
 
    if (atom == 0) {
559
 
        atom = AllocateAtom(atable);
560
 
        SetAtomValue(atable, atom, hashindex);
561
 
    }
562
 
    return atom;
563
 
} /* LookUpAddString */
564
 
 
565
 
/*
566
 
 * GetAtomString()
567
 
 *
568
 
 */
569
 
 
570
 
const  char *GetAtomString(AtomTable *atable, int atom)
571
 
{
572
 
    int soffset;
573
 
 
574
 
    if (atom > 0 && atom < atable->nextFree) {
575
 
        soffset = atable->amap[atom];
576
 
        if (soffset > 0 && soffset < atable->stable.nextFree) {
577
 
            return &atable->stable.strings[soffset];
578
 
        } else {
579
 
            return "<internal error: bad soffset>";
580
 
        }
581
 
    } else {
582
 
        if (atom == 0) {
583
 
            return "<null atom>";
584
 
        } else {
585
 
            if (atom == EOF) {
586
 
                return "<EOF>";
587
 
            } else {
588
 
                return "<invalid atom>";
589
 
            }
590
 
        }
591
 
    }
592
 
} /* GetAtomString */
593
 
 
594
 
/*
595
 
 * GetReversedAtom()
596
 
 *
597
 
 */
598
 
 
599
 
int GetReversedAtom(AtomTable *atable, int atom)
600
 
{
601
 
    if (atom > 0 && atom < atable->nextFree) {
602
 
        return atable->arev[atom];
603
 
    } else {
604
 
        return 0;
605
 
    }
606
 
} /* GetReversedAtom */
607
 
 
608
 
/*
609
 
 * AddAtom() - Add a string to the atom, hash and string tables if it isn't already there.
610
 
 *         Return it's atom index.
611
 
 */
612
 
 
613
 
int AddAtom(AtomTable *atable, const char *s)
614
 
{
615
 
    int atom;
616
 
 
617
 
    atom = LookUpAddString(atable, s);
618
 
    return atom;
619
 
} /* AddAtom */
620
 
 
621
 
/*
622
 
 * AddAtomFixed() - Add an atom to the hash and string tables if it isn't already there.
623
 
 *         Assign it the atom value of "atom".
624
 
 */
625
 
 
626
 
static int AddAtomFixed(AtomTable *atable, const char *s, int atom)
627
 
{
628
 
    int hashindex, lsize;
629
 
 
630
 
    hashindex = LookUpAddStringHash(atable, s);
631
 
    if (atable->nextFree >= atable->size || atom >= atable->size) {
632
 
        lsize = atable->size*2;
633
 
        if (lsize <= atom)
634
 
            lsize = atom + 1;
635
 
        GrowAtomTable(atable, lsize);
636
 
    }
637
 
    atable->amap[atom] = atable->htable.entry[hashindex].index;
638
 
    atable->htable.entry[hashindex].value = atom;
639
 
    /*if (atom >= atable->nextFree) */
640
 
    /*    atable->nextFree = atom + 1; */
641
 
    while (atom >= atable->nextFree) {
642
 
        atable->arev[atable->nextFree] = lReverse(atable->nextFree);
643
 
        atable->nextFree++;
644
 
    }
645
 
    return atom;
646
 
} /* AddAtomFixed */
647
 
 
648
 
/*
649
 
 * InitAtomTable() - Initialize the atom table.
650
 
 *
651
 
 */
652
 
 
653
 
int InitAtomTable(AtomTable *atable, int htsize)
654
 
{
655
 
    int ii;
656
 
 
657
 
    htsize = htsize <= 0 ? INIT_HASH_TABLE_SIZE : htsize;
658
 
    if (!InitStringTable(&atable->stable))
659
 
        return 0;
660
 
    if (!InitHashTable(&atable->htable, htsize))
661
 
        return 0;
662
 
 
663
 
    atable->nextFree = 0;
664
 
    atable->amap = NULL;
665
 
    atable->size = 0;
666
 
    GrowAtomTable(atable, INIT_ATOM_TABLE_SIZE);
667
 
    if (!atable->amap)
668
 
        return 0;
669
 
 
670
 
    /* Initialize lower part of atom table to "<undefined>" atom: */
671
 
 
672
 
    AddAtomFixed(atable, "<undefined>", 0);
673
 
    for (ii = 0; ii < FIRST_USER_TOKEN_SY; ii++)
674
 
        atable->amap[ii] = atable->amap[0];
675
 
 
676
 
    /* Add single character tokens to the atom table: */
677
 
 
678
 
    {
679
 
                const char *s = "~!%^&*()-+=|,.<>/?;:[]{}#";
680
 
        char t[2];
681
 
 
682
 
        t[1] = '\0';
683
 
        while (*s) {
684
 
            t[0] = *s;
685
 
            AddAtomFixed(atable, t, s[0]);
686
 
            s++;
687
 
        }
688
 
    }
689
 
 
690
 
    /* Add multiple character scanner tokens : */
691
 
 
692
 
    for (ii = 0; ii < sizeof(tokens)/sizeof(tokens[0]); ii++)
693
 
        AddAtomFixed(atable, tokens[ii].str, tokens[ii].val);
694
 
 
695
 
    /* Add error symbol if running in error mode: */
696
 
 
697
 
    if (cpp->options.ErrorMode)
698
 
        AddAtomFixed(atable, "error", ERROR_SY);
699
 
 
700
 
    AddAtom(atable, "<*** end fixed atoms ***>");
701
 
 
702
 
    return 1;
703
 
} /* InitAtomTable */
704
 
 
705
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
706
 
/*//////////////////////////////// Debug Printing Functions: ////////////////////////////////// */
707
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
708
 
 
709
 
/*
710
 
 * PrintAtomTable()
711
 
 *
712
 
 */
713
 
 
714
 
void PrintAtomTable(AtomTable *atable)
715
 
{
716
 
    int ii;
717
 
    char str[200];
718
 
 
719
 
    for (ii = 0; ii < atable->nextFree; ii++) {
720
 
        sprintf(str, "%d: \"%s\"", ii, &atable->stable.strings[atable->amap[ii]]);
721
 
        CPPDebugLogMsg(str);
722
 
    }
723
 
    sprintf(str, "Hash table: size=%d, entries=%d, collisions=",
724
 
           atable->htable.size, atable->htable.entries);
725
 
    CPPDebugLogMsg(str);
726
 
    for (ii = 0; ii < HASH_TABLE_MAX_COLLISIONS; ii++) {
727
 
        sprintf(str, " %d", atable->htable.counts[ii]);
728
 
        CPPDebugLogMsg(str);
729
 
    }
730
 
 
731
 
} /* PrintAtomTable */
732
 
 
733
 
 
734
 
/*
735
 
 * GetStringOfAtom()
736
 
 *
737
 
 */
738
 
 
739
 
char* GetStringOfAtom(AtomTable *atable, int atom)
740
 
{
741
 
         char* chr_str;
742
 
         chr_str=&atable->stable.strings[atable->amap[atom]];
743
 
         return chr_str;
744
 
} /* GetStringOfAtom */
745
 
 
746
 
/*
747
 
 * FreeAtomTable() - Free the atom table and associated memory
748
 
 *
749
 
 */
750
 
 
751
 
void FreeAtomTable(AtomTable *atable)
752
 
{
753
 
    FreeStringTable(&atable->stable);
754
 
    FreeHashTable(&atable->htable);
755
 
    if (atable->amap)
756
 
        free(atable->amap);
757
 
    if (atable->arev)
758
 
        free(atable->arev);
759
 
    atable->amap = NULL;
760
 
    atable->arev = NULL;
761
 
    atable->nextFree = 0;
762
 
    atable->size = 0;
763
 
} /* FreeAtomTable */
764
 
 
765
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
766
 
/*/////////////////////////////////////// End of atom.c /////////////////////////////////////// */
767
 
/*///////////////////////////////////////////////////////////////////////////////////////////// */
768