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