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