1 /* $NetBSD: read.c,v 1.2 1995/07/03 21:24:59 cgd Exp $ */
4 * Copyright (c) 1994, 1995 Jochen Pohl
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
33 * $NetBSD: read.c,v 1.2 1995/07/03 21:24:59 cgd Exp $
34 * $DragonFly: src/usr.bin/xlint/lint2/read.c,v 1.7 2004/07/07 12:13:26 asmodai Exp $
47 /* index of current (included) source file */
51 * The array pointed to by inpfns maps the file name indices of input files
52 * to the file name indices used in lint2
55 static size_t ninpfns
;
58 * The array pointed to by *fnames maps file name indizes to file names.
59 * Indices of type short are used instead of pointers to save memory.
62 static size_t nfnames
;
65 * Types are shared (to save memory for the types itself) and accessed
66 * via indices (to save memory for references to types (indices are short)).
67 * To share types, a equal type must be located fast. This is done by a
68 * hash table. Access by indices is done via an array of pointers to the
71 typedef struct thtab
{
76 static thtab_t
**thtab
; /* hash table */
77 type_t
**tlst
; /* array for indexed access */
78 static size_t tlstlen
; /* length of tlst */
80 /* index of current C source file (as spezified at the command line) */
84 static void inperr(void);
85 static void setsrc(const char *);
86 static void setfnid(int, const char *);
87 static void funccall(pos_t
*, const char *);
88 static void decldef(pos_t
*, const char *);
89 static void usedsym(pos_t
*, const char *);
90 static u_short
inptype(const char *, const char **);
91 static int gettlen(const char *, const char **);
92 static u_short
findtype(const char *, size_t, int);
93 static u_short
storetyp(type_t
*, const char *, size_t, int);
94 static int thash(const char *, size_t);
95 static char *inpqstrg(const char *, const char **);
96 static const char *inpname(const char *, const char **);
97 static int getfnidx(const char *);
100 readfile(const char *name
)
105 char *line
, *eptr
, rt
;
106 int cline
, isrc
, iline
;
110 inpfns
= xcalloc(ninpfns
= 128, sizeof (short));
112 fnames
= xcalloc(nfnames
= 256, sizeof (char *));
114 tlst
= xcalloc(tlstlen
= 256, sizeof (type_t
*));
116 thtab
= xcalloc(THSHSIZ2
, sizeof (thtab_t
));
118 srcfile
= getfnidx(name
);
120 if ((inp
= fopen(name
, "r")) == NULL
)
121 err(1, "cannot open %s", name
);
123 while ((line
= fgetln(inp
, &len
)) != NULL
) {
125 if (len
== 0 || line
[len
- 1] != '\n')
127 line
[len
- 1] = '\0';
130 /* line number in csrcfile */
131 cline
= (int)strtol(cp
, &eptr
, 10);
148 } else if (rt
== 's') {
154 * Index of (included) source file. If this index is
155 * different from csrcfile, it refers to an included
158 isrc
= (int)strtol(cp
, &eptr
, 10);
164 /* line number in isrc */
167 iline
= (int)strtol(cp
, &eptr
, 10);
172 pos
.p_src
= (u_short
)csrcfile
;
173 pos
.p_line
= (u_short
)cline
;
174 pos
.p_isrc
= (u_short
)isrc
;
175 pos
.p_iline
= (u_short
)iline
;
177 /* process rest of this record */
195 err(1, "read error on %s", name
);
204 errx(1, "input file error: %s", fnames
[srcfile
]);
208 * Set the name of the C source file of the .ln file which is
212 setsrc(const char *cp
)
214 csrcfile
= getfnidx(cp
);
218 * setfnid() gets as input an index as used in an input file and the
219 * associated file name. If neccessary, it creates a new lint2 file
220 * name index for this file name and creates the mapping of the index
221 * as used in the input file to the index used in lint2.
224 setfnid(int fid
, const char *cp
)
229 if (fid
>= ninpfns
) {
230 inpfns
= xrealloc(inpfns
, (ninpfns
* 2) * sizeof (short));
231 (void)memset(inpfns
+ ninpfns
, 0, ninpfns
* sizeof (short));
235 * Should always be true because indices written in the output
236 * file by lint1 are always the previous index + 1.
239 errx(1, "internal error: setfnid()");
240 inpfns
[fid
] = (u_short
)getfnidx(cp
);
244 * Process a function call record (c-record).
247 funccall(pos_t
*posp
, const char *cp
)
255 fcall
= xalloc(sizeof (fcall_t
));
256 STRUCT_ASSIGN(fcall
->f_pos
, *posp
);
260 lai
= &fcall
->f_args
;
261 while ((c
= *cp
) == 'u' || c
== 'i' || c
== 'd' ||
262 c
== 'z' || c
== 'p' || c
== 'n' || c
== 's') {
283 ai
= xalloc(sizeof (arginf_t
));
284 ai
->a_num
= (int)strtol(cp
, &eptr
, 10);
289 ai
->a_pcon
= ai
->a_zero
= 1;
290 } else if (c
== 'p') {
292 } else if (c
== 'n') {
296 ai
->a_fstrg
= inpqstrg(cp
, &cp
);
303 fcall
->f_rused
= rused
;
304 fcall
->f_rdisc
= rdisc
;
306 /* read name of function */
307 hte
= hsearch(inpname(cp
, &cp
), 1);
310 fcall
->f_type
= inptype(cp
, &cp
);
312 *hte
->h_lcall
= fcall
;
313 hte
->h_lcall
= &fcall
->f_nxt
;
320 * Process a declaration or definition (d-record).
323 decldef(pos_t
*posp
, const char *cp
)
330 (void)memset(&sym
, 0, sizeof (sym
));
331 STRUCT_ASSIGN(sym
.s_pos
, *posp
);
336 while ((c
= *cp
) == 't' || c
== 'd' || c
== 'e' || c
== 'u' ||
337 c
== 'r' || c
== 'o' || c
== 's' || c
== 'v' ||
338 c
== 'P' || c
== 'S') {
342 if (sym
.s_def
!= NODECL
)
347 if (sym
.s_def
!= NODECL
)
352 if (sym
.s_def
!= NODECL
)
380 sym
.s_nva
= (short)strtol(cp
, &ep
, 10);
389 sym
.s_nprfl
= (short)strtol(cp
, &ep
, 10);
398 sym
.s_nscfl
= (short)strtol(cp
, &ep
, 10);
406 /* read symbol name */
407 hte
= hsearch(inpname(cp
, &cp
), 1);
409 if (sym
.s_def
== DEF
|| sym
.s_def
== TDEF
)
412 sym
.s_type
= inptype(cp
, &cp
);
415 * Allocate memory for this symbol only if it was not already
416 * declared or tentatively defined at the same location with
417 * the same type. Works only for symbols with external linkage,
418 * because static symbols, tentatively defined at the same location
419 * but in different translation units are really different symbols.
421 for (symp
= hte
->h_syms
; symp
!= NULL
; symp
= symp
->s_nxt
) {
422 if (symp
->s_pos
.p_isrc
== sym
.s_pos
.p_isrc
&&
423 symp
->s_pos
.p_iline
== sym
.s_pos
.p_iline
&&
424 symp
->s_type
== sym
.s_type
&&
425 ((symp
->s_def
== DECL
&& sym
.s_def
== DECL
) ||
426 (!sflag
&& symp
->s_def
== TDEF
&& sym
.s_def
== TDEF
)) &&
427 !symp
->s_static
&& !sym
.s_static
) {
433 /* allocsym reserviert keinen Platz fuer s_nva */
434 if (sym
.s_va
|| sym
.s_prfl
|| sym
.s_scfl
) {
435 symp
= xalloc(sizeof (sym_t
));
436 STRUCT_ASSIGN(*symp
, sym
);
438 symp
= xalloc(sizeof (symp
->s_s
));
439 STRUCT_ASSIGN(symp
->s_s
, sym
.s_s
);
442 hte
->h_lsym
= &symp
->s_nxt
;
450 * Read an u-record (emited by lint1 if a symbol was used).
453 usedsym(pos_t
*posp
, const char *cp
)
458 usym
= xalloc(sizeof (usym_t
));
459 STRUCT_ASSIGN(usym
->u_pos
, *posp
);
461 /* needed as delimiter between two numbers */
465 hte
= hsearch(inpname(cp
, &cp
), 1);
468 *hte
->h_lusym
= usym
;
469 hte
->h_lusym
= &usym
->u_nxt
;
473 * Read a type and return the index of this type.
476 inptype(const char *cp
, const char **epp
)
486 /* If we have this type already, return it's index. */
487 tlen
= gettlen(cp
, &ep
);
489 if ((tidx
= findtype(cp
, tlen
, h
)) != 0) {
494 /* No, we must create a new type. */
495 tp
= xalloc(sizeof (type_t
));
497 tidx
= storetyp(tp
, cp
, tlen
, h
);
501 while (c
== 'c' || c
== 'v') {
510 if (c
== 's' || c
== 'u' || c
== 'l' || c
== 'e') {
519 tp
->t_tspec
= s
== 's' ? SCHAR
: (s
== 'u' ? UCHAR
: CHAR
);
522 tp
->t_tspec
= s
== 'u' ? USHORT
: SHORT
;
525 tp
->t_tspec
= s
== 'u' ? UINT
: INT
;
528 tp
->t_tspec
= s
== 'u' ? ULONG
: LONG
;
531 tp
->t_tspec
= s
== 'u' ? UQUAD
: QUAD
;
534 tp
->t_tspec
= s
== 's' ? FLOAT
: (s
== 'l' ? LDOUBLE
: DOUBLE
);
551 tp
->t_tspec
= s
== 'e' ? ENUM
: (s
== 's' ? STRUCT
: UNION
);
555 switch (tp
->t_tspec
) {
557 tp
->t_dim
= (int)strtol(cp
, &eptr
, 10);
559 tp
->t_subt
= TP(inptype(cp
, &cp
));
562 tp
->t_subt
= TP(inptype(cp
, &cp
));
566 if (isdigit((u_char
)c
)) {
569 narg
= (int)strtol(cp
, &eptr
, 10);
571 tp
->t_args
= xcalloc((size_t)(narg
+ 1),
573 for (i
= 0; i
< narg
; i
++) {
574 if (i
== narg
- 1 && *cp
== 'E') {
578 tp
->t_args
[i
] = TP(inptype(cp
, &cp
));
582 tp
->t_subt
= TP(inptype(cp
, &cp
));
595 tp
->t_tag
= hsearch(inpname(cp
, &cp
), 1);
599 tp
->t_tynam
= hsearch(inpname(cp
, &cp
), 1);
603 /* LINTED (enumeration value(s) not handled in switch) */
613 * Get the length of a type string.
616 gettlen(const char *cp
, const char **epp
)
629 while (c
== 'c' || c
== 'v') {
642 if (c
== 's' || c
== 'u' || c
== 'l' || c
== 'e') {
655 } else if (s
== 'u') {
657 } else if (s
== '\0') {
664 } else if (s
== '\0') {
671 } else if (s
== '\0') {
678 } else if (s
== '\0') {
685 } else if (s
== '\0') {
692 } else if (s
== 'l') {
694 } else if (s
== '\0') {
718 } else if (s
== 's') {
720 } else if (s
== 'u') {
733 (void)strtol(cp
, &eptr
, 10);
737 (void)gettlen(cp
, &cp
);
740 (void)gettlen(cp
, &cp
);
744 if (isdigit((u_char
)c
)) {
745 narg
= (int)strtol(cp
, &eptr
, 10);
747 for (i
= 0; i
< narg
; i
++) {
748 if (i
== narg
- 1 && *cp
== 'E') {
751 (void)gettlen(cp
, &cp
);
755 (void)gettlen(cp
, &cp
);
764 (void)inpname(cp
, &cp
);
767 (void)inpname(cp
, &cp
);
773 /* LINTED (enumeration value(s) not handled in switch) */
783 * Search a type by it's type string.
786 findtype(const char *cp
, size_t len
, int h
)
790 for (thte
= thtab
[h
]; thte
!= NULL
; thte
= thte
->th_nxt
) {
791 if (strncmp(thte
->th_name
, cp
, len
) != 0)
793 if (thte
->th_name
[len
] == '\0')
794 return (thte
->th_idx
);
801 * Store a type and it's type string so we can later share this type
802 * if we read the same type string from the input file.
805 storetyp(type_t
*tp
, const char *cp
, size_t len
, int h
)
808 static u_int tidx
= 1;
812 if (tidx
>= USHRT_MAX
)
813 errx(1, "sorry, too many types");
815 if (tidx
== tlstlen
- 1) {
816 tlst
= xrealloc(tlst
, (tlstlen
* 2) * sizeof (type_t
*));
817 (void)memset(tlst
+ tlstlen
, 0, tlstlen
* sizeof (type_t
*));
823 /* create a hash table entry */
824 name
= xalloc(len
+ 1);
825 (void)memcpy(name
, cp
, len
);
828 thte
= xalloc(sizeof (thtab_t
));
829 thte
->th_name
= name
;
831 thte
->th_nxt
= thtab
[h
];
834 return ((u_short
)tidx
++);
838 * Hash function for types
841 thash(const char *s
, size_t len
)
847 v
= (v
<< sizeof (v
)) + (u_char
)*s
++;
848 v
^= v
>> (sizeof (v
) * CHAR_BIT
- sizeof (v
));
850 return (v
% THSHSIZ2
);
854 * Read a string enclosed by "". This string may contain quoted chars.
857 inpqstrg(const char *src
, const char **epp
)
864 dst
= strg
= xmalloc(slen
= 32);
866 if ((c
= *src
++) != '"')
868 if ((c
= *src
++) == '\0')
873 if ((c
= *src
++) == '\0')
906 case '0': case '1': case '2': case '3':
908 if ((c
= *src
++) < '0' || c
> '7')
911 if ((c
= *src
++) < '0' || c
> '7')
920 /* keep space for trailing '\0' */
921 if (dst
- strg
== slen
- 1) {
922 strg
= xrealloc(strg
, slen
* 2);
923 dst
= strg
+ (slen
- 1);
927 if ((c
= *src
++) == '\0')
937 * Read the name of a symbol in static memory.
940 inpname(const char *cp
, const char **epp
)
943 static size_t blen
= 0;
947 len
= (int)strtol(cp
, &eptr
, 10);
952 buf
= xrealloc(buf
, blen
= len
+ 1);
953 for (i
= 0; i
< len
; i
++) {
955 if (!isalnum(c
) && c
!= '_')
966 * Return the index of a file name. If the name cannot be found, create
967 * a new entry and return the index of the newly created entry.
970 getfnidx(const char *fn
)
975 for (i
= 1; fnames
[i
] != NULL
; i
++) {
976 if (strcmp(fnames
[i
], fn
) == 0)
979 if (fnames
[i
] != NULL
)
982 if (i
== nfnames
- 1) {
983 fnames
= xrealloc(fnames
, (nfnames
* 2) * sizeof (char *));
984 (void)memset(fnames
+ nfnames
, 0, nfnames
* sizeof (char *));
988 fnames
[i
] = xstrdup(fn
);
993 * Separate symbols with static and external linkage.
998 sym_t
*sym1
, **symp
, *sym
;
999 fcall_t
**callp
, *call
;
1000 usym_t
**usymp
, *usym
;
1004 /* Look for first static definition */
1005 for (sym1
= hte
->h_syms
; sym1
!= NULL
; sym1
= sym1
->s_nxt
) {
1012 /* Do nothing if this name is used only in one translation unit. */
1014 for (sym
= hte
->h_syms
; sym
!= NULL
&& !ofnd
; sym
= sym
->s_nxt
) {
1015 if (sym
->s_pos
.p_src
!= sym1
->s_pos
.p_src
)
1018 for (call
= hte
->h_calls
; call
!= NULL
&& !ofnd
; call
= call
->f_nxt
) {
1019 if (call
->f_pos
.p_src
!= sym1
->s_pos
.p_src
)
1022 for (usym
= hte
->h_usyms
; usym
!= NULL
&& !ofnd
; usym
= usym
->u_nxt
) {
1023 if (usym
->u_pos
.p_src
!= sym1
->s_pos
.p_src
)
1028 /* errors about undef. static symbols are printed in lint1 */
1035 * Create a new hash table entry
1037 * XXX this entry should be put at the beginning of the list to
1038 * avoid to process the same symbol twice.
1040 for (nhte
= hte
; nhte
->h_link
!= NULL
; nhte
= nhte
->h_link
) ;
1041 nhte
->h_link
= xalloc(sizeof (hte_t
));
1042 nhte
= nhte
->h_link
;
1043 nhte
->h_name
= hte
->h_name
;
1046 nhte
->h_def
= 1; /* error in lint1 */
1047 nhte
->h_lsym
= &nhte
->h_syms
;
1048 nhte
->h_lcall
= &nhte
->h_calls
;
1049 nhte
->h_lusym
= &nhte
->h_usyms
;
1052 * move all symbols used in this translation unit into the new
1055 for (symp
= &hte
->h_syms
; (sym
= *symp
) != NULL
; ) {
1056 if (sym
->s_pos
.p_src
== sym1
->s_pos
.p_src
) {
1058 (*symp
) = sym
->s_nxt
;
1059 if (hte
->h_lsym
== &sym
->s_nxt
)
1062 *nhte
->h_lsym
= sym
;
1063 nhte
->h_lsym
= &sym
->s_nxt
;
1068 for (callp
= &hte
->h_calls
; (call
= *callp
) != NULL
; ) {
1069 if (call
->f_pos
.p_src
== sym1
->s_pos
.p_src
) {
1070 (*callp
) = call
->f_nxt
;
1071 if (hte
->h_lcall
== &call
->f_nxt
)
1072 hte
->h_lcall
= callp
;
1074 *nhte
->h_lcall
= call
;
1075 nhte
->h_lcall
= &call
->f_nxt
;
1077 callp
= &call
->f_nxt
;
1080 for (usymp
= &hte
->h_usyms
; (usym
= *usymp
) != NULL
; ) {
1081 if (usym
->u_pos
.p_src
== sym1
->s_pos
.p_src
) {
1082 (*usymp
) = usym
->u_nxt
;
1083 if (hte
->h_lusym
== &usym
->u_nxt
)
1084 hte
->h_lusym
= usymp
;
1086 *nhte
->h_lusym
= usym
;
1087 nhte
->h_lusym
= &usym
->u_nxt
;
1089 usymp
= &usym
->u_nxt
;
1093 /* h_def must be recalculated for old hte */
1094 hte
->h_def
= nhte
->h_def
= 0;
1095 for (sym
= hte
->h_syms
; sym
!= NULL
; sym
= sym
->s_nxt
) {
1096 if (sym
->s_def
== DEF
|| sym
->s_def
== TDEF
) {