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