]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.bin/xlint/lint2/read.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.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         }
700
701         *epp = cp;
702         return (tidx);
703 }
704
705 /*
706  * Get the length of a type string.
707  */
708 static int
709 gettlen(const char *cp, const char **epp)
710 {
711         const   char *cp1;
712         char    c, s, *eptr;
713         tspec_t t;
714         int     narg, i, cm, vm;
715
716         cp1 = cp;
717
718         c = *cp++;
719
720         cm = vm = 0;
721
722         while (c == 'c' || c == 'v') {
723                 if (c == 'c') {
724                         if (cm)
725                                 inperr();
726                         cm = 1;
727                 } else {
728                         if (vm)
729                                 inperr();
730                         vm = 1;
731                 }
732                 c = *cp++;
733         }
734
735         if (c == 's' || c == 'u' || c == 'l' || c == 'e') {
736                 s = c;
737                 c = *cp++;
738         } else {
739                 s = '\0';
740         }
741
742         t = NOTSPEC;
743
744         switch (c) {
745         case 'C':
746                 if (s == 's') {
747                         t = SCHAR;
748                 } else if (s == 'u') {
749                         t = UCHAR;
750                 } else if (s == '\0') {
751                         t = CHAR;
752                 }
753                 break;
754         case 'S':
755                 if (s == 'u') {
756                         t = USHORT;
757                 } else if (s == '\0') {
758                         t = SHORT;
759                 }
760                 break;
761         case 'I':
762                 if (s == 'u') {
763                         t = UINT;
764                 } else if (s == '\0') {
765                         t = INT;
766                 }
767                 break;
768         case 'L':
769                 if (s == 'u') {
770                         t = ULONG;
771                 } else if (s == '\0') {
772                         t = LONG;
773                 }
774                 break;
775         case 'Q':
776                 if (s == 'u') {
777                         t = UQUAD;
778                 } else if (s == '\0') {
779                         t = QUAD;
780                 }
781                 break;
782         case 'D':
783                 if (s == 's') {
784                         t = FLOAT;
785                 } else if (s == 'l') {
786                         t = LDOUBLE;
787                 } else if (s == '\0') {
788                         t = DOUBLE;
789                 }
790                 break;
791         case 'V':
792                 if (s == '\0')
793                         t = VOID;
794                 break;
795         case 'P':
796                 if (s == '\0')
797                         t = PTR;
798                 break;
799         case 'A':
800                 if (s == '\0')
801                         t = ARRAY;
802                 break;
803         case 'F':
804         case 'f':
805                 if (s == '\0')
806                         t = FUNC;
807                 break;
808         case 'T':
809                 if (s == 'e') {
810                         t = ENUM;
811                 } else if (s == 's') {
812                         t = STRUCT;
813                 } else if (s == 'u') {
814                         t = UNION;
815                 }
816                 break;
817         default:
818                 inperr();
819         }
820
821         if (t == NOTSPEC)
822                 inperr();
823
824         switch (t) {
825         case ARRAY:
826                 (void)strtol(cp, &eptr, 10);
827                 if (cp == eptr)
828                         inperr();
829                 cp = eptr;
830                 (void)gettlen(cp, &cp);
831                 break;
832         case PTR:
833                 (void)gettlen(cp, &cp);
834                 break;
835         case FUNC:
836                 c = *cp;
837                 if (isdigit((u_char)c)) {
838                         narg = (int)strtol(cp, &eptr, 10);
839                         cp = eptr;
840                         for (i = 0; i < narg; i++) {
841                                 if (i == narg - 1 && *cp == 'E') {
842                                         cp++;
843                                 } else {
844                                         (void)gettlen(cp, &cp);
845                                 }
846                         }
847                 }
848                 (void)gettlen(cp, &cp);
849                 break;
850         case ENUM:
851         case STRUCT:
852         case UNION:
853                 switch (*cp++) {
854                 case '1':
855                         (void)inpname(cp, &cp);
856                         break;
857                 case '2':
858                         (void)inpname(cp, &cp);
859                         break;
860                 case '3':
861                         /* unique position: line.file.uniquifier */
862                         (void)strtol(cp, &eptr, 10);
863                         if (cp == eptr)
864                                 inperr();
865                         cp = eptr;
866                         if (*cp++ != '.')
867                                 inperr();
868                         (void)strtol(cp, &eptr, 10);
869                         if (cp == eptr)
870                                 inperr();
871                         cp = eptr;
872                         if (*cp++ != '.')
873                                 inperr();
874                         (void)strtol(cp, &eptr, 10);
875                         if (cp == eptr)
876                                 inperr();
877                         cp = eptr;
878                         break;
879                 default:
880                         inperr();
881                 }
882                 break;
883         case FLOAT:
884         case USHORT:
885         case SHORT:
886         case UCHAR:
887         case SCHAR:
888         case CHAR:
889         case UNSIGN:
890         case SIGNED:
891         case NOTSPEC:
892         case INT:
893         case UINT:
894         case DOUBLE:
895         case LDOUBLE:
896         case VOID:
897         case ULONG:
898         case QUAD:
899         case UQUAD:
900         case LONG:
901                 break;
902         }
903
904         *epp = cp;
905         return (cp - cp1);
906 }
907
908 /*
909  * Search a type by it's type string.
910  */
911 static u_short
912 findtype(const char *cp, size_t len, int h)
913 {
914         thtab_t *thte;
915
916         for (thte = thtab[h]; thte != NULL; thte = thte->th_nxt) {
917                 if (strncmp(thte->th_name, cp, len) != 0)
918                         continue;
919                 if (thte->th_name[len] == '\0')
920                         return (thte->th_idx);
921         }
922
923         return (0);
924 }
925
926 /*
927  * Store a type and it's type string so we can later share this type
928  * if we read the same type string from the input file.
929  */
930 static u_short
931 storetyp(type_t *tp, const char *cp, size_t len, int h)
932 {
933         static  u_int   tidx = 1;       /* 0 is reserved */
934         thtab_t *thte;
935         char    *name;
936
937         if (tidx >= USHRT_MAX)
938                 errx(1, "sorry, too many types");
939
940         if (tidx == tlstlen - 1) {
941                 if ((tlst = realloc(tlst, (tlstlen * 2) * sizeof (type_t *)))
942                     == NULL)
943                         nomem();
944                 (void)memset(tlst + tlstlen, 0, tlstlen * sizeof (type_t *));
945                 tlstlen *= 2;
946         }
947
948         tlst[tidx] = tp;
949
950         /* create a hash table entry */
951         name = xalloc(len + 1);
952         (void)memcpy(name, cp, len);
953         name[len] = '\0';
954
955         thte = xalloc(sizeof (thtab_t));
956         thte->th_name = name;
957         thte->th_idx = tidx;
958         thte->th_nxt = thtab[h];
959         thtab[h] = thte;
960
961         return ((u_short)tidx++);
962 }
963
964 /*
965  * Hash function for types
966  */
967 static int
968 thash(const char *s, size_t len)
969 {
970         u_int   v;
971
972         v = 0;
973         while (len-- != 0) {
974                 v = (v << sizeof (v)) + (u_char)*s++;
975                 v ^= v >> (sizeof (v) * CHAR_BIT - sizeof (v));
976         }
977         return (v % THSHSIZ2);
978 }
979
980 /*
981  * Read a string enclosed by "". This string may contain quoted chars.
982  */
983 static char *
984 inpqstrg(const char *src, const char **epp)
985 {
986         char    *strg, *dst;
987         size_t  slen;
988         int     c;
989         int     v;
990
991         if ((dst = strg = malloc(slen = 32)) == NULL)
992                 nomem();
993
994         if ((c = *src++) != '"')
995                 inperr();
996         if ((c = *src++) == '\0')
997                 inperr();
998
999         while (c != '"') {
1000                 if (c == '\\') {
1001                         if ((c = *src++) == '\0')
1002                                 inperr();
1003                         switch (c) {
1004                         case 'n':
1005                                 c = '\n';
1006                                 break;
1007                         case 't':
1008                                 c = '\t';
1009                                 break;
1010                         case 'v':
1011                                 c = '\v';
1012                                 break;
1013                         case 'b':
1014                                 c = '\b';
1015                                 break;
1016                         case 'r':
1017                                 c = '\r';
1018                                 break;
1019                         case 'f':
1020                                 c = '\f';
1021                                 break;
1022                         case 'a':
1023                                 c = '\a';
1024                                 break;
1025                         case '\\':
1026                                 c = '\\';
1027                                 break;
1028                         case '"':
1029                                 c = '"';
1030                                 break;
1031                         case '\'':
1032                                 c = '\'';
1033                                 break;
1034                         case '0': case '1': case '2': case '3':
1035                                 v = (c - '0') << 6;
1036                                 if ((c = *src++) < '0' || c > '7')
1037                                         inperr();
1038                                 v |= (c - '0') << 3;
1039                                 if ((c = *src++) < '0' || c > '7')
1040                                         inperr();
1041                                 v |= c - '0';
1042                                 c = (u_char)v;
1043                                 break;
1044                         default:
1045                                 inperr();
1046                         }
1047                 }
1048                 /* keep space for trailing '\0' */
1049                 if (dst - strg == slen - 1) {
1050                         if ((strg = realloc(strg, slen * 2)) == NULL)
1051                                 nomem();
1052                         dst = strg + (slen - 1);
1053                         slen *= 2;
1054                 }
1055                 *dst++ = (char)c;
1056                 if ((c = *src++) == '\0')
1057                         inperr();
1058         }
1059         *dst = '\0';
1060
1061         *epp = src;
1062         return (strg);
1063 }
1064
1065 /*
1066  * Read the name of a symbol in static memory.
1067  */
1068 static const char *
1069 inpname(const char *cp, const char **epp)
1070 {
1071         static  char    *buf;
1072         static  size_t  blen = 0;
1073         size_t  len, i;
1074         char    *eptr, c;
1075
1076         len = (int)strtol(cp, &eptr, 10);
1077         if (cp == eptr)
1078                 inperr();
1079         cp = eptr;
1080         if (len + 1 > blen)
1081                 if ((buf = realloc(buf, blen = len + 1)) == NULL)
1082                         nomem();
1083         for (i = 0; i < len; i++) {
1084                 c = *cp++;
1085                 if (!isalnum((unsigned char)c) && c != '_')
1086                         inperr();
1087                 buf[i] = c;
1088         }
1089         buf[i] = '\0';
1090
1091         *epp = cp;
1092         return (buf);
1093 }
1094
1095 /*
1096  * Return the index of a file name. If the name cannot be found, create
1097  * a new entry and return the index of the newly created entry.
1098  */
1099 static int
1100 getfnidx(const char *fn)
1101 {
1102         int     i;
1103
1104         /* 0 ist reserved */
1105         for (i = 1; fnames[i] != NULL; i++) {
1106                 if (strcmp(fnames[i], fn) == 0)
1107                         break;
1108         }
1109         if (fnames[i] != NULL)
1110                 return (i);
1111
1112         if (i == nfnames - 1) {
1113                 if ((fnames = realloc(fnames, (nfnames * 2) * sizeof (char *)))
1114                     == NULL)
1115                         nomem();
1116                 (void)memset(fnames + nfnames, 0, nfnames * sizeof (char *));
1117                 nfnames *= 2;
1118         }
1119
1120         if ((fnames[i] = strdup(fn)) == NULL)
1121                 nomem();
1122         return (i);
1123 }
1124
1125 /*
1126  * Separate symbols with static and external linkage.
1127  */
1128 void
1129 mkstatic(hte_t *hte)
1130 {
1131         sym_t   *sym1, **symp, *sym;
1132         fcall_t **callp, *call;
1133         usym_t  **usymp, *usym;
1134         hte_t   *nhte;
1135         int     ofnd;
1136
1137         /* Look for first static definition */
1138         for (sym1 = hte->h_syms; sym1 != NULL; sym1 = sym1->s_nxt) {
1139                 if (sym1->s_static)
1140                         break;
1141         }
1142         if (sym1 == NULL)
1143                 return;
1144
1145         /* Do nothing if this name is used only in one translation unit. */
1146         ofnd = 0;
1147         for (sym = hte->h_syms; sym != NULL && !ofnd; sym = sym->s_nxt) {
1148                 if (sym->s_pos.p_src != sym1->s_pos.p_src)
1149                         ofnd = 1;
1150         }
1151         for (call = hte->h_calls; call != NULL && !ofnd; call = call->f_nxt) {
1152                 if (call->f_pos.p_src != sym1->s_pos.p_src)
1153                         ofnd = 1;
1154         }
1155         for (usym = hte->h_usyms; usym != NULL && !ofnd; usym = usym->u_nxt) {
1156                 if (usym->u_pos.p_src != sym1->s_pos.p_src)
1157                         ofnd = 1;
1158         }
1159         if (!ofnd) {
1160                 hte->h_used = 1;
1161                 /* errors about undef. static symbols are printed in lint1 */
1162                 hte->h_def = 1;
1163                 hte->h_static = 1;
1164                 return;
1165         }
1166
1167         /*
1168          * Create a new hash table entry
1169          *
1170          * XXX this entry should be put at the beginning of the list to
1171          * avoid to process the same symbol twice.
1172          */
1173         for (nhte = hte; nhte->h_link != NULL; nhte = nhte->h_link)
1174                 continue;
1175         nhte->h_link = xmalloc(sizeof (hte_t));
1176         nhte = nhte->h_link;
1177         nhte->h_name = hte->h_name;
1178         nhte->h_used = 1;
1179         nhte->h_def = 1;        /* error in lint1 */
1180         nhte->h_static = 1;
1181         nhte->h_syms = NULL;
1182         nhte->h_lsym = &nhte->h_syms;
1183         nhte->h_calls = NULL;
1184         nhte->h_lcall = &nhte->h_calls;
1185         nhte->h_usyms = NULL;
1186         nhte->h_lusym = &nhte->h_usyms;
1187         nhte->h_link = NULL;
1188         nhte->h_hte = NULL;
1189
1190         /*
1191          * move all symbols used in this translation unit into the new
1192          * hash table entry.
1193          */
1194         for (symp = &hte->h_syms; (sym = *symp) != NULL; ) {
1195                 if (sym->s_pos.p_src == sym1->s_pos.p_src) {
1196                         sym->s_static = 1;
1197                         (*symp) = sym->s_nxt;
1198                         if (hte->h_lsym == &sym->s_nxt)
1199                                 hte->h_lsym = symp;
1200                         sym->s_nxt = NULL;
1201                         *nhte->h_lsym = sym;
1202                         nhte->h_lsym = &sym->s_nxt;
1203                 } else {
1204                         symp = &sym->s_nxt;
1205                 }
1206         }
1207         for (callp = &hte->h_calls; (call = *callp) != NULL; ) {
1208                 if (call->f_pos.p_src == sym1->s_pos.p_src) {
1209                         (*callp) = call->f_nxt;
1210                         if (hte->h_lcall == &call->f_nxt)
1211                                 hte->h_lcall = callp;
1212                         call->f_nxt = NULL;
1213                         *nhte->h_lcall = call;
1214                         nhte->h_lcall = &call->f_nxt;
1215                 } else {
1216                         callp = &call->f_nxt;
1217                 }
1218         }
1219         for (usymp = &hte->h_usyms; (usym = *usymp) != NULL; ) {
1220                 if (usym->u_pos.p_src == sym1->s_pos.p_src) {
1221                         (*usymp) = usym->u_nxt;
1222                         if (hte->h_lusym == &usym->u_nxt)
1223                                 hte->h_lusym = usymp;
1224                         usym->u_nxt = NULL;
1225                         *nhte->h_lusym = usym;
1226                         nhte->h_lusym = &usym->u_nxt;
1227                 } else {
1228                         usymp = &usym->u_nxt;
1229                 }
1230         }
1231
1232         /* h_def must be recalculated for old hte */
1233         hte->h_def = nhte->h_def = 0;
1234         for (sym = hte->h_syms; sym != NULL; sym = sym->s_nxt) {
1235                 if (sym->s_def == DEF || sym->s_def == TDEF) {
1236                         hte->h_def = 1;
1237                         break;
1238                 }
1239         }
1240
1241         mkstatic(hte);
1242 }