From: dick Date: Wed, 12 Oct 1988 15:49:11 +0000 (+0000) Subject: formats introduced X-Git-Tag: release-5-5~2798 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=ac21f8d98ab03018dd35c0947c539eed19694cf8;p=ack.git formats introduced --- diff --git a/lang/cem/lint/lpass2/Makefile b/lang/cem/lint/lpass2/Makefile index 4fbb5c8e4..8e8989d76 100644 --- a/lang/cem/lint/lpass2/Makefile +++ b/lang/cem/lint/lpass2/Makefile @@ -7,7 +7,7 @@ # Machine and environ dependent definitions EMHOME = /usr/em -LPASS1 = ../lpass1 +LPASS1 = $(EMHOME)/lang/cem/cemcom # Libraries and EM interface definitions SYSLIB = $(EMHOME)/modules/lib/libsystem.a @@ -24,12 +24,13 @@ CFLAGS = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg -I/usr/include .str.h: $(LPASS1)/make.allocd <$*.str >$*.h -SRC = lpass2.c read.c report.c class.c -OBJ = lpass2.o read.o report.o class.o +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 -# lpass2 -xh <.i + lpass2 -xh <.i +# make lint + lpass2: $(OBJ) Makefile next.o $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) next.o $(LLIBS) -o lpass2 diff --git a/lang/cem/lint/lpass2/checkargs.c b/lang/cem/lint/lpass2/checkargs.c new file mode 100644 index 000000000..e50f3ea05 --- /dev/null +++ b/lang/cem/lint/lpass2/checkargs.c @@ -0,0 +1,248 @@ +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Header$ */ + +/******** A R G U M E N T T Y P E C H E C K I N G ********/ + +#include "private.h" +#include "inpdef.h" + +extern char *strcpy(); + +#define streq(s1,s2) (strcmp(s1, s2) == 0) + +/* a format is developed into a normal parameter definition */ +PRIVATE int is_formatargs; /* present or not */ +PRIVATE char formatargs[1000]; /* the definitions */ + +PRIVATE chk_argtps(); +PRIVATE char *next_atype(); +PRIVATE int type_match(); + +int +type_equal(act, form) + char *act, *form; +{ + return streq(act, form) + || streq(act, "erroneous") + || streq(form, "erroneous"); +} + +chk_args(id, def) + struct inpdef *id, *def; +{ + char *act_tp = id->id_argtps; + int nrargs = 0; /* number of args */ + + /* clear format */ + is_formatargs = 0; + + /* check normal arguments */ + chk_argtps(id, def, &nrargs, act_tp, def->id_argtps); + + if (is_formatargs) { + /* there was a format */ + register int i; + + /* skip over the actuals already covered */ + for (i = 0; i < nrargs; i++) { + act_tp = next_atype(act_tp); + } + + /* and check the format arguments */ + chk_argtps(id, (struct inpdef *)0, &nrargs, + act_tp, &formatargs[0]); + } +} + +PRIVATE chk_argtps(id, def, nrargs, act_tp, form_tp) + struct inpdef *id; /* the actual call */ + struct inpdef *def; /* 0 for format-derived definition */ + int *nrargs; /* in-out parameter, counting */ + char *act_tp; /* actual types */ + char *form_tp; /* formal type definitions */ +{ + while (*act_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[-1] = '\0'; + + /* isolate formal argument type */ + form_tp = next_atype(form_tp); + form_tp[-1] = '\0'; + + (*nrargs)++; + if (!type_match(id, act_start, form_start)) { + report("%L: arg %d of %s differs from that in %L", + id, *nrargs, id->id_name, def); + } + act_tp[-1] = ':'; + form_tp[-1] = ':'; + } + + if (*form_tp) { + /* formal type definitions not exhausted */ + report("%L: %s has fewer arguments than in %L", + id, id->id_name, def); + } + if (*act_tp) { + /* actual types not exhausted */ + if (def && def->id_nrargs < 0) { + /* the function had VARARGS */ + } + else { + report("%L: %s has more arguments than in %L", + id, id->id_name, def); + } + } +} + +PRIVATE char * +next_atype(tp) + char *tp; +{ + while (*tp && *tp != ':') { + tp++; + } + if (*tp == ':') { + tp++; + } + return tp; +} + +int +PRIVATE type_match(id, act, form) + struct inpdef *id; + char *act, *form; +{ + if (form[0] == '"' && act[0] == '"') { + conv_format(id, act, form); + return 1; + } + + if ( (form[0] == '"' && streq(act, "char*")) + || (act[0] == '"' && streq(form, "char*")) + ) { + return 1; + } + + if (type_equal(act, form)) + return 1; + + if (act[0] == '+') { + /* a non-negative constant */ + /* might be signed or unsigned */ + if (type_equal(&act[1], form)) + return 1; + if ( strncmp(form, "unsigned ", strlen("unsigned ")) == 0 + && type_equal(&act[1], &form[strlen("unsigned ")]) + ) { + return 1; + } + } + return 0; +} + +PRIVATE conv_format(id, act, form) + struct inpdef *id; + char *act, *form; +{ + /* convert the actual format into a def-list, using the + formal format (form) as a map to convert from %X to type + */ + register char *fmt = &formatargs[0]; + + is_formatargs = 1; + while (*act) { + register char *map; + + /* find next conversion specification */ + while (*act && *act != '%') { + act++; + } + if (*act++ != '%') + break; + if (*act == '%') { + /* %% */ + act++; + continue; + } + + /* process options */ + if (*act && *act == '-') { + act++; + } + while (*act && ('0' <= *act && *act <= '9')) { + act++; + } + if (*act == '*') { + act++; + strcpy(fmt, "int:"); + fmt += 4; + } + if (*act && *act == '.') { + act++; + } + while (*act && ('0' <= *act && *act <= '9')) { + act++; + } + if (*act == '*') { + act++; + strcpy(fmt, "int:"); + fmt += 4; + } + + map = form; + while (*map) { + register char *cs = act; + + /* find next conversion mapping */ + while (*map && *map != '%') { + map++; + } + if (*map++ != '%') { + /* we ran off the map */ + report("%L: unknown conversion specification in format", + id); + break; + } + + while (*map && *map != '=') { + register int match = 0; + + if (*map == '[') { + while (*map && *map != ']') { + if (*map == *cs) { + match = 1; + } + map++; + } + } + else { + match = (*map == *cs); + } + + if (match) { + map++, cs++; + } + else break; + } + if (*map++ == '=') { + /* found the type belonging to %*cs */ + while (*map && *map != '%' && *map != '"') { + *fmt++ = *map++; + } + *fmt++ = ':'; + act = cs; + break; + } + } + } + *fmt++ = '\0'; +} + diff --git a/lang/cem/lint/lpass2/class.h b/lang/cem/lint/lpass2/class.h index 38c542a63..29f012c1f 100644 --- a/lang/cem/lint/lpass2/class.h +++ b/lang/cem/lint/lpass2/class.h @@ -9,7 +9,7 @@ class[] contains a bit pattern for each letter, with those bits set that correspond to the lint class meaning of the letter. - This facility is used through the macro is_class(inpdef_var, CL_???) + This facility is used through the macro is_class(inpdef_var, CL_XXX) */ #define CL_DEF (1<<0) diff --git a/lang/cem/lint/lpass2/l_print3ack.c b/lang/cem/lint/lpass2/l_print3ack.c new file mode 100644 index 000000000..d4684d2bb --- /dev/null +++ b/lang/cem/lint/lpass2/l_print3ack.c @@ -0,0 +1,30 @@ +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Header$ */ + +/* A C K P R I N T M O D U L E D E F I N T I O N S */ + +#ifdef lint + +#include + +/* LINTLIBRARY */ + +/* FORMAT0 $ + %[bdox] = int %l[bdox] = long + %c = int %s = char * + %u = unsigned int +$ */ +print(format) char *format; { ; } + +/* FORMAT1 */ +fprint(filep, format) File *filep; char *format; { ; } +/* FORMAT1 */ +sprint(s, format) char *s; char *format; { ; } +/* FORMAT1 */ +doprnt(filep, format) File *filep; char *format; { ; } + +#endif lint + diff --git a/lang/cem/lint/lpass2/lpass2.c b/lang/cem/lint/lpass2/lpass2.c index c4d6597b1..b5cfdf179 100644 --- a/lang/cem/lint/lpass2/lpass2.c +++ b/lang/cem/lint/lpass2/lpass2.c @@ -15,13 +15,11 @@ extern char *strcpy(); #define streq(s1,s2) (strcmp(s1, s2) == 0) -#define min(a,b) ((a) <= (b) ? (a) : (b)) PRIVATE char cur_name[NAMESIZE]; PRIVATE struct inpdef *dot, *lib, *ext, *sta; -PRIVATE check_args(); -PRIVATE check_def(); +PRIVATE chk_def(); PRIVATE ext_decls(); PRIVATE ext_def(); PRIVATE get_dot(); @@ -32,8 +30,6 @@ PRIVATE one_func_call(); PRIVATE one_var_usage(); PRIVATE stat_def(); PRIVATE statics(); -PRIVATE int type_equal(); -PRIVATE int type_match(); PRIVATE usage(); #define same_name() (dot && streq(cur_name, dot->id_name)) @@ -67,7 +63,7 @@ main(argc, argv) ext_decls(); usage(0); if (ext) - check_def(ext); + chk_def(ext); statics(); if (same_name()) { /* there are more lines for this name that have @@ -199,6 +195,7 @@ PRIVATE one_ext_decl(kind, other_kind, other_class) report("%L: %s %s %s as %s at %L", dot, kind, dot->id_name, defdec(def), other_kind, def); /* no further testing possible */ + get_dot(); return; } @@ -264,7 +261,7 @@ PRIVATE one_func_call(def) def->id_called = 1; if (def->id_args) { - check_args(dot, def); + chk_args(dot, def); if ( dot->id_valused == USED && def->id_valreturned == NOVALRETURNED ) { @@ -284,7 +281,7 @@ PRIVATE one_func_call(def) def->id_voided = 1; break; default: - panic("invalid dot->id_valused in check"); + panic("invalid dot->id_valused in one_func_call()"); break; } @@ -326,7 +323,7 @@ PRIVATE statics() stat_def(stnr); usage(stnr); if (sta) - check_def(sta); + chk_def(sta); if (same_obj(stnr)) panic("sequence error in input"); @@ -360,7 +357,7 @@ PRIVATE stat_def(stnr) } } -PRIVATE check_def(def) +PRIVATE chk_def(def) struct inpdef *def; { if (!def) @@ -396,104 +393,6 @@ PRIVATE check_def(def) } -/******** T Y P E C H E C K I N G ********/ - -PRIVATE check_args(id, def) - struct inpdef *id, *def; -{ - register char *act_tp = id->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 (def->id_nrargs < 0) { - varargs = 1; - nrargs = -def->id_nrargs - 1; - } - else { - varargs = 0; - 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, 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, def); - nrargs = min(nrargs, id->id_nrargs); - } - } - - for (i = 1; i <= nrargs; i++) { - register char *act_par = act_tp; - register char *def_par = def_tp; - - /* isolate actual argument type */ - while (*act_tp) { - if (*act_tp == ':') { - *act_tp = '\0'; - break; - } - act_tp++; - } - /* isolate formal argument type */ - while (*def_tp) { - if (*def_tp == ':') { - *def_tp = '\0'; - break; - } - def_tp++; - } - - if (!type_match(act_par, def_par)) { - report("%L: arg %d of %s differs from that at %L", - id, i, id->id_name, def); - } - *act_tp++ = ':'; - *def_tp++ = ':'; - } -} - -int -PRIVATE type_equal(act, def) - char *act, *def; -{ - return streq(act, def) - || streq(act, "erroneous") - || streq(def, "erroneous"); -} - -int -PRIVATE 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 */ - if (type_equal(&act[1], def)) - return 1; - if ( strncmp(def, "unsigned ", strlen("unsigned ")) == 0 - && type_equal(&act[1], &def[strlen("unsigned ")]) - ) { - return 1; - } - } - return 0; -} - - /******** D E B U G G I N G ********/ print_id(name, id) diff --git a/lang/cem/lint/lpass2/read.c b/lang/cem/lint/lpass2/read.c index cc47ca1ca..6af6bcf8d 100644 --- a/lang/cem/lint/lpass2/read.c +++ b/lang/cem/lint/lpass2/read.c @@ -17,7 +17,7 @@ #include "private.h" -PRIVATE int LineNr = 1; +int LineNr = 1; /* Two dangerous macro's. They replace a single statement by * two statements @@ -25,10 +25,13 @@ PRIVATE int LineNr = 1; #define loadchar(ch) LoadChar(ch); if (ch=='\n') LineNr++ #define pushback(ch) PushBack(); if (ch=='\n') LineNr-- +/* all the ReadX() functions return 0 upon EOI */ PRIVATE int ReadString(); PRIVATE int ReadInt(); -PRIVATE SkipChar(); PRIVATE int ReadArgs(); +PRIVATE int ReadArg(); + +PRIVATE SkipChar(); int get_id(id) @@ -79,20 +82,18 @@ get_id(id) if (!ReadString(id->id_file, '\n', FNAMESIZE)) return 0; - return (1); + return 1; } 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(). + /* 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. 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; @@ -104,14 +105,18 @@ ReadString(buf, delim, maxsize) return 0; if (ch == delim) break; + if (ch == '\n') { + panic("newline in string"); + /*NOTREACHED*/ + } buf[nread++] = (char)ch; } buf[nread++] = '\0'; if (ch != delim) { - panic("line %d: string too long: %s", LineNr, buf); + panic("string too long"); /*NOTREACHED*/ } - return (nread); + return 1; } PRIVATE int @@ -123,7 +128,6 @@ ReadInt(ip) * Non-digits except minus-sign in front of the number are discarded. * Doesn't check on overflow. * Just a minus-sign is interpreted as 0. (To prevent a look-ahead.) - * At EOI 0 is returned, else 1. */ int ch; int negative = 0; @@ -148,24 +152,12 @@ ReadInt(ip) return 1; } -PRIVATE SkipChar(ch) -{ - int c; - - loadchar(c); - if (c != ch) { - panic("line %d: bad format, '%c' expected; '%c' read", - LineNr, ch, c); - /*NOTREACHED*/ - } -} - PRIVATE int ReadArgs(nrargs, buf) char *buf; { /* Reads a string into buf with format - :: ... :: + :: ... ::\0 Note: format must include the final colon. */ int i; @@ -179,7 +171,7 @@ ReadArgs(nrargs, buf) for (i = 0; i < nrargs; i++) { int n; - if (!ReadString(buf, ':', ARGTPSSIZE-charcount-1)) + if (!ReadArg(buf, ARGTPSSIZE-charcount-1)) return 0; n = strlen(buf) + 1; charcount += n; @@ -190,3 +182,40 @@ ReadArgs(nrargs, buf) return 1; } +PRIVATE int +ReadArg(buf, size) + char *buf; + int size; +{ + int ch; + + loadchar(ch); + switch (ch) { + case '"': /* formal format or actual string */ + *buf++ = ch; + if (!ReadString(buf, ch, size-1)) + return 0; + buf += strlen(buf); + *buf++ = ch; + *buf++ = '\0'; + SkipChar(':'); + return 1; + default: /* normal type */ + pushback(ch); + return ReadString(buf, ':', size); + case EOI: + return 0; + } +} + +PRIVATE SkipChar(ch) +{ + int c; + + loadchar(c); + if (c != ch) { + panic("bad format, '%c' expected; '%c' read", ch, c); + /*NOTREACHED*/ + } +} + diff --git a/lang/cem/lint/lpass2/report.c b/lang/cem/lint/lpass2/report.c index 333fa784d..be479430f 100644 --- a/lang/cem/lint/lpass2/report.c +++ b/lang/cem/lint/lpass2/report.c @@ -14,6 +14,8 @@ #define MSGOUT STDERR /* filedes on which to write the messages */ #define ERROUT STDERR /* filedes on which to write the panics */ +extern int LineNr; + PRIVATE rep_loc(); /* VARARGS */ @@ -90,6 +92,11 @@ PRIVATE rep_loc(id) struct inpdef *id; { + /* a definition can come from a number of places */ + if (!id) { + fprint(MSGOUT, "format"); + } + else if (is_class(id, CL_LIB)) { fprint(MSGOUT, "library file %s", id->id_file); } @@ -103,7 +110,7 @@ rep_loc(id) panic(fmt, args) char *fmt; { - fprint(ERROUT, "PANIC, lint, pass2: "); + fprint(ERROUT, "PANIC, lint, pass2: line %d: ", LineNr); doprnt(ERROUT, fmt, &args); fprint(ERROUT, "\n"); exit(1);