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