Home | History | Annotate | Line # | Download | only in lint2
read.c revision 1.2
      1 /*	$NetBSD: read.c,v 1.2 1995/07/03 21:24:59 cgd Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1994, 1995 Jochen Pohl
      5  * All Rights Reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *      This product includes software developed by Jochen Pohl for
     18  *	The NetBSD Project.
     19  * 4. The name of the author may not be used to endorse or promote products
     20  *    derived from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 static char rcsid[] = "$NetBSD: read.c,v 1.2 1995/07/03 21:24:59 cgd Exp $";
     36 #endif
     37 
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <ctype.h>
     42 #include <limits.h>
     43 #include <err.h>
     44 
     45 #include "lint2.h"
     46 
     47 
     48 /* index of current (included) source file */
     49 static	int	srcfile;
     50 
     51 /*
     52  * The array pointed to by inpfns maps the file name indices of input files
     53  * to the file name indices used in lint2
     54  */
     55 static	short	*inpfns;
     56 static	size_t	ninpfns;
     57 
     58 /*
     59  * The array pointed to by *fnames maps file name indizes to file names.
     60  * Indices of type short are used instead of pointers to save memory.
     61  */
     62 const	char **fnames;
     63 static	size_t	nfnames;
     64 
     65 /*
     66  * Types are shared (to save memory for the types itself) and accessed
     67  * via indices (to save memory for references to types (indices are short)).
     68  * To share types, a equal type must be located fast. This is done by a
     69  * hash table. Access by indices is done via an array of pointers to the
     70  * types.
     71  */
     72 typedef struct thtab {
     73 	const	char *th_name;
     74 	u_short	th_idx;
     75 	struct	thtab *th_nxt;
     76 } thtab_t;
     77 static	thtab_t	**thtab;		/* hash table */
     78 type_t	**tlst;				/* array for indexed access */
     79 static	size_t	tlstlen;		/* length of tlst */
     80 
     81 /* index of current C source file (as spezified at the command line) */
     82 static	int	csrcfile;
     83 
     84 
     85 static	void	inperr __P((void));
     86 static	void	setsrc __P((const char *));
     87 static	void	setfnid __P((int, const char *));
     88 static	void	funccall __P((pos_t *, const char *));
     89 static	void	decldef __P((pos_t *, const char *));
     90 static	void	usedsym __P((pos_t *, const char *));
     91 static	u_short	inptype __P((const char *, const char **));
     92 static	int	gettlen __P((const char *, const char **));
     93 static	u_short	findtype __P((const char *, size_t, int));
     94 static	u_short	storetyp __P((type_t *, const char *, size_t, int));
     95 static	int	thash __P((const char *, size_t));
     96 static	char	*inpqstrg __P((const char *, const char **));
     97 static	const	char *inpname __P((const char *, const char **));
     98 static	int	getfnidx __P((const char *));
     99 
    100 void
    101 readfile(name)
    102 	const	char *name;
    103 {
    104 	FILE	*inp;
    105 	size_t	len;
    106 	const	char *cp;
    107 	char	*line, *eptr, rt;
    108 	int	cline, isrc, iline;
    109 	pos_t	pos;
    110 
    111 	if (inpfns == NULL)
    112 		inpfns = xcalloc(ninpfns = 128, sizeof (short));
    113 	if (fnames == NULL)
    114 		fnames = xcalloc(nfnames = 256, sizeof (char *));
    115 	if (tlstlen == 0)
    116 		tlst = xcalloc(tlstlen = 256, sizeof (type_t *));
    117 	if (thtab == NULL)
    118 		thtab = xcalloc(THSHSIZ2, sizeof (thtab_t));
    119 
    120 	srcfile = getfnidx(name);
    121 
    122 	if ((inp = fopen(name, "r")) == NULL)
    123 		err(1, "cannot open %s", name);
    124 
    125 	while ((line = fgetln(inp, &len)) != NULL) {
    126 
    127 		if (len == 0 || line[len - 1] != '\n')
    128 			inperr();
    129 		line[len - 1] = '\0';
    130 		cp = line;
    131 
    132 		/* line number in csrcfile */
    133 		cline = (int)strtol(cp, &eptr, 10);
    134 		if (cp == eptr) {
    135 		        cline = -1;
    136 		} else {
    137 			cp = eptr;
    138 		}
    139 
    140 		/* record type */
    141 		if (*cp != '\0') {
    142 			rt = *cp++;
    143 		} else {
    144 			inperr();
    145 		}
    146 
    147 		if (rt == 'S') {
    148 			setsrc(cp);
    149 			continue;
    150 		} else if (rt == 's') {
    151 			setfnid(cline, cp);
    152 			continue;
    153 		}
    154 
    155 		/*
    156 		 * Index of (included) source file. If this index is
    157 		 * different from csrcfile, it refers to an included
    158 		 * file.
    159 		 */
    160 		isrc = (int)strtol(cp, &eptr, 10);
    161 		if (cp == eptr)
    162 			inperr();
    163 		cp = eptr;
    164 		isrc = inpfns[isrc];
    165 
    166 		/* line number in isrc */
    167 		if (*cp++ != '.')
    168 			inperr();
    169 		iline = (int)strtol(cp, &eptr, 10);
    170 		if (cp == eptr)
    171 			inperr();
    172 		cp = eptr;
    173 
    174 		pos.p_src = (u_short)csrcfile;
    175 		pos.p_line = (u_short)cline;
    176 		pos.p_isrc = (u_short)isrc;
    177 		pos.p_iline = (u_short)iline;
    178 
    179 		/* process rest of this record */
    180 		switch (rt) {
    181 		case 'c':
    182 			funccall(&pos, cp);
    183 			break;
    184 		case 'd':
    185 			decldef(&pos, cp);
    186 			break;
    187 		case 'u':
    188 			usedsym(&pos, cp);
    189 			break;
    190 		default:
    191 			inperr();
    192 		}
    193 
    194 	}
    195 
    196 	if (ferror(inp))
    197 		err(1, "read error on %s", name);
    198 
    199 	(void)fclose(inp);
    200 }
    201 
    202 
    203 static void
    204 inperr()
    205 {
    206 	errx(1, "input file error: %s", fnames[srcfile]);
    207 }
    208 
    209 /*
    210  * Set the name of the C source file of the .ln file which is
    211  * currently read.
    212  */
    213 static void
    214 setsrc(cp)
    215 	const	char *cp;
    216 {
    217 	csrcfile = getfnidx(cp);
    218 }
    219 
    220 /*
    221  * setfnid() gets as input an index as used in an input file and the
    222  * associated file name. If neccessary, it creates a new lint2 file
    223  * name index for this file name and creates the mapping of the index
    224  * as used in the input file to the index used in lint2.
    225  */
    226 static void
    227 setfnid(fid, cp)
    228 	int	fid;
    229 	const	char *cp;
    230 {
    231 	if (fid == -1)
    232 		inperr();
    233 
    234 	if (fid >= ninpfns) {
    235 		inpfns = xrealloc(inpfns, (ninpfns * 2) * sizeof (short));
    236 		(void)memset(inpfns + ninpfns, 0, ninpfns * sizeof (short));
    237 		ninpfns *= 2;
    238 	}
    239 	/*
    240 	 * Should always be true because indices written in the output
    241 	 * file by lint1 are always the previous index + 1.
    242 	 */
    243 	if (fid >= ninpfns)
    244 		errx(1, "internal error: setfnid()");
    245 	inpfns[fid] = (u_short)getfnidx(cp);
    246 }
    247 
    248 /*
    249  * Process a function call record (c-record).
    250  */
    251 static void
    252 funccall(posp, cp)
    253 	pos_t	*posp;
    254 	const	char *cp;
    255 {
    256 	arginf_t *ai, **lai;
    257 	char	c, *eptr;
    258 	int	rused, rdisc;
    259 	hte_t	*hte;
    260 	fcall_t	*fcall;
    261 
    262 	fcall = xalloc(sizeof (fcall_t));
    263 	STRUCT_ASSIGN(fcall->f_pos, *posp);
    264 
    265 	/* read flags */
    266 	rused = rdisc = 0;
    267 	lai = &fcall->f_args;
    268 	while ((c = *cp) == 'u' || c == 'i' || c == 'd' ||
    269 	       c == 'z' || c == 'p' || c == 'n' || c == 's') {
    270 		cp++;
    271 		switch (c) {
    272 		case 'u':
    273 			if (rused || rdisc)
    274 				inperr();
    275 			rused = 1;
    276 			break;
    277 		case 'i':
    278 			if (rused || rdisc)
    279 				inperr();
    280 			break;
    281 		case 'd':
    282 			if (rused || rdisc)
    283 				inperr();
    284 			rdisc = 1;
    285 			break;
    286 		case 'z':
    287 		case 'p':
    288 		case 'n':
    289 		case 's':
    290 			ai = xalloc(sizeof (arginf_t));
    291 			ai->a_num = (int)strtol(cp, &eptr, 10);
    292 			if (cp == eptr)
    293 				inperr();
    294 			cp = eptr;
    295 			if (c == 'z') {
    296 				ai->a_pcon = ai->a_zero = 1;
    297 			} else if (c == 'p') {
    298 				ai->a_pcon = 1;
    299 			} else if (c == 'n') {
    300 				ai->a_ncon = 1;
    301 			} else {
    302 				ai->a_fmt = 1;
    303 				ai->a_fstrg = inpqstrg(cp, &cp);
    304 			}
    305 			*lai = ai;
    306 			lai = &ai->a_nxt;
    307 			break;
    308 		}
    309 	}
    310 	fcall->f_rused = rused;
    311 	fcall->f_rdisc = rdisc;
    312 
    313 	/* read name of function */
    314 	hte = hsearch(inpname(cp, &cp), 1);
    315 	hte->h_used = 1;
    316 
    317 	fcall->f_type = inptype(cp, &cp);
    318 
    319 	*hte->h_lcall = fcall;
    320 	hte->h_lcall = &fcall->f_nxt;
    321 
    322 	if (*cp != '\0')
    323 		inperr();
    324 }
    325 
    326 /*
    327  * Process a declaration or definition (d-record).
    328  */
    329 static void
    330 decldef(posp, cp)
    331 	pos_t	*posp;
    332 	const	char *cp;
    333 {
    334 	sym_t	*symp, sym;
    335 	char	c, *ep;
    336 	int	used;
    337 	hte_t	*hte;
    338 
    339 	(void)memset(&sym, 0, sizeof (sym));
    340 	STRUCT_ASSIGN(sym.s_pos, *posp);
    341 	sym.s_def = NODECL;
    342 
    343 	used = 0;
    344 
    345 	while ((c = *cp) == 't' || c == 'd' || c == 'e' || c == 'u' ||
    346 	       c == 'r' || c == 'o' || c == 's' || c == 'v' ||
    347 	       c == 'P' || c == 'S') {
    348 		cp++;
    349 		switch (c) {
    350 		case 't':
    351 			if (sym.s_def != NODECL)
    352 				inperr();
    353 			sym.s_def = TDEF;
    354 			break;
    355 		case 'd':
    356 			if (sym.s_def != NODECL)
    357 				inperr();
    358 			sym.s_def = DEF;
    359 			break;
    360 		case 'e':
    361 			if (sym.s_def != NODECL)
    362 				inperr();
    363 			sym.s_def = DECL;
    364 			break;
    365 		case 'u':
    366 			if (used)
    367 				inperr();
    368 			used = 1;
    369 			break;
    370 		case 'r':
    371 			if (sym.s_rval)
    372 				inperr();
    373 			sym.s_rval = 1;
    374 			break;
    375 		case 'o':
    376 			if (sym.s_osdef)
    377 				inperr();
    378 			sym.s_osdef = 1;
    379 			break;
    380 		case 's':
    381 			if (sym.s_static)
    382 				inperr();
    383 			sym.s_static = 1;
    384 			break;
    385 		case 'v':
    386 			if (sym.s_va)
    387 				inperr();
    388 			sym.s_va = 1;
    389 			sym.s_nva = (short)strtol(cp, &ep, 10);
    390 			if (cp == ep)
    391 				inperr();
    392 			cp = ep;
    393 			break;
    394 		case 'P':
    395 			if (sym.s_prfl)
    396 				inperr();
    397 			sym.s_prfl = 1;
    398 			sym.s_nprfl = (short)strtol(cp, &ep, 10);
    399 			if (cp == ep)
    400 				inperr();
    401 			cp = ep;
    402 			break;
    403 		case 'S':
    404 			if (sym.s_scfl)
    405 				inperr();
    406 			sym.s_scfl = 1;
    407 			sym.s_nscfl = (short)strtol(cp, &ep, 10);
    408 			if (cp == ep)
    409 				inperr();
    410 			cp = ep;
    411 			break;
    412 		}
    413 	}
    414 
    415 	/* read symbol name */
    416 	hte = hsearch(inpname(cp, &cp), 1);
    417 	hte->h_used |= used;
    418 	if (sym.s_def == DEF || sym.s_def == TDEF)
    419 		hte->h_def = 1;
    420 
    421 	sym.s_type = inptype(cp, &cp);
    422 
    423 	/*
    424 	 * Allocate memory for this symbol only if it was not already
    425 	 * declared or tentatively defined at the same location with
    426 	 * the same type. Works only for symbols with external linkage,
    427 	 * because static symbols, tentatively defined at the same location
    428 	 * but in different translation units are really different symbols.
    429 	 */
    430 	for (symp = hte->h_syms; symp != NULL; symp = symp->s_nxt) {
    431 		if (symp->s_pos.p_isrc == sym.s_pos.p_isrc &&
    432 		    symp->s_pos.p_iline == sym.s_pos.p_iline &&
    433 		    symp->s_type == sym.s_type &&
    434 		    ((symp->s_def == DECL && sym.s_def == DECL) ||
    435 		     (!sflag && symp->s_def == TDEF && sym.s_def == TDEF)) &&
    436 		    !symp->s_static && !sym.s_static) {
    437 			break;
    438 		}
    439 	}
    440 
    441 	if (symp == NULL) {
    442 		/* allocsym reserviert keinen Platz fuer s_nva */
    443 		if (sym.s_va || sym.s_prfl || sym.s_scfl) {
    444 			symp = xalloc(sizeof (sym_t));
    445 			STRUCT_ASSIGN(*symp, sym);
    446 		} else {
    447 			symp = xalloc(sizeof (symp->s_s));
    448 			STRUCT_ASSIGN(symp->s_s, sym.s_s);
    449 		}
    450 		*hte->h_lsym = symp;
    451 		hte->h_lsym = &symp->s_nxt;
    452 	}
    453 
    454 	if (*cp != '\0')
    455 		inperr();
    456 }
    457 
    458 /*
    459  * Read an u-record (emited by lint1 if a symbol was used).
    460  */
    461 static void
    462 usedsym(posp, cp)
    463 	pos_t	*posp;
    464 	const	char *cp;
    465 {
    466 	usym_t	*usym;
    467 	hte_t	*hte;
    468 
    469 	usym = xalloc(sizeof (usym_t));
    470 	STRUCT_ASSIGN(usym->u_pos, *posp);
    471 
    472 	/* needed as delimiter between two numbers */
    473 	if (*cp++ != 'x')
    474 		inperr();
    475 
    476 	hte = hsearch(inpname(cp, &cp), 1);
    477 	hte->h_used = 1;
    478 
    479 	*hte->h_lusym = usym;
    480 	hte->h_lusym = &usym->u_nxt;
    481 }
    482 
    483 /*
    484  * Read a type and return the index of this type.
    485  */
    486 static u_short
    487 inptype(cp, epp)
    488 	const	char *cp, **epp;
    489 {
    490 	char	c, s, *eptr;
    491 	const	char *ep;
    492 	type_t	*tp;
    493 	int	narg, i, osdef;
    494 	size_t	tlen;
    495 	u_short	tidx;
    496 	int	h;
    497 
    498 	/* If we have this type already, return it's index. */
    499 	tlen = gettlen(cp, &ep);
    500 	h = thash(cp, tlen);
    501 	if ((tidx = findtype(cp, tlen, h)) != 0) {
    502 		*epp = ep;
    503 		return (tidx);
    504 	}
    505 
    506 	/* No, we must create a new type. */
    507 	tp = xalloc(sizeof (type_t));
    508 
    509 	tidx = storetyp(tp, cp, tlen, h);
    510 
    511 	c = *cp++;
    512 
    513 	while (c == 'c' || c == 'v') {
    514 		if (c == 'c') {
    515 			tp->t_const = 1;
    516 		} else {
    517 			tp->t_volatile = 1;
    518 		}
    519 		c = *cp++;
    520 	}
    521 
    522 	if (c == 's' || c == 'u' || c == 'l' || c == 'e') {
    523 		s = c;
    524 		c = *cp++;
    525 	} else {
    526 		s = '\0';
    527 	}
    528 
    529 	switch (c) {
    530 	case 'C':
    531 		tp->t_tspec = s == 's' ? SCHAR : (s == 'u' ? UCHAR : CHAR);
    532 		break;
    533 	case 'S':
    534 		tp->t_tspec = s == 'u' ? USHORT : SHORT;
    535 		break;
    536 	case 'I':
    537 		tp->t_tspec = s == 'u' ? UINT : INT;
    538 		break;
    539 	case 'L':
    540 		tp->t_tspec = s == 'u' ? ULONG : LONG;
    541 		break;
    542 	case 'Q':
    543 		tp->t_tspec = s == 'u' ? UQUAD : QUAD;
    544 		break;
    545 	case 'D':
    546 		tp->t_tspec = s == 's' ? FLOAT : (s == 'l' ? LDOUBLE : DOUBLE);
    547 		break;
    548 	case 'V':
    549 		tp->t_tspec = VOID;
    550 		break;
    551 	case 'P':
    552 		tp->t_tspec = PTR;
    553 		break;
    554 	case 'A':
    555 		tp->t_tspec = ARRAY;
    556 		break;
    557 	case 'F':
    558 	case 'f':
    559 		osdef = c == 'f';
    560 		tp->t_tspec = FUNC;
    561 		break;
    562 	case 'T':
    563 		tp->t_tspec = s == 'e' ? ENUM : (s == 's' ? STRUCT : UNION);
    564 		break;
    565 	}
    566 
    567 	switch (tp->t_tspec) {
    568 	case ARRAY:
    569 		tp->t_dim = (int)strtol(cp, &eptr, 10);
    570 		cp = eptr;
    571 		tp->t_subt = TP(inptype(cp, &cp));
    572 		break;
    573 	case PTR:
    574 		tp->t_subt = TP(inptype(cp, &cp));
    575 		break;
    576 	case FUNC:
    577 		c = *cp;
    578 		if (isdigit((u_char)c)) {
    579 			if (!osdef)
    580 				tp->t_proto = 1;
    581 			narg = (int)strtol(cp, &eptr, 10);
    582 			cp = eptr;
    583 			tp->t_args = xcalloc((size_t)(narg + 1),
    584 					     sizeof (type_t *));
    585 			for (i = 0; i < narg; i++) {
    586 				if (i == narg - 1 && *cp == 'E') {
    587 					tp->t_vararg = 1;
    588 					cp++;
    589 				} else {
    590 					tp->t_args[i] = TP(inptype(cp, &cp));
    591 				}
    592 			}
    593 		}
    594 		tp->t_subt = TP(inptype(cp, &cp));
    595 		break;
    596 	case ENUM:
    597 		tp->t_tspec = INT;
    598 		tp->t_isenum = 1;
    599 		/* FALLTHROUGH */
    600 	case STRUCT:
    601 	case UNION:
    602 		switch (*cp++) {
    603 		case '0':
    604 			break;
    605 		case '1':
    606 			tp->t_istag = 1;
    607 			tp->t_tag = hsearch(inpname(cp, &cp), 1);
    608 			break;
    609 		case '2':
    610 			tp->t_istynam = 1;
    611 			tp->t_tynam = hsearch(inpname(cp, &cp), 1);
    612 			break;
    613 		}
    614 		break;
    615 		/* LINTED (enumeration value(s) not handled in switch) */
    616 	}
    617 
    618 	*epp = cp;
    619 	return (tidx);
    620 }
    621 
    622 /*
    623  * Get the length of a type string.
    624  */
    625 static int
    626 gettlen(cp, epp)
    627 	const	char *cp, **epp;
    628 {
    629 	const	char *cp1;
    630 	char	c, s, *eptr;
    631 	tspec_t	t;
    632 	int	narg, i, cm, vm;
    633 
    634 	cp1 = cp;
    635 
    636 	c = *cp++;
    637 
    638 	cm = vm = 0;
    639 
    640 	while (c == 'c' || c == 'v') {
    641 		if (c == 'c') {
    642 			if (cm)
    643 				inperr();
    644 			cm = 1;
    645 		} else {
    646 			if (vm)
    647 				inperr();
    648 			vm = 1;
    649 		}
    650 		c = *cp++;
    651 	}
    652 
    653 	if (c == 's' || c == 'u' || c == 'l' || c == 'e') {
    654 		s = c;
    655 		c = *cp++;
    656 	} else {
    657 		s = '\0';
    658 	}
    659 
    660 	t = NOTSPEC;
    661 
    662 	switch (c) {
    663 	case 'C':
    664 		if (s == 's') {
    665 			t = SCHAR;
    666 		} else if (s == 'u') {
    667 			t = UCHAR;
    668 		} else if (s == '\0') {
    669 			t = CHAR;
    670 		}
    671 		break;
    672 	case 'S':
    673 		if (s == 'u') {
    674 			t = USHORT;
    675 		} else if (s == '\0') {
    676 			t = SHORT;
    677 		}
    678 		break;
    679 	case 'I':
    680 		if (s == 'u') {
    681 			t = UINT;
    682 		} else if (s == '\0') {
    683 			t = INT;
    684 		}
    685 		break;
    686 	case 'L':
    687 		if (s == 'u') {
    688 			t = ULONG;
    689 		} else if (s == '\0') {
    690 			t = LONG;
    691 		}
    692 		break;
    693 	case 'Q':
    694 		if (s == 'u') {
    695 			t = UQUAD;
    696 		} else if (s == '\0') {
    697 			t = QUAD;
    698 		}
    699 		break;
    700 	case 'D':
    701 		if (s == 's') {
    702 			t = FLOAT;
    703 		} else if (s == 'l') {
    704 			t = LDOUBLE;
    705 		} else if (s == '\0') {
    706 			t = DOUBLE;
    707 		}
    708 		break;
    709 	case 'V':
    710 		if (s == '\0')
    711 			t = VOID;
    712 		break;
    713 	case 'P':
    714 		if (s == '\0')
    715 			t = PTR;
    716 		break;
    717 	case 'A':
    718 		if (s == '\0')
    719 			t = ARRAY;
    720 		break;
    721 	case 'F':
    722 	case 'f':
    723 		if (s == '\0')
    724 			t = FUNC;
    725 		break;
    726 	case 'T':
    727 		if (s == 'e') {
    728 			t = ENUM;
    729 		} else if (s == 's') {
    730 			t = STRUCT;
    731 		} else if (s == 'u') {
    732 			t = UNION;
    733 		}
    734 		break;
    735 	default:
    736 		inperr();
    737 	}
    738 
    739 	if (t == NOTSPEC)
    740 		inperr();
    741 
    742 	switch (t) {
    743 	case ARRAY:
    744 		(void)strtol(cp, &eptr, 10);
    745 		if (cp == eptr)
    746 			inperr();
    747 		cp = eptr;
    748 		(void)gettlen(cp, &cp);
    749 		break;
    750 	case PTR:
    751 		(void)gettlen(cp, &cp);
    752 		break;
    753 	case FUNC:
    754 		c = *cp;
    755 		if (isdigit((u_char)c)) {
    756 			narg = (int)strtol(cp, &eptr, 10);
    757 			cp = eptr;
    758 			for (i = 0; i < narg; i++) {
    759 				if (i == narg - 1 && *cp == 'E') {
    760 					cp++;
    761 				} else {
    762 					(void)gettlen(cp, &cp);
    763 				}
    764 			}
    765 		}
    766 		(void)gettlen(cp, &cp);
    767 		break;
    768 	case ENUM:
    769 	case STRUCT:
    770 	case UNION:
    771 		switch (*cp++) {
    772 		case '0':
    773 			break;
    774 		case '1':
    775 			(void)inpname(cp, &cp);
    776 			break;
    777 		case '2':
    778 			(void)inpname(cp, &cp);
    779 			break;
    780 		default:
    781 			inperr();
    782 		}
    783 		break;
    784 		/* LINTED (enumeration value(s) not handled in switch) */
    785 	}
    786 
    787 	*epp = cp;
    788 	return (cp - cp1);
    789 }
    790 
    791 /*
    792  * Search a type by it's type string.
    793  */
    794 static u_short
    795 findtype(cp, len, h)
    796 	const	char *cp;
    797 	size_t	len;
    798 	int	h;
    799 {
    800 	thtab_t	*thte;
    801 
    802 	for (thte = thtab[h]; thte != NULL; thte = thte->th_nxt) {
    803 		if (strncmp(thte->th_name, cp, len) != 0)
    804 			continue;
    805 		if (thte->th_name[len] == '\0')
    806 			return (thte->th_idx);
    807 	}
    808 
    809 	return (0);
    810 }
    811 
    812 /*
    813  * Store a type and it's type string so we can later share this type
    814  * if we read the same type string from the input file.
    815  */
    816 static u_short
    817 storetyp(tp, cp, len, h)
    818 	type_t	*tp;
    819 	const	char *cp;
    820 	size_t	len;
    821 	int	h;
    822 {
    823 	/* 0 ist reserved */
    824 	static	u_int	tidx = 1;
    825 	thtab_t	*thte;
    826 	char	*name;
    827 
    828 	if (tidx >= USHRT_MAX)
    829 		errx(1, "sorry, too many types");
    830 
    831 	if (tidx == tlstlen - 1) {
    832 		tlst = xrealloc(tlst, (tlstlen * 2) * sizeof (type_t *));
    833 		(void)memset(tlst + tlstlen, 0, tlstlen * sizeof (type_t *));
    834 		tlstlen *= 2;
    835 	}
    836 
    837 	tlst[tidx] = tp;
    838 
    839 	/* create a hash table entry */
    840 	name = xalloc(len + 1);
    841 	(void)memcpy(name, cp, len);
    842 	name[len] = '\0';
    843 
    844 	thte = xalloc(sizeof (thtab_t));
    845 	thte->th_name = name;
    846 	thte->th_idx = tidx;
    847 	thte->th_nxt = thtab[h];
    848 	thtab[h] = thte;
    849 
    850 	return ((u_short)tidx++);
    851 }
    852 
    853 /*
    854  * Hash function for types
    855  */
    856 static int
    857 thash(s, len)
    858 	const	char *s;
    859 	size_t	len;
    860 {
    861 	u_int	v;
    862 
    863 	v = 0;
    864 	while (len-- != 0) {
    865 		v = (v << sizeof (v)) + (u_char)*s++;
    866 		v ^= v >> (sizeof (v) * CHAR_BIT - sizeof (v));
    867 	}
    868 	return (v % THSHSIZ2);
    869 }
    870 
    871 /*
    872  * Read a string enclosed by "". This string may contain quoted chars.
    873  */
    874 static char *
    875 inpqstrg(src, epp)
    876 	const	char *src, **epp;
    877 {
    878 	char	*strg, *dst;
    879 	size_t	slen;
    880 	int	c;
    881 	int	v;
    882 
    883 	dst = strg = xmalloc(slen = 32);
    884 
    885 	if ((c = *src++) != '"')
    886 		inperr();
    887 	if ((c = *src++) == '\0')
    888 		inperr();
    889 
    890 	while (c != '"') {
    891 		if (c == '\\') {
    892 			if ((c = *src++) == '\0')
    893 				inperr();
    894 			switch (c) {
    895 			case 'n':
    896 				c = '\n';
    897 				break;
    898 			case 't':
    899 				c = '\t';
    900 				break;
    901 			case 'v':
    902 #ifdef __STDC__
    903 				c = '\v';
    904 #else
    905 				c = '\013';
    906 #endif
    907 				break;
    908 			case 'b':
    909 				c = '\b';
    910 				break;
    911 			case 'r':
    912 				c = '\r';
    913 				break;
    914 			case 'f':
    915 				c = '\f';
    916 				break;
    917 			case 'a':
    918 #ifdef __STDC__
    919 				c = '\a';
    920 #else
    921 				c = '\007';
    922 #endif
    923 				break;
    924 			case '\\':
    925 				c = '\\';
    926 				break;
    927 			case '"':
    928 				c = '"';
    929 				break;
    930 			case '\'':
    931 				c = '\'';
    932 				break;
    933 			case '0': case '1': case '2': case '3':
    934 				v = (c - '0') << 6;
    935 				if ((c = *src++) < '0' || c > '7')
    936 					inperr();
    937 				v |= (c - '0') << 3;
    938 				if ((c = *src++) < '0' || c > '7')
    939 					inperr();
    940 				v |= c - '0';
    941 				c = (u_char)v;
    942 				break;
    943 			default:
    944 				inperr();
    945 			}
    946 		}
    947 		/* keep space for trailing '\0' */
    948 		if (dst - strg == slen - 1) {
    949 			strg = xrealloc(strg, slen * 2);
    950 			dst = strg + (slen - 1);
    951 			slen *= 2;
    952 		}
    953 		*dst++ = (char)c;
    954 		if ((c = *src++) == '\0')
    955 			inperr();
    956 	}
    957 	*dst = '\0';
    958 
    959 	*epp = src;
    960 	return (strg);
    961 }
    962 
    963 /*
    964  * Read the name of a symbol in static memory.
    965  */
    966 static const char *
    967 inpname(cp, epp)
    968 	const	char *cp, **epp;
    969 {
    970 	static	char	*buf;
    971 	static	size_t	blen = 0;
    972 	size_t	len, i;
    973 	char	*eptr, c;
    974 
    975 	len = (int)strtol(cp, &eptr, 10);
    976 	if (cp == eptr)
    977 		inperr();
    978 	cp = eptr;
    979 	if (len + 1 > blen)
    980 		buf = xrealloc(buf, blen = len + 1);
    981 	for (i = 0; i < len; i++) {
    982 		c = *cp++;
    983 		if (!isalnum(c) && c != '_')
    984 			inperr();
    985 		buf[i] = c;
    986 	}
    987 	buf[i] = '\0';
    988 
    989 	*epp = cp;
    990 	return (buf);
    991 }
    992 
    993 /*
    994  * Return the index of a file name. If the name cannot be found, create
    995  * a new entry and return the index of the newly created entry.
    996  */
    997 static int
    998 getfnidx(fn)
    999 	const	char *fn;
   1000 {
   1001 	int	i;
   1002 
   1003 	/* 0 ist reserved */
   1004 	for (i = 1; fnames[i] != NULL; i++) {
   1005 		if (strcmp(fnames[i], fn) == 0)
   1006 			break;
   1007 	}
   1008 	if (fnames[i] != NULL)
   1009 		return (i);
   1010 
   1011 	if (i == nfnames - 1) {
   1012 		fnames = xrealloc(fnames, (nfnames * 2) * sizeof (char *));
   1013 		(void)memset(fnames + nfnames, 0, nfnames * sizeof (char *));
   1014 		nfnames *= 2;
   1015 	}
   1016 
   1017 	fnames[i] = xstrdup(fn);
   1018 	return (i);
   1019 }
   1020 
   1021 /*
   1022  * Separate symbols with static and external linkage.
   1023  */
   1024 void
   1025 mkstatic(hte)
   1026 	hte_t	*hte;
   1027 {
   1028 	sym_t	*sym1, **symp, *sym;
   1029 	fcall_t	**callp, *call;
   1030 	usym_t	**usymp, *usym;
   1031 	hte_t	*nhte;
   1032 	int	ofnd;
   1033 
   1034 	/* Look for first static definition */
   1035 	for (sym1 = hte->h_syms; sym1 != NULL; sym1 = sym1->s_nxt) {
   1036 		if (sym1->s_static)
   1037 			break;
   1038 	}
   1039 	if (sym1 == NULL)
   1040 		return;
   1041 
   1042 	/* Do nothing if this name is used only in one translation unit. */
   1043 	ofnd = 0;
   1044 	for (sym = hte->h_syms; sym != NULL && !ofnd; sym = sym->s_nxt) {
   1045 		if (sym->s_pos.p_src != sym1->s_pos.p_src)
   1046 			ofnd = 1;
   1047 	}
   1048 	for (call = hte->h_calls; call != NULL && !ofnd; call = call->f_nxt) {
   1049 		if (call->f_pos.p_src != sym1->s_pos.p_src)
   1050 			ofnd = 1;
   1051 	}
   1052 	for (usym = hte->h_usyms; usym != NULL && !ofnd; usym = usym->u_nxt) {
   1053 		if (usym->u_pos.p_src != sym1->s_pos.p_src)
   1054 			ofnd = 1;
   1055 	}
   1056 	if (!ofnd) {
   1057 		hte->h_used = 1;
   1058 		/* errors about undef. static symbols are printed in lint1 */
   1059 		hte->h_def = 1;
   1060 		hte->h_static = 1;
   1061 		return;
   1062 	}
   1063 
   1064 	/*
   1065 	 * Create a new hash table entry
   1066 	 *
   1067 	 * XXX this entry should be put at the beginning of the list to
   1068 	 * avoid to process the same symbol twice.
   1069 	 */
   1070 	for (nhte = hte; nhte->h_link != NULL; nhte = nhte->h_link) ;
   1071 	nhte->h_link = xalloc(sizeof (hte_t));
   1072 	nhte = nhte->h_link;
   1073 	nhte->h_name = hte->h_name;
   1074 	nhte->h_static = 1;
   1075 	nhte->h_used = 1;
   1076 	nhte->h_def = 1;	/* error in lint1 */
   1077 	nhte->h_lsym = &nhte->h_syms;
   1078 	nhte->h_lcall = &nhte->h_calls;
   1079 	nhte->h_lusym = &nhte->h_usyms;
   1080 
   1081 	/*
   1082 	 * move all symbols used in this translation unit into the new
   1083 	 * hash table entry.
   1084 	 */
   1085 	for (symp = &hte->h_syms; (sym = *symp) != NULL; ) {
   1086 		if (sym->s_pos.p_src == sym1->s_pos.p_src) {
   1087 			sym->s_static = 1;
   1088 			(*symp) = sym->s_nxt;
   1089 			if (hte->h_lsym == &sym->s_nxt)
   1090 				hte->h_lsym = symp;
   1091 			sym->s_nxt = NULL;
   1092 			*nhte->h_lsym = sym;
   1093 			nhte->h_lsym = &sym->s_nxt;
   1094 		} else {
   1095 			symp = &sym->s_nxt;
   1096 		}
   1097 	}
   1098 	for (callp = &hte->h_calls; (call = *callp) != NULL; ) {
   1099 		if (call->f_pos.p_src == sym1->s_pos.p_src) {
   1100 			(*callp) = call->f_nxt;
   1101 			if (hte->h_lcall == &call->f_nxt)
   1102 				hte->h_lcall = callp;
   1103 			call->f_nxt = NULL;
   1104 			*nhte->h_lcall = call;
   1105 			nhte->h_lcall = &call->f_nxt;
   1106 		} else {
   1107 			callp = &call->f_nxt;
   1108 		}
   1109 	}
   1110 	for (usymp = &hte->h_usyms; (usym = *usymp) != NULL; ) {
   1111 		if (usym->u_pos.p_src == sym1->s_pos.p_src) {
   1112 			(*usymp) = usym->u_nxt;
   1113 			if (hte->h_lusym == &usym->u_nxt)
   1114 				hte->h_lusym = usymp;
   1115 			usym->u_nxt = NULL;
   1116 			*nhte->h_lusym = usym;
   1117 			nhte->h_lusym = &usym->u_nxt;
   1118 		} else {
   1119 			usymp = &usym->u_nxt;
   1120 		}
   1121 	}
   1122 
   1123 	/* h_def must be recalculated for old hte */
   1124 	hte->h_def = nhte->h_def = 0;
   1125 	for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
   1126 		if (sym->s_def == DEF || sym->s_def == TDEF) {
   1127 			hte->h_def = 1;
   1128 			break;
   1129 		}
   1130 	}
   1131 
   1132 	mkstatic(hte);
   1133 }
   1134