1 /* $Id: symtabs.c,v 1.19 2011/01/22 22:08:23 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * These definitions are used in the patricia tree that stores
36 #define LEFT_IS_LEAF 0x80000000
37 #define RIGHT_IS_LEAF 0x40000000
38 #define IS_LEFT_LEAF(x) (((x) & LEFT_IS_LEAF) != 0)
39 #define IS_RIGHT_LEAF(x) (((x) & RIGHT_IS_LEAF) != 0)
40 #define BITNO(x) ((x) & ~(LEFT_IS_LEAF|RIGHT_IS_LEAF))
48 static struct tree
*firstname
;
49 int nametabs
, namestrlen
;
50 static struct tree
*firststr
;
51 int strtabs
, strstrlen
;
52 static char *symtab_add(char *key
, struct tree
**, int *, int *);
54 #define P_BIT(key, bit) (key[bit >> 3] >> (bit & 7)) & 1
55 #define getree() permalloc(sizeof(struct tree))
60 return symtab_add(key
, &firstname
, &nametabs
, &namestrlen
);
66 return symtab_add(key
, &firststr
, &strtabs
, &strstrlen
);
70 * Add a name to the name stack (if its non-existing),
72 * This is a simple patricia implementation.
75 symtab_add(char *key
, struct tree
**first
, int *tabs
, int *stlen
)
77 struct tree
*w
, *new, *last
;
78 int cix
, bit
, fbit
, svbit
, ix
, bitno
, len
;
81 /* Count full string length */
82 for (k
= key
, len
= 0; *k
; k
++, len
++)
87 *first
= (struct tree
*)newstring(key
, len
);
90 return (char *)*first
;
94 svbit
= 0; /* XXX why? */
99 bitno
= len
* CHECKBITS
;
101 bit
= BITNO(w
->bitno
);
102 fbit
= bit
> bitno
? 0 : P_BIT(key
, bit
);
103 svbit
= fbit
? IS_RIGHT_LEAF(w
->bitno
) :
104 IS_LEFT_LEAF(w
->bitno
);
116 /* Check for correct string and return */
117 for (cix
= 0; *m
&& *k
&& *m
== *k
; m
++, k
++, cix
+= CHECKBITS
)
119 if (*m
== 0 && *k
== 0)
123 while ((ix
& 1) == 0)
126 /* Create new node */
128 bit
= P_BIT(key
, cix
);
129 new->bitno
= cix
| (bit
? RIGHT_IS_LEAF
: LEFT_IS_LEAF
);
130 new->lr
[bit
] = (struct tree
*)newstring(key
, len
);
133 if ((*tabs
)++ == 1) {
134 new->lr
[!bit
] = *first
;
135 new->bitno
|= (bit
? LEFT_IS_LEAF
: RIGHT_IS_LEAF
);
137 return (char *)new->lr
[bit
];
145 bitno
= BITNO(w
->bitno
);
147 cerror("bitno == cix");
150 svbit
= P_BIT(key
, bitno
);
153 if (fbit
& (svbit
? RIGHT_IS_LEAF
: LEFT_IS_LEAF
))
161 last
->lr
[svbit
] = new;
162 last
->bitno
&= ~(svbit
? RIGHT_IS_LEAF
: LEFT_IS_LEAF
);
165 new->bitno
|= (bit
? LEFT_IS_LEAF
: RIGHT_IS_LEAF
);
166 return (char *)new->lr
[bit
];
169 static struct tree
*sympole
[NSTYPES
];
170 static struct symtab
*tmpsyms
[NSTYPES
];
171 int numsyms
[NSTYPES
];
174 * Inserts a symbol into the symbol tree.
175 * Returns a struct symtab.
178 lookup(char *key
, int stype
)
181 struct tree
*w
, *new, *last
;
182 int cix
, bit
, fbit
, svbit
, bitno
;
184 intptr_t ix
, match
, code
= (intptr_t)key
;
186 type
= stype
& SMASK
;
187 uselvl
= (blevel
> 0 && type
!= SSTRING
);
190 * The local symbols are kept in a simple linked list.
191 * Check this list first.
194 for (sym
= tmpsyms
[type
]; sym
; sym
= sym
->snext
)
195 if (sym
->sname
== key
)
198 switch (numsyms
[type
]) {
200 if (stype
& SNOCREAT
)
203 sym
= getsymtab(key
, stype
|STEMP
);
204 sym
->snext
= tmpsyms
[type
];
208 sympole
[type
] = (struct tree
*)getsymtab(key
, stype
);
210 return (struct symtab
*)sympole
[type
];
213 w
= (struct tree
*)sympole
[type
];
214 svbit
= 0; /* XXX why? */
220 bit
= BITNO(w
->bitno
);
221 fbit
= (code
>> bit
) & 1;
222 svbit
= fbit
? IS_RIGHT_LEAF(w
->bitno
) :
223 IS_LEFT_LEAF(w
->bitno
);
230 sym
= (struct symtab
*)w
;
231 match
= (intptr_t)sym
->sname
;
236 else if (stype
& SNOCREAT
)
241 printf(" adding %s as %s at level %d\n",
242 key
, uselvl
? "temp" : "perm", blevel
);
246 * Insert into the linked list, if feasible.
249 sym
= getsymtab(key
, stype
|STEMP
);
250 sym
->snext
= tmpsyms
[type
];
256 * Need a new node. If type is SNORMAL and inside a function
257 * the node must be allocated as permanent anyway.
258 * This could be optimized by adding a remove routine, but it
259 * may be more trouble than it is worth.
261 if (stype
== (STEMP
|SNORMAL
))
264 for (cix
= 0; (ix
& 1) == 0; ix
>>= 1, cix
++)
267 new = stype
& STEMP
? tmpalloc(sizeof(struct tree
)) :
268 permalloc(sizeof(struct tree
));
269 bit
= (code
>> cix
) & 1;
270 new->bitno
= cix
| (bit
? RIGHT_IS_LEAF
: LEFT_IS_LEAF
);
271 new->lr
[bit
] = (struct tree
*)getsymtab(key
, stype
);
272 if (numsyms
[type
]++ == 1) {
273 new->lr
[!bit
] = sympole
[type
];
274 new->bitno
|= (bit
? LEFT_IS_LEAF
: RIGHT_IS_LEAF
);
276 return (struct symtab
*)new->lr
[bit
];
284 bitno
= BITNO(w
->bitno
);
286 cerror("bitno == cix");
289 svbit
= (code
>> bitno
) & 1;
292 if (fbit
& (svbit
? RIGHT_IS_LEAF
: LEFT_IS_LEAF
))
300 last
->lr
[svbit
] = new;
301 last
->bitno
&= ~(svbit
? RIGHT_IS_LEAF
: LEFT_IS_LEAF
);
304 new->bitno
|= (bit
? LEFT_IS_LEAF
: RIGHT_IS_LEAF
);
305 return (struct symtab
*)new->lr
[bit
];
316 printf("symclear(%d)\n", level
);
319 for (i
= 0; i
< NSTYPES
; i
++) {
326 uerror("label '%s' undefined",s
->sname
);
331 for (i
= 0; i
< NSTYPES
; i
++) {
333 continue; /* function scope */
334 while (tmpsyms
[i
] != NULL
&&
335 tmpsyms
[i
]->slevel
> level
) {
336 tmpsyms
[i
] = tmpsyms
[i
]->snext
;
343 hide(struct symtab
*sym
)
346 int typ
= sym
->sflags
& SMASK
;
348 new = getsymtab(sym
->sname
, typ
|STEMP
);
349 new->snext
= tmpsyms
[typ
];
352 warner(Wshadow
, sym
->sname
, sym
->slevel
? "local" : "global");
356 printf("\t%s hidden at level %d (%p -> %p)\n",
357 sym
->sname
, blevel
, sym
, new);