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