From: dick Date: Sun, 7 Aug 1988 22:55:20 +0000 (+0000) Subject: many improvements X-Git-Tag: release-5-5~2945 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=56fff3d6cdd6087da1ef6c814f9417edcd04cfbd;p=ack.git many improvements --- diff --git a/lang/cem/lint/lpass2/ChangeLog b/lang/cem/lint/lpass2/ChangeLog index 7853c6958..23d4f6e87 100644 --- a/lang/cem/lint/lpass2/ChangeLog +++ b/lang/cem/lint/lpass2/ChangeLog @@ -1,3 +1,21 @@ + 7-Aug-88 Dick Grune (dick) at dick + About the class of an inpdef, often set-like questions are asked. + To speed up answering these questions, a mapping has been created + of the values of `class' onto answers to these questions. See + class.[ch]. + + 5-Aug-88 Dick Grune (dick) at dick + Streamlined the program by rearranging the input sequence: + - library + - external defs + - external decls + - external usage + - static defs + - static usage + This change to a much more natural order has been possible by the + introduction of the static file number. Many pieces of code could + now be taken together and the program is much cleaner now. + 8-Jul-88 Dick Grune (dick) at dick Added a special meta-type (also in lpaas1) for non-negative constant actual arguments, because these may match both the signed diff --git a/lang/cem/lint/lpass2/Makefile b/lang/cem/lint/lpass2/Makefile index a81e05548..37a5df105 100644 --- a/lang/cem/lint/lpass2/Makefile +++ b/lang/cem/lint/lpass2/Makefile @@ -1,26 +1,26 @@ # M A K E F I L E F O R L P A S S 2 # Machine and environ dependent definitions -EMHOME = /usr/em -LPASS1 = ../lpass1 +EMHOME = /usr/em +LPASS1 = ../lpass1 # Libraries and EM interface definitions -SYSLIB = $(EMHOME)/modules/lib/libsystem.a -STRLIB = $(EMHOME)/modules/lib/libstring.a -PRTLIB = $(EMHOME)/modules/lib/libprint.a -INPLIB = $(EMHOME)/modules/lib/libinput.a -ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a -MALLOC = $(EMHOME)/modules/lib/malloc.o -LLIBS = $(INPLIB) $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB) +SYSLIB = $(EMHOME)/modules/lib/libsystem.a +STRLIB = $(EMHOME)/modules/lib/libstring.a +PRTLIB = $(EMHOME)/modules/lib/libprint.a +INPLIB = $(EMHOME)/modules/lib/libinput.a +ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a +MALLOC = $(EMHOME)/modules/lib/malloc.o +LLIBS = $(INPLIB) $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB) -CFLAGS = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg -I/usr/include +CFLAGS = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg -I/usr/include .SUFFIXES: .str .h .str.h: $(LPASS1)/make.allocd <$*.str >$*.h -SRC = lpass2.c read.c -OBJ = lpass2.o read.o +SRC = lpass2.c read.c report.c class.c +OBJ = lpass2.o read.o report.o class.o test: lpass2 make lint @@ -32,7 +32,7 @@ lpass2: $(OBJ) Makefile next.o lint: ../lint $(CFLAGS) $(SRC) next.c #??? -next.c: inpdef.str +next.c: $(LPASS1)/make.next inpdef.str $(LPASS1)/make.next inpdef.str > next.c tags: $(SRC) @@ -42,4 +42,7 @@ clean: rm -f a.out core next.c inpdef.h $(OBJ) next.o #---------------------------------------------------------------- -lpass2.o: ../lpass1/errout.h ../lpass1/lint.h ../lpass1/l_class.h inpdef.h +class.o: class.h +lpass2.o: ../lpass1/l_class.h ../lpass1/l_lint.h class.h inpdef.h +read.o: ../lpass1/l_class.h class.h inpdef.h +report.o: inpdef.h diff --git a/lang/cem/lint/lpass2/class.c b/lang/cem/lint/lpass2/class.c new file mode 100644 index 000000000..b477e4819 --- /dev/null +++ b/lang/cem/lint/lpass2/class.c @@ -0,0 +1,47 @@ +#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 +}; + +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"); + } +} + diff --git a/lang/cem/lint/lpass2/class.h b/lang/cem/lint/lpass2/class.h new file mode 100644 index 000000000..4c961e6d4 --- /dev/null +++ b/lang/cem/lint/lpass2/class.h @@ -0,0 +1,16 @@ +#define CL_DEF (1<<0) +#define CL_DECL (1<<1) +#define CL_USAGE (1<<2) + +#define CL_FUNC (1<<3) +#define CL_VAR (1<<4) + +#define CL_LIB (1<<5) +#define CL_EXT (1<<6) +#define CL_IMPL (1<<7) +#define CL_STAT (1<<8) + +extern int class[]; + +#define is_class(id,cl) ((class[(id)->id_class-'a'] & (cl)) == (cl)) + diff --git a/lang/cem/lint/lpass2/inpdef.str b/lang/cem/lint/lpass2/inpdef.str index 7c85d1835..aa907ac9c 100644 --- a/lang/cem/lint/lpass2/inpdef.str +++ b/lang/cem/lint/lpass2/inpdef.str @@ -5,14 +5,22 @@ struct inpdef { struct inpdef *next; - int id_class; + + /* filled by get_id() */ + int id_class; /* see ../lpass1/l_class.h */ char id_name[NAMESIZE]; + int id_statnr; char id_file[FNAMESIZE]; int id_line; - int id_nrargs; - char id_argtps[ARGTPSSIZE]; - int id_returns; char id_type[TYPESIZE]; + + int id_args; /* set if arguments given */ + int id_nrargs; /* number of args, neg. for varargs */ + char id_argtps[ARGTPSSIZE]; /* argument types, colon separated */ + int id_valreturned; /* for def/decl, set if val returned */ + int id_valused; /* for FC, see ../lpass1/l_lint.h */ + + /* not filled by get_id() */ int id_called; int id_used; int id_ignored; diff --git a/lang/cem/lint/lpass2/lpass2.c b/lang/cem/lint/lpass2/lpass2.c index 4f42089c4..92a0f5660 100644 --- a/lang/cem/lint/lpass2/lpass2.c +++ b/lang/cem/lint/lpass2/lpass2.c @@ -1,46 +1,55 @@ -#include +#include #include "../lpass1/l_lint.h" #include "../lpass1/l_class.h" +#include "class.h" #include "inpdef.h" -#include -#include - -#define MSGOUT STDERR /* filedes on which to write the messages */ -#define ERROUT STDERR /* filedes on which to write the panics */ - #define streq(s1,s2) (strcmp(s1, s2) == 0) #define min(a,b) ((a) <= (b) ? (a) : (b)) -#define type_equal(s1,s2) (streq(s1, s2)) +char cur_name[NAMESIZE]; +struct inpdef *dot, *lib, *ext, *sta; -char *cur_name; -struct inpdef *dot_id, - *ext_def, - *static_def; -struct inpdef *id_read(); +#define same_name() (dot && streq(cur_name, dot->id_name)) +#define same_obj(stnr) (same_name() && dot->id_statnr == stnr) -#define same_name() streq(cur_name, dot_id->id_name) +#define defdec(id) (is_class(id, CL_DEF) ? "defined" : "declared") + + +/******** M A I N ********/ main(argc, argv) char *argv[]; { - struct inpdef *id; - init(argc, argv); - get_dot_id(); - while (dot_id) { - cur_name = dot_id->id_name; - read_defs(); - while (dot_id && same_name()) { - id = id_read(); - check(id); - free_inpdef(id); + dot = new_inpdef(); + get_dot(); + while (dot) { + if (lib) { + free_inpdef(lib); + lib = 0; + } + if (ext) { + free_inpdef(ext); + ext = 0; + } + strcpy(cur_name, dot->id_name); + lib_def(); + ext_def(); + ext_decls(); + usage(0); + if (ext) + check_def(ext); + statics(); + /* inpdefs of class ERRCL are never generated */ + if (same_name()) { + /* there are more lines for this name that have + not been absorbed + */ + panic("sequence error in intermediate file"); } - check_usage(); - free_defs(); } } @@ -50,13 +59,14 @@ static char *table[] = {0}; init(argc, argv) char *argv[]; { -/* Prepare standard input for reading using the input-package - * Read first inpdef into dot_id +/* * Parse options + * Prepare standard input for reading using the input-package */ - char *result; + init_class(); + while (argc > 1 && *argv[1] == '-') { switch (argv[1][1]) { case 'u': @@ -67,7 +77,7 @@ init(argc, argv) options[argv[1][1]] = 1; break; default: - /* ready to extend */ + /* ready to be extended */ break; } argc--, argv++; @@ -77,248 +87,295 @@ init(argc, argv) panic("InsertFile() fails"); } -read_defs() +get_dot() { - struct inpdef *id; + if (!get_id(dot)) { + free_inpdef(dot); + dot = 0; + cur_name[0] = '\0'; + } +} - if (ext_def || static_def) - panic("read_defs: slate not clean");/*???*/ - - while (dot_id && same_name() && is_def(dot_id)) { - id = id_read(); - switch (id->id_class) { - case EFDF: - case EVDF: - if (ext_def) { - report("%L: %s also defined at %L", - id, id->id_name, ext_def); - free_inpdef(id); - } - else { - ext_def = id; - } - break; - case SFDF: - case SVDF: - if (ext_def) { - report("%L: %s also defined at %L", - id, id->id_name, ext_def); - free_inpdef(id); - } - else { - static_in_list(id); - } - break; - case LFDF: - case LVDF: - if (ext_def) { - /* Some libraries contain more than one - * definition - */ - if (is_lib_class(ext_def->id_class)) { - report("%L: %s redefined in library %L", - id, id->id_name, ext_def); - } - free_inpdef(id); - } - else { - ext_def = id; - } - break; - default: - panic("invalid class (%c) in read_defs", id->id_class); + +/******** L I B R A R Y ********/ + +lib_def() +{ + if (same_obj(0) && is_class(dot, CL_LIB)) { + 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(); + } +} + + +/******** E X T E R N ********/ + +ext_def() +{ + if (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) { + if (lib) { + report("%L: %s also defined in library %L", + dot, dot->id_name, lib); } + ext = dot; + dot = new_inpdef(); + get_dot(); + } + + while (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) { + report("%L: %s also defined at %L", + dot, dot->id_name, ext); + get_dot(); } } -struct inpdef * -id_read() +ext_decls() { -/* Returns the value of dot_id if present, 0 otherwise. - * Reads a new inpdef ahead, to which dot_id will be pointing. - * Cur_name will be pointing to id_name of the returned inpdef. - */ - struct inpdef *old_id; - - if (!dot_id) - return (0); - old_id = dot_id; - cur_name = old_id->id_name; - get_dot_id(); - return (old_id); + while (same_obj(0) && dot->id_class == EFDC) { + one_ext_decl("function", "variable", CL_VAR); + } + + while (same_obj(0) && dot->id_class == EVDC) { + one_ext_decl("variable", "function", CL_FUNC); + } + + while (same_obj(0) && dot->id_class == IFDC) { + one_ext_decl("function", "variable", CL_VAR); + } } -get_dot_id() +one_ext_decl(kind, other_kind, other_class) + char *kind; + char *other_kind; + int other_class; { -/* Allocates a new inpdef, calls it dot_id and fills it */ - dot_id = new_inpdef(); - if (!get_id(dot_id)) { - free_inpdef(dot_id); - cur_name = ""; - dot_id = 0; + struct inpdef *def = ext ? ext : lib ? lib : 0; + + if (!def) { + /* the declaration will have to serve */ + if (!is_class(dot, CL_IMPL) && !options['u']) { + report("%L: %s %s declared but never defined", + dot, dot->id_name, kind); + } + ext = dot; + dot = new_inpdef(); + get_dot(); + return; + } + + 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); + /* no further testing possible */ + return; } + + 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); + } + + get_dot(); } -struct inpdef *definition(); -check(id) - struct inpdef *id; +/******** U S A G E ********/ + +usage(stnr) + int stnr; { -/* Checks a declaration, function call or variable usage, described by id, - * against the definitions. - */ - struct inpdef *idef; + struct inpdef *def = stnr ? sta : ext ? ext : lib ? lib : 0; - idef = definition(id); - switch (id->id_class) { - case EFDC: - if (!idef) { - if (!options['u']) { - report("%L: %s declared but never defined", - id, id->id_name); - } - discard_defs(); - break; - } - if (idef->id_class == EVDF || idef->id_class == LVDF) { - report("%L: function %s declared as variable at %L", - id, id->id_name, idef); - break; + while (same_obj(stnr) && dot->id_class == FC) { + one_func_call(def); + } + + while (same_obj(stnr) && dot->id_class == VU) { + one_var_usage(def); + } +} + +one_func_call(def) + struct inpdef *def; +{ + if (!def) { + if (!options['u']) { + report("%L: function %s used but not defined", + dot, dot->id_name); } - if (!type_equal(id->id_type, idef->id_type)) { - report("%L: value of function %s declared differently at %L", - id, id->id_name, idef); + get_dot(); + return; + } + + def->id_called = 1; + + if (def->id_args) { + check_args(dot, def); + if (dot->id_valused == USED && !def->id_valreturned) { + report("%L: value of %s is used, but none is returned at %L", + dot, dot->id_name, def); } + } + + switch (dot->id_valused) { + case USED: + def->id_used = 1; break; - case EVDC: - if (!idef) { - if (!options['u']) { - report("%L: %s declared but never defined", - id, id->id_name); - } - discard_defs(); - break; - } - if (idef->id_class == EFDF || idef->id_class == LFDF) { - report("%L: variable %s declared as function at %L", - id, id->id_name, idef); - break; - } - if (!type_equal(id->id_type, idef->id_type)) { - report("%L: variable %s declared differently at %L", - id, id->id_name, idef); - } + case IGNORED: + def->id_ignored = 1; break; - case IFDC: - if (!idef) - break; /* used but not defined */ - if (idef->id_class == EVDF || idef->id_class == LVDF) { - report("%L: function %s declared as variable at %L", - id, id->id_name, idef); - break; - } - if (!type_equal(id->id_type, idef->id_type)) { - report("%L: function value of %s declared differently at %L", - id, id->id_name, idef); - } + case VOIDED: + def->id_voided = 1; break; - case FC: - if (!idef) { - if (!options['u']) { - report("%L: function %s used but not defined", - id, id->id_name); - } - discard_defs(); - break; + default: + panic("invalid dot->id_valused in check"); + break; + } + + get_dot(); +} + +one_var_usage(def) + struct inpdef *def; +{ + if (!def) { + if (!options['u']) { + report("%L: variable %s used but not defined", + dot, dot->id_name); } - idef->id_called = 1; - check_args(id, idef); - if (id->id_returns == USED && !idef->id_returns) { - report("%L: value of %s is used, but none is returned at %L", - id, id->id_name, idef); + get_dot(); + return; + } + + def->id_called = 1; + + get_dot(); +} + + +/******** S T A T I C ********/ + +statics() +{ + while (same_name() && dot->id_statnr != 0) { + one_static(dot->id_statnr); + } +} + +one_static(stnr) + int stnr; +{ + while (same_obj(stnr)) { + if (sta) { + free_inpdef(sta); + sta = 0; } - switch (id->id_returns) { - case USED: - idef->id_used = 1; - break; - case IGNORED: - idef->id_ignored = 1; - break; - case VOIDED: - idef->id_voided = 1; - break; - default: - panic("invalid id->id_returns in check"); + stat_def(stnr); + usage(stnr); + if (sta) + check_def(sta); + get_dot(); + } +} + +stat_def(stnr) + int stnr; +{ + if (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) { + if (lib) { + report("%L: %s also defined in library %L", + dot, dot->id_name, lib); } - break; - case VU: - if (!idef) { - if (!options['u']) { - report("%L: variable %s used but not defined", - id, id->id_name); - } - discard_defs(); - break; + if (ext) { + report("%L: %s also %s at %L", + dot, dot->id_name, defdec(ext), ext); } - idef->id_called = 1; - break; - case EFDF: - case SFDF: - case EVDF: - case SVDF: - case LFDF: - case LVDF: - panic("check() called for a definition"); - break; - default: - panic("invalid class (%c) in check", id->id_class); - break; + sta = dot; + dot = new_inpdef(); + get_dot(); + } + + while (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) { + report("%L: %s also defined at %L", + dot, dot->id_name, sta); + get_dot(); } } -discard_defs() +check_def(def) + struct inpdef *def; { -/* Read until a definition having another name */ + if (!def) + return; - struct inpdef *id; + if (!def->id_called) { + if (streq(def->id_name, "main")) { + /* silent */ + } + else if (ext && is_class(ext, CL_LIB)) { + /* silent */ + } + else { + if (!options['u']) { + report("%L: %s %s but never used", + def, def->id_name, defdec(def)); + } + } + } - while (dot_id && same_name()) { - id = id_read(); - free_inpdef(id); + if (is_class(def, CL_DEF|CL_FUNC)) { + if (def->id_valreturned && def->id_called && def->id_ignored) { + report("%L: %s returns value which is %s ignored", + def, def->id_name, + (def->id_used || def->id_voided) ? + "sometimes" : "always"); + } } } -check_args(id, idef) - struct inpdef *id, *idef; + +/******** T Y P E C H E C K I N G ********/ + +check_args(id, def) + struct inpdef *id, *def; { register char *act_tp = id->id_argtps; - register char *def_tp = idef->id_argtps; + register char *def_tp = def->id_argtps; register int i; register int nrargs; /* # of args to be type-checked */ register int varargs; /* determine nrargs */ - if (idef->id_nrargs < 0) { + if (def->id_nrargs < 0) { varargs = 1; - nrargs = -idef->id_nrargs - 1; + nrargs = -def->id_nrargs - 1; } else { varargs = 0; - nrargs = idef->id_nrargs; + nrargs = def->id_nrargs; } /* adjust nrargs, if necessary */ if (varargs) { if (nrargs > id->id_nrargs) { report("%L: number of args to %s differs from %L", - id, id->id_name, idef); + id, id->id_name, def); nrargs = id->id_nrargs; } } else { if (nrargs != id->id_nrargs) { report("%L: number of args to %s differs from %L", - id, id->id_name, idef); + id, id->id_name, def); nrargs = min(nrargs, id->id_nrargs); } } @@ -346,19 +403,27 @@ check_args(id, idef) if (!type_match(act, def)) { report("%L: arg %d of %s differs from that at %L", - id, i, id->id_name, idef); + id, i, id->id_name, def); } *act_tp++ = ':'; *def_tp++ = ':'; } } +int +type_equal(act, def) + char *act, *def; +{ + return streq(act, def); +} + int type_match(act, def) char *act, *def; { if (type_equal(act, def)) return 1; + if (act[0] == '+') { /* a non-negative constant */ /* might be signed or unsigned */ @@ -373,181 +438,22 @@ type_match(act, def) return 0; } -check_usage() -{ -/* Checks if the defined function or variable is used. - * There can be several static definitions. - */ - struct inpdef *sd = static_def; - - if (ext_def) - check_def(ext_def); - while (sd) { - check_def(sd); - sd = sd->next; - } -} +/******** D E B U G G I N G ********/ -check_def(id) - struct inpdef *id; -{ - if (!id->id_called) { - if (streq(id->id_name, "main")) { - /* silent */ - } - else if (ext_def && is_lib_class(ext_def->id_class)) { - /* silent */ - } - else { - if (!options['u']) { - report("%L: %s defined but never used", - id, id->id_name); - } - } - } - - if (is_fundef_class(id->id_class)) { - if (id->id_returns && id->id_called && id->id_ignored) { - report("%L: %s returns value which is %s ignored", - id, id->id_name, - (id->id_used || id->id_voided) ? - "sometimes" : "always"); - } - } -} - -static_in_list(id) - struct inpdef *id; -{ -/* Put id in the list of static definitions. - * static_def points to the first element. - */ - id->next = static_def; - static_def = id; -} - -struct inpdef * -definition(id) - struct inpdef *id; -{ -/* If there is a static definition that comes from the same file, a pointer - * to this definition will be returned. - * Otherwise a pointer to the ext_def is returned (which may be null). - */ - struct inpdef *sd = static_def; - - while (sd) { - if (id->id_statnr == sd->id_statnr) - return (sd); - sd = sd->next; - } - return (ext_def); -} - -free_defs() -{ -/* Dispose the external definition and the static definitions. */ - struct inpdef *sd; - - if (ext_def) { - free_inpdef(ext_def); - ext_def = 0; - } - while (static_def) { - sd = static_def; - static_def = static_def->next; - free_inpdef(sd); - } -} - -/* VARARGS */ -report(va_alist) - va_dcl -{ - va_list ap; - - va_start(ap); - { - char *fmt = va_arg(ap, char*); - register char *f = fmt; - register char fc; - - /* First see if the first arg is an inpdef with - a global file name; if so, skip this message. - */ - if (f[0] == '%' && f[1] == 'L') { - /* it is an inpdef */ - register struct inpdef *id = - va_arg(ap, struct inpdef *); - - f += 2; - /* is the file name global? */ - if (id->id_file[0] == '/') - return; - /* if no, we have used up the argument, - so print it here - */ - fprint(MSGOUT, "\"%s\", line %d", - id->id_file, id->id_line); - } - while ((fc = *f++)) { - if (fc == '%') { - switch (*f++) { - register struct inpdef *id; - register char *s; - register int i; - case 'L': /* a location item */ - id = va_arg(ap, struct inpdef *); - fprint(MSGOUT, "\"%s\", line %d", - id->id_file, id->id_line); - break; - case 's': /* a string item */ - s = va_arg(ap, char *); - fprint(MSGOUT, "%s", s); - break; - case 'd': /* an int item */ - i = va_arg(ap, int); - fprint(MSGOUT, "%d", i); - break; - default: - panic("bad format %s", fmt); - break; - } - } - else { - fprint(MSGOUT, "%c", fc); - } - } - fprint(MSGOUT, "\n"); - } - va_end(ap); -} - -/* VARARGS1 */ -panic(fmt, args) - char *fmt; -{ - fprint(ERROUT, "PANIC, lint, pass2: "); - doprnt(ERROUT, fmt, &args); - fprint(ERROUT, "\n"); - exit(1); -} - -/* for DEBUGGING */ print_id(id) struct inpdef *id; { - print("inpdef: %s, %s, %04d, \"%s\", %d, %d, %s, %d, %s\n", - id->id_class == EFDF ? "EFDF" : - id->id_class == SFDF ? "SFDF" : - id->id_class == EVDF ? "EVDF" : - id->id_class == SVDF ? "SVDF" : + print("inpdef: %s, %s, %04d, \"%s\", %d, %s", id->id_class == LFDF ? "LFDF" : id->id_class == LVDF ? "LVDF" : + id->id_class == EFDF ? "EFDF" : + id->id_class == EVDF ? "EVDF" : id->id_class == EFDC ? "EFDC" : id->id_class == EVDC ? "EVDC" : id->id_class == IFDC ? "IFDC" : + id->id_class == SFDF ? "SFDF" : + id->id_class == SVDF ? "SVDF" : id->id_class == FC ? "FC" : id->id_class == VU ? "VU" : id->id_class == ERRCL ? "ERRCL" : "", @@ -555,9 +461,21 @@ print_id(id) id->id_statnr, id->id_file, id->id_line, - id->id_nrargs, - ((id->id_nrargs == 0) ? "" : id->id_argtps), - id->id_returns, - id->id_type); + id->id_type + ); + 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 ? "VALRETURNED" : + "NOVALRETURNED") + ); + } + print("\n"); } diff --git a/lang/cem/lint/lpass2/read.c b/lang/cem/lint/lpass2/read.c index 1c979d861..e97a0ca8d 100644 --- a/lang/cem/lint/lpass2/read.c +++ b/lang/cem/lint/lpass2/read.c @@ -1,12 +1,13 @@ -#include "../lpass1/l_class.h" -#include "inpdef.h" +#include "../lpass1/l_class.h" +#include "class.h" +#include "inpdef.h" -#include +#include #define INP_NPUSHBACK 2 -#include -#include +#include +#include PRIVATE int LineNr = 1; @@ -25,37 +26,49 @@ int get_id(id) struct inpdef *id; { -/* A low-level function which just reads a definition */ + /* A low-level function which just reads a definition */ if (!ReadString(id->id_name, ':', NAMESIZE)) return 0; if (!ReadInt(&id->id_statnr)) return 0; SkipChar(':'); + loadchar(id->id_class); if (id->id_class == EOI) return 0; SkipChar(':'); - switch (id->id_class) { - case EFDF: - case SFDF: - case LFDF: - case FC: + + if (is_class(id, CL_FUNC|CL_DEF) || is_class(id, CL_FUNC|CL_USAGE)) { + /* read the argument information */ + id->id_args = 1; if (!ReadInt(&id->id_nrargs)) return 0; SkipChar(':'); if (!ReadArgs(id->id_nrargs, id->id_argtps)) return 0; - if (!ReadInt(&id->id_returns)) - return 0; + if (id->id_class == FC) { + /* function call */ + if (!ReadInt(&id->id_valused)) + return 0; + } + else { + /* function definition */ + if (!ReadInt(&id->id_valreturned)) + return 0; + } SkipChar(':'); - break; } + else { + id->id_args = 0; + } + if (!ReadString(id->id_type, ':', TYPESIZE)) return 0; if (!ReadInt(&id->id_line)) return 0; SkipChar(':'); + if (!ReadString(id->id_file, '\n', FNAMESIZE)) return 0; { extern char options[]; @@ -69,14 +82,16 @@ PRIVATE int ReadString(buf, delim, maxsize) char *buf; { -/* Reads a string until 'delim' is encountered. - * Delim is discarded. - * If 'maxsize-1' is exceeded, "string too long" is written by panic(). - * A '\0' is appended to the string. - * At EOI 0 is returned, else the length of the string (including - * the appended '\0') is returned. - */ - int ch; + /* Reads a string until 'delim' is encountered. + Delim is discarded. + If 'maxsize-1' is exceeded, "string too long" is written + by panic(). + A '\0' is appended to the string. + At EOI 0 is returned, else the length of the string (including + the appended '\0') is returned. + */ + + int ch = 0; int nread = 0; while (nread < maxsize - 1) { @@ -87,11 +102,11 @@ ReadString(buf, delim, maxsize) break; buf[nread++] = (char)ch; } + buf[nread++] = '\0'; if (ch != delim) { panic("line %d: string too long: %s", LineNr, buf); /*NOTREACHED*/ } - buf[nread++] = '\0'; return (nread); } diff --git a/lang/cem/lint/lpass2/report.c b/lang/cem/lint/lpass2/report.c new file mode 100644 index 000000000..14f54ba29 --- /dev/null +++ b/lang/cem/lint/lpass2/report.c @@ -0,0 +1,81 @@ +#include + +#include +#include "inpdef.h" + +#define MSGOUT STDERR /* filedes on which to write the messages */ +#define ERROUT STDERR /* filedes on which to write the panics */ + +/* VARARGS */ +report(va_alist) + va_dcl +{ + va_list ap; + + va_start(ap); + { + char *fmt = va_arg(ap, char*); + register char *f = fmt; + register char fc; + + /* First see if the first arg is an inpdef with + a global file name; if so, skip this message. + */ + if (f[0] == '%' && f[1] == 'L') { + /* it is an inpdef */ + register struct inpdef *id = + va_arg(ap, struct inpdef *); + + f += 2; + /* is the file name global? */ + if (id->id_file[0] == '/') + return; + /* if no, we have used up the argument, + so print it here + */ + fprint(MSGOUT, "\"%s\", line %d", + id->id_file, id->id_line); + } + while ((fc = *f++)) { + if (fc == '%') { + switch (*f++) { + register struct inpdef *id; + register char *s; + register int i; + case 'L': /* a location item */ + id = va_arg(ap, struct inpdef *); + fprint(MSGOUT, "\"%s\", line %d", + id->id_file, id->id_line); + break; + case 's': /* a string item */ + s = va_arg(ap, char *); + fprint(MSGOUT, "%s", s); + break; + case 'd': /* an int item */ + i = va_arg(ap, int); + fprint(MSGOUT, "%d", i); + break; + default: + panic("bad format %s", fmt); + break; + } + } + else { + fprint(MSGOUT, "%c", fc); + } + } + fprint(MSGOUT, "\n"); + } + va_end(ap); +} + +/* VARARGS1 */ +panic(fmt, args) + char *fmt; +{ + fprint(ERROUT, "PANIC, lint, pass2: "); + doprnt(ERROUT, fmt, &args); + fprint(ERROUT, "\n"); + exit(1); +} +