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