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