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