From 67a2cc281f4a28e74df3d7e34e3ab791573cb3e8 Mon Sep 17 00:00:00 2001 From: dick Date: Fri, 8 Mar 1991 15:54:05 +0000 Subject: [PATCH] ANSI C prototype handling added --- lang/cem/lint/lpass2/Makefile | 13 +- lang/cem/lint/lpass2/checkargs.c | 23 +++- lang/cem/lint/lpass2/class.c | 54 +++----- lang/cem/lint/lpass2/class.h | 2 +- lang/cem/lint/lpass2/lpass2.c | 207 +++++++++++++++++++++---------- lang/cem/lint/lpass2/read.c | 18 +-- lang/cem/lint/lpass2/report.c | 8 +- 7 files changed, 196 insertions(+), 129 deletions(-) diff --git a/lang/cem/lint/lpass2/Makefile b/lang/cem/lint/lpass2/Makefile index 605ac8524..40cd686f2 100644 --- a/lang/cem/lint/lpass2/Makefile +++ b/lang/cem/lint/lpass2/Makefile @@ -6,8 +6,8 @@ # M A K E F I L E F O R L P A S S 2 # Machine and environ dependent definitions -EMHOME = /usr/proj/em/Work -LPASS1 = $(EMHOME)/lang/cem/cemcom +EMHOME = ../../.. +LPASS1 = ../lpass1# ??? # Libraries and EM interface definitions SYSLIB = $(EMHOME)/modules/lib/libsystem.a @@ -28,8 +28,8 @@ SRC = lpass2.c checkargs.c read.c report.c class.c l_print3ack.c OBJ = lpass2.o checkargs.o read.o report.o class.o l_print3ack.o test: lpass2 - make lint.test -# lpass2 -xh <.i + lpass2 -xh next.c @@ -49,7 +49,8 @@ clean: rm -f a.out core next.c inpdef.h $(OBJ) next.o #---------------------------------------------------------------- +checkargs.o: inpdef.h private.h class.o: ../lpass1/l_class.h class.h lpass2.o: ../lpass1/l_class.h ../lpass1/l_lint.h class.h inpdef.h private.h read.o: ../lpass1/l_class.h class.h inpdef.h private.h -report.o: inpdef.h +report.o: ../lpass1/l_class.h class.h inpdef.h private.h diff --git a/lang/cem/lint/lpass2/checkargs.c b/lang/cem/lint/lpass2/checkargs.c index 979362724..bd99f2680 100644 --- a/lang/cem/lint/lpass2/checkargs.c +++ b/lang/cem/lint/lpass2/checkargs.c @@ -18,7 +18,7 @@ PRIVATE int is_formatargs; /* present or not */ PRIVATE char formatargs[1000]; /* the definitions */ PRIVATE chk_argtps(); -PRIVATE char *next_atype(); +PRIVATE char *next_argtype(); PRIVATE int type_match(); PRIVATE form_type(); @@ -37,6 +37,14 @@ chk_args(id, def) char *act_tp = id->id_argtps; int nrargs = 0; /* number of args */ + /* void is a special case */ + if ( /* the definition has one void argument */ + def->id_nrargs == 1 && streq(def->id_argtps, "void:") + && /* the referent has no argumants */ + id->id_nrargs == 0 + ) /* we have a prefect match */ + return; + /* clear format */ is_formatargs = 0; @@ -49,7 +57,7 @@ chk_args(id, def) /* skip over the actuals already covered */ for (i = 0; i < nrargs; i++) { - act_tp = next_atype(act_tp); + act_tp = next_argtype(act_tp); } /* and check the format arguments */ @@ -65,16 +73,16 @@ PRIVATE chk_argtps(id, def, nrargs, act_tp, form_tp) char *act_tp; /* actual types */ char *form_tp; /* formal type definitions */ { - while (*act_tp && *form_tp) { + while (*act_tp && *form_tp && *form_tp != '.') { register char *act_start = act_tp; register char *form_start = form_tp; /* isolate actual argument type */ - act_tp = next_atype(act_tp); + act_tp = next_argtype(act_tp); act_tp[-1] = '\0'; /* isolate formal argument type */ - form_tp = next_atype(form_tp); + form_tp = next_argtype(form_tp); form_tp[-1] = '\0'; (*nrargs)++; @@ -92,6 +100,9 @@ PRIVATE chk_argtps(id, def, nrargs, act_tp, form_tp) form_tp[-1] = ':'; } + if (*form_tp == '.') /* ellipsis */ + return; + if (*form_tp) { /* formal type definitions not exhausted */ report("%L: %s has fewer arguments than in %L", @@ -110,7 +121,7 @@ PRIVATE chk_argtps(id, def, nrargs, act_tp, form_tp) } PRIVATE char * -next_atype(tp) +next_argtype(tp) char *tp; { while (*tp && *tp != ':') { diff --git a/lang/cem/lint/lpass2/class.c b/lang/cem/lint/lpass2/class.c index d74052605..aed53508a 100644 --- a/lang/cem/lint/lpass2/class.c +++ b/lang/cem/lint/lpass2/class.c @@ -7,47 +7,23 @@ #include "../lpass1/l_class.h" #include "class.h" -int class[] = { - /* mapping of class values onto bit patterns */ - /* LFDF */ CL_LIB|CL_FUNC|CL_DEF, - /* LVDF */ CL_LIB|CL_VAR|CL_DEF, - /* EFDF */ CL_EXT|CL_FUNC|CL_DEF, - /* EVDF */ CL_EXT|CL_VAR|CL_DEF, - /* EFDC */ CL_EXT|CL_FUNC|CL_DECL, - /* EVDC */ CL_EXT|CL_VAR|CL_DECL, - /* IFDC */ CL_IMPL|CL_FUNC|CL_DECL, - /* SFDF */ CL_STAT|CL_FUNC|CL_DEF, - /* SVDF */ CL_STAT|CL_VAR|CL_DEF, - /* FC */ CL_FUNC|CL_USAGE, - /* VU */ CL_VAR|CL_USAGE -}; - -static int val[] = { - LFDF, - LVDF, - EFDF, - EVDF, - EFDC, - EVDC, - IFDC, - SFDF, - SVDF, - FC, - VU -}; +int class[MAX_CLASS_CONST-MIN_CLASS_CONST+1]; init_class() { - /* The initialization of class[] has been taken care of above. - For it to work, we have to test that the class values are - in the right order. This is also necessary for the scanning - sequence in lpass2.c to work properly. - */ - int i; - - for (i = 0; i+1 < sizeof(val)/sizeof(val[0]); i++) { - if (val[i] >= val[i+1]) - panic("class values out of sequence"); - } + /* mapping of class values onto bit patterns */ + class[LFDF-LFDF] = CL_LIB | CL_FUNC | CL_DEF; + class[LVDF-LFDF] = CL_LIB | CL_VAR | CL_DEF; + class[PFDF-LFDF] = CL_EXT | CL_FUNC | CL_DEF; + class[EFDF-LFDF] = CL_EXT | CL_FUNC | CL_DEF; + class[EVDF-LFDF] = CL_EXT | CL_VAR | CL_DEF; + class[EFDC-LFDF] = CL_EXT | CL_FUNC | CL_DECL; + class[EVDC-LFDF] = CL_EXT | CL_VAR | CL_DECL; + class[IFDC-LFDF] = CL_IMPL | CL_FUNC | CL_DECL; + class[SFDF-LFDF] = CL_STAT | CL_FUNC | CL_DEF; + class[SVDF-LFDF] = CL_STAT | CL_VAR | CL_DEF; + class[FC-LFDF] = CL_FUNC | CL_USAGE; + class[VU-LFDF] = CL_VAR | CL_USAGE; + class[XXDF-LFDF] = 0; } diff --git a/lang/cem/lint/lpass2/class.h b/lang/cem/lint/lpass2/class.h index 29f012c1f..ed32b4a39 100644 --- a/lang/cem/lint/lpass2/class.h +++ b/lang/cem/lint/lpass2/class.h @@ -26,5 +26,5 @@ extern int class[]; -#define is_class(id,cl) ((class[(id)->id_class-'a'] & (cl)) == (cl)) +#define is_class(id,cl) ((class[(id)->id_class-MIN_CLASS_CONST] & (cl)) == (cl)) diff --git a/lang/cem/lint/lpass2/lpass2.c b/lang/cem/lint/lpass2/lpass2.c index ca73e1afe..87286a483 100644 --- a/lang/cem/lint/lpass2/lpass2.c +++ b/lang/cem/lint/lpass2/lpass2.c @@ -17,10 +17,13 @@ extern char *strcpy(); #define streq(s1,s2) (strcmp(s1, s2) == 0) PRIVATE char cur_name[NAMESIZE]; -PRIVATE struct inpdef *dot, *lib, *ext, *sta; +PRIVATE struct inpdef *dot, *lib, *proto, *ext, *sta; +PRIVATE one_name(); PRIVATE chk_def(); PRIVATE ext_decls(); +PRIVATE proto_defs(); +PRIVATE chk_proto(); PRIVATE ext_def(); PRIVATE get_dot(); PRIVATE init(); @@ -35,8 +38,8 @@ PRIVATE usage(); #define same_name() (dot && streq(cur_name, dot->id_name)) #define same_obj(stnr) (same_name() && dot->id_statnr == stnr) -#define defdec(id) (is_class(id, CL_DEF) ? "defined" : "declared") -#define funvar(id) (is_class(id, CL_FUNC) ? "function" : "variable") +#define def_or_dec(id) (is_class(id, CL_DEF) ? "defined" : "declared") +#define fun_or_var(id) (is_class(id, CL_FUNC) ? "function" : "variable") /******** M A I N ********/ @@ -53,24 +56,15 @@ main(argc, argv) free_inpdef(lib); lib = 0; } + if (proto) { + free_inpdef(proto); + proto = 0; + } if (ext) { free_inpdef(ext); ext = 0; } - strcpy(cur_name, dot->id_name); - lib_def(); - ext_def(); - ext_decls(); - usage(0); - if (ext) - chk_def(ext); - statics(); - if (same_name()) { - /* there are more lines for this name that have - not been absorbed - */ - panic("sequence error in intermediate file"); - } + one_name(); } } @@ -81,7 +75,7 @@ PRIVATE init(argc, argv) char *argv[]; { /* - * Parse options + * Get command line options * Prepare standard input for reading using the input-package */ char *result; @@ -107,8 +101,9 @@ PRIVATE init(argc, argv) argc--, argv++; } - if (!InsertFile((char *)0, table, &result)) + if (!InsertFile((char *)0, table, &result)) { panic("InsertFile() fails"); + } } PRIVATE get_dot() @@ -118,8 +113,32 @@ PRIVATE get_dot() dot = 0; cur_name[0] = '\0'; } + if (loptions['X']) { + print_id("get_dot", dot); + } } +PRIVATE one_name() +{ + strcpy(cur_name, dot->id_name); + lib_def(); + proto_defs(); + ext_def(); + ext_decls(); + usage(0); + if (proto) { + chk_def(proto); + } + else + if (ext) { + chk_def(ext); + } + statics(); + if (same_name()) { + /* there are lines for this name that have not been absorbed */ + panic("sequence error in intermediate file"); + } +} /******** L I B R A R Y ********/ @@ -129,12 +148,42 @@ PRIVATE lib_def() lib = dot; dot = new_inpdef(); get_dot(); + while (same_obj(0) && is_class(dot, CL_LIB)) { + report(">%L: multiple definition of %s in library", + dot, dot->id_name); + get_dot(); + } } +} - while (same_obj(0) && is_class(dot, CL_LIB)) { - report(">%L: multiple definition of %s in library", - dot, dot->id_name); + +/******** P R O T O T Y P E S ********/ +PRIVATE proto_defs() +{ + if (same_obj(0) && dot->id_class == PFDF) { + if (lib) { + report("%L: function %s also defined in %L", + dot, dot->id_name, lib); + } + proto = dot; + dot = new_inpdef(); get_dot(); + while (same_obj(0) && dot->id_class == PFDF) { + chk_proto(dot); + get_dot(); + } + } +} + +PRIVATE chk_proto(def) + struct inpdef *def; +{ + if (proto->id_args) { + chk_args(def, proto); + } + if (!type_equal(def->id_type, proto->id_type)) { + report("%L: return type of function %s declared differently at %L", + def, def->id_name, proto); } } @@ -144,19 +193,21 @@ PRIVATE lib_def() PRIVATE ext_def() { if (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) { - if (lib) { + if (lib && !proto) { report("%L: %s %s also defined in %L", - dot, funvar(dot), dot->id_name, lib); + dot, fun_or_var(dot), dot->id_name, lib); + } + if (proto) { + chk_proto(dot); } ext = dot; dot = new_inpdef(); get_dot(); - } - - while (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) { - report("%L: %s %s also defined at %L", - dot, funvar(dot), dot->id_name, ext); - get_dot(); + while (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) { + report("%L: %s %s also defined at %L", + dot, fun_or_var(dot), dot->id_name, ext); + get_dot(); + } } } @@ -180,7 +231,7 @@ PRIVATE one_ext_decl(kind, other_kind, other_class) char *other_kind; int other_class; { - struct inpdef *def = ext ? ext : lib ? lib : 0; + struct inpdef *def = (proto ? proto : ext ? ext : lib ? lib : 0); if (!def) { /* the declaration will have to serve */ @@ -193,7 +244,9 @@ PRIVATE one_ext_decl(kind, other_kind, other_class) if (is_class(def, other_class)) { /* e.g.: function FFF declared as variable at ... */ report("%L: %s %s %s as %s at %L", - dot, kind, dot->id_name, defdec(def), other_kind, def); + dot, kind, dot->id_name, + def_or_dec(def), other_kind, def + ); /* no further testing possible */ get_dot(); return; @@ -202,7 +255,11 @@ PRIVATE one_ext_decl(kind, other_kind, other_class) if (!type_equal(dot->id_type, def->id_type)) { /* e.g.: type of variable VVV defined differently at ... */ report("%L: type of %s %s %s differently at %L", - dot, kind, dot->id_name, defdec(def), def); + dot, kind, dot->id_name, def_or_dec(def), def); + + /* no further testing needed */ + get_dot(); + return; } get_dot(); @@ -214,7 +271,8 @@ PRIVATE one_ext_decl(kind, other_kind, other_class) PRIVATE usage(stnr) int stnr; { - register struct inpdef *def = stnr ? sta : ext ? ext : lib ? lib : 0; + register struct inpdef *def = + (stnr ? sta : proto ? proto : ext ? ext : lib ? lib : 0); register int VU_count = 0; register int VU_samefile = 0; @@ -236,8 +294,9 @@ PRIVATE usage(stnr) if ( stnr == 0 && VU_count == 1 && VU_samefile == 1 - && def == ext - && !is_class(ext, CL_IMPL) + && ( def == proto + || (def == ext && !is_class(ext, CL_IMPL)) + ) && streq(&fn[strlen(fn)-2], ".c") ) { report("%L: extern %s could be declared static", @@ -313,20 +372,25 @@ PRIVATE statics() while (same_name()) { int stnr = dot->id_statnr; - if (stnr == 0) - panic("sequence error in input"); + if (stnr == 0) { + panic("sequence error in intermediate file: externals after statics"); + } if (sta) { free_inpdef(sta); sta = 0; } + stat_def(stnr); usage(stnr); - if (sta) - chk_def(sta); - if (same_obj(stnr)) - panic("sequence error in input"); + if (sta) { + chk_def(sta); + } + + if (same_obj(stnr)) { + panic("sequence error in intermediate file: statics out of order"); + } } } @@ -336,24 +400,26 @@ PRIVATE stat_def(stnr) if (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) { if (lib) { report("%L: %s %s also defined in %L", - dot, funvar(dot), dot->id_name, lib); + dot, fun_or_var(dot), dot->id_name, lib); } - if (ext) { - if (!streq(dot->id_file, ext->id_file)) { + if (proto || ext) { + struct inpdef *def = (proto ? proto : ext); + + if (!streq(dot->id_file, def->id_file)) { report("%L: %s %s also %s at %L", - dot, funvar(dot), dot->id_name, - defdec(ext), ext); + dot, fun_or_var(dot), dot->id_name, + def_or_dec(def), def + ); } } sta = dot; dot = new_inpdef(); get_dot(); - } - - while (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) { - report("%L: %s %s also defined at %L", - dot, funvar(dot), dot->id_name, sta); - get_dot(); + while (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) { + report("%L: %s %s also defined at %L", + dot, fun_or_var(dot), dot->id_name, sta); + get_dot(); + } } } @@ -373,7 +439,7 @@ PRIVATE chk_def(def) else { if (!loptions['u']) { report("%L: %s %s not used anywhere", - def, funvar(def), def->id_name); + def, fun_or_var(def), def->id_name); } } } @@ -398,9 +464,15 @@ print_id(name, id) char *name; struct inpdef *id; { + if (!id) { + print("%s: \n", name); + return; + } + print("%s: %s, %s, %04d, \"%s\", %d, %s", name, id->id_class == LFDF ? "LFDF" : id->id_class == LVDF ? "LVDF" : + id->id_class == PFDF ? "PFDF" : id->id_class == EFDF ? "EFDF" : id->id_class == EVDF ? "EVDF" : id->id_class == EFDC ? "EFDC" : @@ -419,19 +491,22 @@ print_id(name, id) if (is_class(id, CL_FUNC|CL_DEF) || is_class(id, CL_FUNC|CL_USAGE)) { print(", %d, %s, %s", id->id_nrargs, - id->id_nrargs == 0 ? "" : id->id_argtps, - id->id_class == FC ? - (id->id_valused == USED ? "USED" : - id->id_valused == IGNORED ? "IGNORED" : - id->id_valused == VOIDED ? "VOIDED" : - "") - : (id->id_valreturned == NOVALRETURNED ? - "NOVALRETURNED" : - id->id_valreturned == VALRETURNED ? - "VALRETURNED" : - id->id_valreturned == NORETURN ? - "NORETURN" : "" + (id->id_nrargs == 0 ? "" : id->id_argtps), + ( id->id_class == FC + ? ( id->id_valused == USED ? "USED" : + id->id_valused == IGNORED ? "IGNORED" : + id->id_valused == VOIDED ? "VOIDED" : + "" ) + : ( id->id_valreturned == NOVALRETURNED + ? "NOVALRETURNED" + : id->id_valreturned == VALRETURNED + ? "VALRETURNED" + : id->id_valreturned == NORETURN + ? "NORETURN" + : "" + ) + ) ); } print("\n"); diff --git a/lang/cem/lint/lpass2/read.c b/lang/cem/lint/lpass2/read.c index 6af6bcf8d..07a43186e 100644 --- a/lang/cem/lint/lpass2/read.c +++ b/lang/cem/lint/lpass2/read.c @@ -92,7 +92,7 @@ ReadString(buf, delim, maxsize) /* Reads a string until 'delim' is encountered; delim is discarded. If 'maxsize-1' is exceeded or the string contains a newline - (which is not delim), panic() is called. + panic() is called (unless delim == newline). A '\0' is appended to the string. */ @@ -106,14 +106,14 @@ ReadString(buf, delim, maxsize) if (ch == delim) break; if (ch == '\n') { - panic("newline in string"); + panic("incomplete line in intermediate file"); /*NOTREACHED*/ } buf[nread++] = (char)ch; } buf[nread++] = '\0'; if (ch != delim) { - panic("string too long"); + panic("line too long in intermediate file"); /*NOTREACHED*/ } return 1; @@ -148,7 +148,7 @@ ReadInt(ip) loadchar(ch); } pushback(ch); - *ip = negative ? -res : res; + *ip = (negative ? -res : res); return 1; } @@ -213,9 +213,11 @@ PRIVATE SkipChar(ch) int c; loadchar(c); - if (c != ch) { - panic("bad format, '%c' expected; '%c' read", ch, c); - /*NOTREACHED*/ - } + if (c == ch) + return; + panic("bad format in intermediate file, '%c' expected; '%c' read", + ch, c + ); + /*NOTREACHED*/ } diff --git a/lang/cem/lint/lpass2/report.c b/lang/cem/lint/lpass2/report.c index 7ca1700c4..010e21b0b 100644 --- a/lang/cem/lint/lpass2/report.c +++ b/lang/cem/lint/lpass2/report.c @@ -8,11 +8,12 @@ #include #include "private.h" +#include "../lpass1/l_class.h" #include "class.h" #include "inpdef.h" -#define MSGOUT STDERR /* filedes on which to write the messages */ -#define ERROUT STDERR /* filedes on which to write the panics */ +#define MSGOUT STDERR /* file descr. on which to write the messages */ +#define ERROUT STDERR /* file descr. on which to write the panics */ extern int LineNr; @@ -75,7 +76,8 @@ report(va_alist) fprint(MSGOUT, "%d", i); break; default: - panic("bad format %s", fmt); + panic("internal error: bad format %s", + fmt); break; } }