xref: /illumos-gate/usr/src/cmd/abi/spectrans/spec2trace/symtab.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1997-1999 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #include <stdio.h>
28 #include <string.h>
29 #include <limits.h>
30 #include <malloc.h>
31 #include "parser.h"
32 #include "trace.h"
33 #include "util.h"
34 #include "symtab.h"
35 #include "errlog.h"
36 
37 /* Types */
38 enum kind_t { PRIMITIVE = 0, COMPOSITE, VARARG };
39 
40 struct entry_t {
41 	char	*e_name;
42 	int	e_valid;
43 	int	e_line;
44 	char	*e_file;
45 	int	e_kind;		/* PRIMITIVE, COMPOSITE... */
46 	char	*e_type;	/* where kind == PRIMITIVE */
47 	/* base type, ie. char if e_type is char */
48 	char	*e_basetype;
49 	int	e_levels;	/* levels of indirection */
50 	char	*e_attribute;	/* kind == COMPOSITE or VARARG. */
51 	char	*e_assertion;	/* reserved for kind == VARARG. */
52 	char	*e_comment;	/* reserved for per-element comments. */
53 	int	e_pre_uses;
54 	int	e_post_uses;
55 };
56 
57 typedef struct entry_head_t {
58 	int	used;
59 	int	n_entries;
60 	ENTRY	entry[1]; /* Actually entry[n_entries]. */
61 } EHEAD;
62 
63 static struct symtab_t {
64 	ENTRY	*Function;
65 	EHEAD	*Args;
66 	EHEAD	*Varargs;
67 	EHEAD	*Globals;
68 	ENTRY	*Errval;
69 
70 	/* Includes */
71 	table_t	*Includes;
72 
73 	/* Bindings */
74 	ENTRY	*Exception;
75 
76 	/* Types */
77 	table_t	*Print_Types;
78 
79 	/* Error-message information. */
80 	int	Line;
81 	char	Filename[MAXLINE];
82 
83 	/* Trace additions */
84 	char	Prototype[MAXLINE];
85 	char	Formals[MAXLINE];
86 	char	Actuals[MAXLINE];
87 	char	Cast[MAXLINE];
88 	int	Nonreturn;
89 	int	Skip;
90 
91 	/* Adl additions */
92 	/* various assertions, one hopes */
93 } Symtab;
94 
95 /* File Globals. */
96 static EHEAD *create_entry_table(int);
97 static EHEAD *add_entry_table(EHEAD *,
98 	char *, int, char *, int, char *, char *, int, char *, int, int);
99 static ENTRY *get_entry_table(EHEAD *, int);
100 static EHEAD *free_entry_table(EHEAD *);
101 static void clear_entries(EHEAD *, int, int);
102 static ENTRY *allocate_entry(ENTRY *, char *, int, char *, int,
103     char *, char *, int, char *, int, int);
104 static ENTRY *set_entry(ENTRY *,
105 	char *, int, char *, int, char *, char *, int, char *, int, int);
106 static ENTRY *free_entry(ENTRY *);
107 static void symtab_clear_varargs(void);
108 static void symtab_clear_globals(void);
109 static void symtab_clear_print_types(void);
110 static void symtab_set_nonreturn(int);
111 static table_t *symtab_free_print_types(table_t *);
112 
113 /*
114  * symtab_new_function -- clear counts, variables for a new function.
115  */
116 void
117 symtab_new_function(const int line, const char *file)
118 {
119 	errlog(BEGIN, "symtab_new_function() {");
120 	Symtab.Line = line;	/* Set, don't clear. */
121 	symtab_set_filename(file);
122 
123 	symtab_clear_function();
124 	symtab_clear_varargs();
125 	symtab_clear_globals();
126 	symtab_clear_errval();
127 	symtab_clear_exception();
128 	symtab_clear_print_types();
129 
130 	symtab_set_nonreturn(NO);
131 	symtab_set_skip(NO);
132 	errlog(END, "}");
133 }
134 
135 
136 /*
137  * symtab_clear_function -- clear function-prototype-derived
138  *	values. Called on each prototype line and at beginning
139  *	of interface.
140  */
141 void
142 symtab_clear_function(void)
143 {
144 
145 	errlog(BEGIN, "symtab_clear_function() {");
146 	Symtab.Function = free_entry(Symtab.Function);
147 	Symtab.Args = free_entry_table(Symtab.Args);
148 	Symtab.Prototype[0] = '\0';
149 	Symtab.Formals[0] = '\0';
150 	Symtab.Actuals[0] = '\0';
151 	Symtab.Cast[0] = '\0';
152 	errlog(END, "}");
153 }
154 
155 
156 /*
157  * symtab_clear_varargs -- called only at end
158  */
159 static void
160 symtab_clear_varargs(void)
161 {
162 
163 	errlog(BEGIN, "symtab_clear_varargs() {");
164 	Symtab.Varargs = free_entry_table(Symtab.Varargs);
165 	errlog(END, "}");
166 }
167 
168 /*
169  * symtab_clear_includes -- clear only at end of file (union++)
170  */
171 void
172 symtab_clear_includes(void)
173 {
174 
175 	errlog(BEGIN, "symtab_clear_includes() {");
176 	Symtab.Includes = free_string_table(Symtab.Includes);
177 	errlog(END, "}");
178 }
179 
180 static void
181 symtab_clear_globals(void)
182 {
183 
184 	errlog(BEGIN, "symtab_clear_globals() {");
185 	Symtab.Globals = free_entry_table(Symtab.Globals);
186 	errlog(END, "}");
187 }
188 
189 void
190 symtab_clear_errval(void)
191 {
192 
193 	errlog(BEGIN, "symtab_clear_errval() {");
194 	Symtab.Errval = free_entry(Symtab.Errval);
195 	errlog(END, "}");
196 }
197 
198 void
199 symtab_clear_exception(void)
200 {
201 
202 	errlog(BEGIN, "symtab_clear_exception() {");
203 	Symtab.Exception = free_entry(Symtab.Exception);
204 	errlog(END, "}");
205 }
206 
207 static void
208 symtab_clear_print_types(void)
209 {
210 
211 	errlog(BEGIN, "symtab_clear_print_types() {");
212 	Symtab.Print_Types = symtab_free_print_types(Symtab.Print_Types);
213 	errlog(END, "}");
214 }
215 
216 
217 /* Generated by m4 -- character string values */
218 
219 void
220 symtab_set_prototype(char *p)
221 {
222 
223 	errlog(BEGIN, "symtab_set_prototype(void) {");
224 	(void) strncpy(Symtab.Prototype, p, sizeof (Symtab.Prototype));
225 	Symtab.Prototype[sizeof (Symtab.Prototype)-1] = '\0';
226 	errlog(END, "}");
227 }
228 
229 char *
230 symtab_get_prototype(void)
231 {
232 	errlog(BEGIN, "symtab_get_prototype() {"); errlog(END, "}");
233 	return (Symtab.Prototype);
234 }
235 
236 void
237 symtab_set_formals(char *p)
238 {
239 	errlog(BEGIN, "symtab_set_formals() {");
240 	errlog(VERBOSE, "p = %s", p);
241 	(void) strncpy(Symtab.Formals, p, sizeof (Symtab.Formals));
242 	Symtab.Formals[sizeof (Symtab.Formals)-1] = '\0';
243 	errlog(END, "}");
244 }
245 
246 char *
247 symtab_get_formals(void)
248 {
249 	errlog(BEGIN, "symtab_get_formals() {"); errlog(END, "}");
250 	return (Symtab.Formals);
251 }
252 
253 void
254 symtab_set_actuals(char *p)
255 {
256 	errlog(BEGIN, "symtab_set_actuals() {"); errlog(END, "}");
257 	errlog(VERBOSE, "p = %s", p);
258 	(void) strncpy(Symtab.Actuals, p, sizeof (Symtab.Actuals));
259 	Symtab.Actuals[sizeof (Symtab.Actuals)-1] = '\0';
260 }
261 
262 char *
263 symtab_get_actuals(void)
264 {
265 	errlog(BEGIN, "symtab_get_actuals() {"); errlog(END, "}");
266 	return (Symtab.Actuals);
267 }
268 
269 void
270 symtab_set_cast(char *p)
271 {
272 	errlog(BEGIN, "symtab_set_cast() {"); errlog(END, "}");
273 	(void) strncpy(Symtab.Cast, p, sizeof (Symtab.Cast));
274 	Symtab.Cast[sizeof (Symtab.Cast)-1] = '\0';
275 }
276 
277 char *
278 symtab_get_cast(void)
279 {
280 	errlog(BEGIN, "symtab_get_cast() {"); errlog(END, "}");
281 	return (Symtab.Cast);
282 }
283 
284 
285 void
286 symtab_set_filename(const char *p)
287 {
288 	errlog(BEGIN, "symtab_set_filename() {"); errlog(END, "}");
289 	(void) strncpy(Symtab.Filename, p, sizeof (Symtab.Filename));
290 	Symtab.Filename[sizeof (Symtab.Filename)-1] = '\0';
291 }
292 
293 char *
294 symtab_get_filename(void)
295 {
296 	errlog(BEGIN, "symtab_get_filename() {"); errlog(END, "}");
297 	return (Symtab.Filename);
298 }
299 
300 
301 /* Generated by m4 -- int values */
302 
303 static void
304 symtab_set_nonreturn(int val)
305 {
306 	errlog(BEGIN, "symtab_set_nonreturn() {"); errlog(END, "}");
307 	Symtab.Nonreturn = val;
308 }
309 
310 int
311 symtab_get_nonreturn(void)
312 {
313 	errlog(BEGIN, "symtab_get_nonreturn() {"); errlog(END, "}");
314 	return (Symtab.Nonreturn);
315 }
316 
317 void
318 symtab_set_line(int val)
319 {
320 	errlog(BEGIN, "symtab_set_line() {"); errlog(END, "}");
321 	Symtab.Line = val;
322 }
323 
324 int
325 symtab_get_line(void)
326 {
327 	errlog(BEGIN, "symtab_get_line() {"); errlog(END, "}");
328 	return (Symtab.Line);
329 }
330 
331 
332 void
333 symtab_set_skip(int value)
334 {
335 	errlog(BEGIN, "symtab_set_skip() {"); errlog(END, "}");
336 	Symtab.Skip = value;
337 }
338 
339 int
340 symtab_get_skip(void)
341 {
342 	errlog(BEGIN, "symtab_get_skip() {"); errlog(END, "}");
343 	return (Symtab.Skip);
344 }
345 
346 /*
347  * Manually written access functions for ENTRY * variables.
348  */
349 
350 void
351 symtab_set_function(char *name, int line, char *file,
352     char *type, char *basetype, int levels)
353 {
354 
355 	errlog(BEGIN, "symtab_set_function() {");
356 	Symtab.Function = allocate_entry(Symtab.Function,
357 	    name, line, file, PRIMITIVE, type, basetype, levels, "", -1, -1);
358 	errlog(END, "}");
359 }
360 
361 ENTRY *
362 symtab_get_function(void)
363 {
364 	errlog(BEGIN, "symtab_get_function() {"); errlog(END, "}");
365 	if (Symtab.Function == NULL)
366 		return (NULL);
367 	else
368 		return ((Symtab.Function->e_valid)? Symtab.Function: NULL);
369 }
370 
371 void
372 symtab_set_exception(char *value, int line, char *file)
373 {
374 
375 	errlog(BEGIN, "symtab_set_exception() {");
376 	Symtab.Exception = allocate_entry(Symtab.Exception,
377 		value, line, file, COMPOSITE, "", "", 0, "", -1, -1);
378 	errlog(END, "}");
379 }
380 
381 ENTRY *
382 symtab_get_exception(void)
383 {
384 
385 	errlog(BEGIN, "symtab_get_exception() {"); errlog(END, "}");
386 	if (Symtab.Exception == NULL)
387 		return (NULL);
388 	else
389 		return ((Symtab.Exception->e_valid)? Symtab.Exception: NULL);
390 }
391 
392 void
393 symtab_set_errval(char *name, int line, char *file, char *type, char *basetype,
394     int levels)
395 {
396 
397 	errlog(BEGIN, "symtab_set_errval() {");
398 	Symtab.Errval = allocate_entry(Symtab.Errval,
399 	    name, line, file, PRIMITIVE, type, basetype, levels,
400 	    "", -1, -1);
401 	errlog(END, "}");
402 }
403 
404 ENTRY *
405 symtab_get_errval(void)
406 {
407 
408 	errlog(BEGIN, "symtab_get_errval() {"); errlog(END, "}");
409 	if (Symtab.Errval == NULL)
410 		return (NULL);
411 	else
412 		return ((Symtab.Errval->e_valid)? Symtab.Errval: NULL);
413 }
414 
415 /*
416  * Manually written  access function for tables of ENTRYs
417  */
418 void
419 symtab_add_args(char *name, int line, char *file,
420     char *type, char *basetype, int levels)
421 {
422 
423 	errlog(BEGIN, "symtab_add_args() {");
424 	if (Symtab.Args == NULL) {
425 		Symtab.Args = create_entry_table(10);
426 	}
427 	Symtab.Args = add_entry_table(Symtab.Args,
428 	    name, line, file, PRIMITIVE, type, basetype, levels, "", -1, -1);
429 	errlog(END, "}");
430 }
431 
432 static int curr_arg;
433 
434 ENTRY *
435 symtab_get_first_arg(void)
436 {
437 
438 	errlog(BEGIN, "symtab_get_first_arg() {"); errlog(END, "}");
439 	curr_arg = 1;
440 	return (get_entry_table(Symtab.Args, 0));
441 }
442 
443 ENTRY *
444 symtab_get_next_arg(void)
445 {
446 
447 	errlog(BEGIN, "symtab_get_next_arg() {"); errlog(END, "}");
448 	return (get_entry_table(Symtab.Args, curr_arg++));
449 }
450 
451 ENTRY *
452 symtab_get_last_arg(void)
453 {
454 
455 	errlog(BEGIN, "symtab_get_last_arg() {"); errlog(END, "}");
456 	return (get_entry_table(Symtab.Args, Symtab.Args->used));
457 }
458 
459 void
460 symtab_add_varargs(char *name, int line, char *file, char *type, char *print)
461 {
462 
463 	errlog(BEGIN, "symtab_add_varargs() {");
464 	if (Symtab.Varargs == NULL) {
465 		Symtab.Varargs = create_entry_table(10);
466 	}
467 	Symtab.Varargs = add_entry_table(Symtab.Varargs,
468 		name, line, file, PRIMITIVE, type, print, 0, "", -1, -1);
469 	errlog(END, "}");
470 }
471 
472 static int curr_vararg;
473 
474 ENTRY *
475 symtab_get_first_vararg(void)
476 {
477 
478 	errlog(BEGIN, "symtab_get_first_vararg() {"); errlog(END, "}");
479 	curr_vararg = 1;
480 	return (get_entry_table(Symtab.Varargs, 0));
481 }
482 
483 ENTRY *
484 symtab_get_next_vararg(void)
485 {
486 
487 	errlog(BEGIN, "symtab_get_next_vararg() {"); errlog(END, "}");
488 	return (get_entry_table(Symtab.Varargs, curr_vararg++));
489 }
490 
491 void
492 symtab_add_globals(char *name, int line, char *file, char *type,
493     char *basetype, int levels)
494 {
495 
496 	errlog(BEGIN, "symtab_add_globals() {");
497 	if (Symtab.Globals == NULL) {
498 		Symtab.Globals = create_entry_table(10);
499 	}
500 	Symtab.Globals = add_entry_table(Symtab.Globals,
501 	    name, line, file, PRIMITIVE, type, basetype, levels, "", -1, -1);
502 	errlog(END, "}");
503 }
504 
505 
506 static int curr_global;
507 
508 ENTRY *
509 symtab_get_first_global(void)
510 {
511 
512 	errlog(BEGIN, "symtab_get_first_global() {"); errlog(END, "}");
513 	curr_global = 1;
514 	return (get_entry_table(Symtab.Globals, 0));
515 }
516 
517 ENTRY *
518 symtab_get_next_global(void)
519 {
520 
521 	errlog(BEGIN, "symtab_get_next_global() {"); errlog(END, "}");
522 	return (get_entry_table(Symtab.Globals, curr_global++));
523 }
524 
525 /*
526  * manually written functions for accessing tables of strings
527  */
528 
529 /*
530  * symtab_add_print_types -- add only non-void print types (due to
531  *	parser errors in collect.c, yuck). Also note trick compare...
532  *	TBD : common code in db, symtab needs to be
533  *	pulled out, as they're getting out of sync.
534  */
535 void
536 symtab_add_print_types(char *print_type, char *c_type)
537 {
538 	char	buffer[MAXLINE];
539 
540 	errlog(BEGIN, "symtab_add_print_types() {");
541 #ifdef notdef
542 	if (strcmp(print_type, "void") == 0 || *print_type == NULL) {
543 		errlog(END, "}");
544 		return;
545 	}
546 #endif
547 	(void) snprintf(buffer, sizeof (buffer), "%s, %s", print_type, c_type);
548 	if (Symtab.Print_Types == NULL) {
549 	Symtab.Print_Types = create_string_table(50);
550 	}
551 	if (in_string_table(Symtab.Print_Types, print_type) == NO) {
552 		Symtab.Print_Types = add_string_table(Symtab.Print_Types,
553 					&buffer[0]);
554 	}
555 	errlog(END, "}");
556 }
557 
558 static table_t *
559 symtab_free_print_types(table_t *t)
560 {
561 	errlog(BEGIN, "symtab_free_print_types() {"); errlog(END, "}");
562 	return (free_string_table(t));
563 }
564 
565 
566 static int curr_print_type;
567 
568 char *
569 symtab_get_first_print_type(void)
570 {
571 
572 	errlog(BEGIN, "symtab_get_first_print_type() {"); errlog(END, "}");
573 	curr_print_type = 1;
574 	return (get_string_table(Symtab.Print_Types, 0));
575 }
576 
577 char *
578 symtab_get_next_print_type(void)
579 {
580 
581 	errlog(BEGIN, "symtab_get_next_print_type() {"); errlog(END, "}");
582 	return (get_string_table(Symtab.Print_Types, curr_print_type++));
583 }
584 
585 void
586 symtab_add_includes(char *value)
587 {
588 
589 	errlog(BEGIN, "symtab_add_includes() {");
590 	if (Symtab.Includes == NULL) {
591 		Symtab.Includes = create_string_table(50);
592 	}
593 	if (in_string_table(Symtab.Includes, value) == NO) {
594 		Symtab.Includes = add_string_table(Symtab.Includes, value);
595 	}
596 	errlog(END, "}");
597 }
598 
599 static int curr_include;
600 
601 char *
602 symtab_get_first_include(void)
603 {
604 
605 	errlog(BEGIN, "symtab_get_first_include() {"); errlog(END, "}");
606 	curr_include = 1;
607 	return (get_string_table(Symtab.Includes, 0));
608 }
609 
610 char *
611 symtab_get_next_include(void)
612 {
613 
614 	errlog(BEGIN, "symtab_get_next_include() {"); errlog(END, "}");
615 	return (get_string_table(Symtab.Includes, curr_include++));
616 }
617 
618 
619 void
620 symtab_sort_includes(void)
621 {
622 	errlog(BEGIN, "symtab_sort_includes() {");
623 	sort_string_table(Symtab.Includes);
624 	errlog(END, "}");
625 }
626 
627 /*
628  * ENTRYs  -- access functions to contents of an entry.
629  */
630 
631 char *
632 name_of(ENTRY *e)
633 {
634 	return (e->e_name);
635 }
636 
637 int
638 validity_of(ENTRY *e)
639 {
640 
641 	if (e == NULL)
642 		return (NO);
643 	else
644 		return (e->e_valid);
645 }
646 
647 int
648 line_of(ENTRY *e)
649 {
650 	return (e->e_line);
651 }
652 
653 
654 char *
655 file_of(ENTRY *e)
656 {
657 	return (e->e_file);
658 }
659 
660 /*
661  * x_type_of -- return (type with an extension: an embedded %s where
662  *	the name goes.
663  */
664 char *
665 x_type_of(ENTRY *e)
666 {
667 	if (e != NULL && (e->e_kind == PRIMITIVE || e->e_kind == VARARG))
668 		return (e->e_type);
669 	else
670 		return (NULL);
671 }
672 
673 
674 /*
675  * type_of -- return (just the type, with the %s removed. This is the common
676  *	case, and its also the slowest... TBD.
677  */
678 char *
679 type_of(ENTRY *e)
680 {
681 	static char buffer[MAXLINE];
682 	char	*p, *q;
683 
684 	if (e != NULL && (e->e_kind == PRIMITIVE || e->e_kind == VARARG)) {
685 		p = e->e_type;
686 		q = &buffer[0];
687 		while (*p != '\0') {
688 			if (*p == '%') {
689 				p += 2;
690 			} else {
691 				*q++ = *p++;
692 			}
693 		}
694 		*q = '\0';
695 		return (strtrim(&buffer[0]));
696 	}
697 	else
698 		return (NULL);
699 }
700 
701 char *
702 basetype_of(ENTRY *e)
703 {
704 	if (e != NULL && (e->e_kind == PRIMITIVE || e->e_kind == VARARG))
705 		return (e->e_basetype);
706 	else
707 		return (NULL);
708 }
709 
710 int
711 levels_of(ENTRY *e)
712 {
713 	if (e != NULL && (e->e_kind == PRIMITIVE || e->e_kind == VARARG))
714 		return (e->e_levels);
715 	else
716 		return (0);
717 }
718 
719 char *
720 inverse_of(ENTRY *e)
721 {
722 
723 	if (e != NULL && e->e_kind == COMPOSITE)
724 		return (e->e_attribute);
725 	else
726 		return (NULL);
727 }
728 
729 char *
730 selector_of(ENTRY *e)
731 {
732 
733 	if (e != NULL && e->e_kind == VARARG)
734 		return (e->e_attribute);
735 	else
736 		return (NULL);
737 }
738 
739 int
740 preuses_of(ENTRY *e)
741 {
742 
743 	if (e)
744 		return (e->e_pre_uses);
745 	else
746 		return (-1);
747 }
748 
749 int
750 postuses_of(ENTRY *e)
751 {
752 
753 	if (e)
754 		return (e->e_post_uses);
755 	else
756 		return (-1);
757 }
758 
759 
760 /*
761  * allocate_entry -- make a parameter list into a complete
762  *	ENTRY struct, allocated dynamically.
763  */
764 	/* ARGSUSED -- lint bug */
765 static ENTRY *
766 allocate_entry(ENTRY *e,
767     char *name, int line, char *file,
768     int kind, char *type, char *basetype, int levels, char *attribute,
769     int npre, int npost)
770 {
771 
772 	errlog(BEGIN, "allocate_entry() {");
773 	if (e == NULL) {
774 		if ((e = (ENTRY *)calloc(1, sizeof (ENTRY))) == NULL) {
775 			errlog(FATAL, "can't allocate space for an ENTRY");
776 		}
777 	}
778 	errlog(END, "}");
779 	return (set_entry(e, name, line, file, kind, type, basetype, levels,
780 			attribute, npre, npost));
781 }
782 
783 /*
784  * set_entry -- set a passed-in entry, using
785  *	passed parameters, to values suitable for a
786  *	symtab entry
787  */
788 static ENTRY *
789 set_entry(ENTRY *e,
790     char *name, int line, char *file,
791     int kind, char *type, char *basetype, int levels, char *attribute,
792     int npre, int npost)
793 {
794 
795 	errlog(BEGIN, "set_entry() {");
796 	if (e == NULL) {
797 		errlog(FATAL, "programmer error: passed a NULL ENTRY");
798 	}
799 	e->e_name = strset(e->e_name, name);
800 	e->e_valid = YES;
801 	e->e_line = line,
802 	e->e_file = strset(e->e_file, file);
803 	e->e_kind = kind;
804 	switch (kind) {
805 	case PRIMITIVE:
806 		e->e_type = strset(e->e_type, type);
807 		e->e_basetype = strset(e->e_basetype, basetype);
808 		e->e_levels = levels;
809 		break;
810 	case COMPOSITE:
811 		e->e_attribute = strset(e->e_attribute, attribute);
812 		break;
813 	case VARARG:
814 		e->e_attribute = strset(e->e_attribute, attribute);
815 		break;
816 	default:
817 		errlog(FATAL, "programmer error: impossible kind of ENTRY");
818 	}
819 
820 	e->e_pre_uses = npre;
821 	e->e_post_uses = npost;
822 	errlog(END, "}");
823 	return (e);
824 }
825 
826 
827 /*
828  * free_entry -- really just mark an entry as invalid
829  */
830 static ENTRY *
831 free_entry(ENTRY *e)
832 {
833 	if (e != NULL)
834 		e->e_valid = NO;
835 	return (e);
836 }
837 
838 
839 /*
840  * ENTRY tables.
841  */
842 #define	ENTRY_INCREMENT 10
843 
844 static EHEAD *
845 create_entry_table(int n)
846 {
847 	EHEAD	*p;
848 
849 	errlog(BEGIN, "create_entry_table() {");
850 	if ((p = (EHEAD *)calloc(1,
851 	    sizeof (EHEAD)+(n*sizeof (ENTRY)))) == NULL) {
852 		errlog(FATAL, "can't allocate space for an ENTRY table");
853 	}
854 	p->used = -1;
855 	p->n_entries = n;
856 	errlog(END, "}");
857 	return (p);
858 }
859 
860 static EHEAD *
861 add_entry_table(EHEAD *t, char *name, int line, char *file,
862     int kind, char *type, char *basetype, int levels, char *attribute,
863     int npre, int npost)
864 {
865 	EHEAD	*t2;
866 
867 	errlog(BEGIN, "add_entry_table() {");
868 	if (t == NULL) {
869 		errlog(FATAL, "programmer error: tried to add to NULL EHEAD");
870 	}
871 	t->used++;
872 	if (t->used >= t->n_entries) {
873 		if ((t2 = (EHEAD *)realloc(t,
874 			sizeof (EHEAD)+(sizeof (ENTRY)*
875 				(t->n_entries+ENTRY_INCREMENT)))) == NULL) {
876 			errlog(FATAL, "out of memory extending an EHEAD");
877 		}
878 		t = t2;
879 		clear_entries(t, t->n_entries, (t->n_entries+ENTRY_INCREMENT));
880 		t->n_entries += ENTRY_INCREMENT;
881 	}
882 	(void) set_entry(&t->entry[t->used],
883 	    name, line, file, kind, type, basetype, levels,
884 	    attribute, npre, npost);
885 	errlog(END, "}");
886 	return (t);
887 }
888 
889 static ENTRY *
890 get_entry_table(EHEAD *t, int index)
891 {
892 	if (t == NULL)  {
893 		return (NULL);
894 	} else if (index > t->used) {
895 		return (NULL);
896 	} else {
897 		return (&(t->entry[index]));
898 	}
899 }
900 
901 static EHEAD *
902 free_entry_table(EHEAD *t)
903 {
904 	if (t != NULL)
905 		t->used = -1;
906 	return (t);
907 }
908 
909 static void
910 clear_entries(EHEAD *t, int start, int end)
911 {
912 	int	i;
913 
914 	for (i = start; i < end; i++) {
915 		(void) memset(&t->entry[i], 0, sizeof (ENTRY));
916 	}
917 }
918