formats introduced
authordick <none@none>
Wed, 12 Oct 1988 15:49:11 +0000 (15:49 +0000)
committerdick <none@none>
Wed, 12 Oct 1988 15:49:11 +0000 (15:49 +0000)
lang/cem/lint/lpass2/Makefile
lang/cem/lint/lpass2/checkargs.c [new file with mode: 0644]
lang/cem/lint/lpass2/class.h
lang/cem/lint/lpass2/l_print3ack.c [new file with mode: 0644]
lang/cem/lint/lpass2/lpass2.c
lang/cem/lint/lpass2/read.c
lang/cem/lint/lpass2/report.c

index 4fbb5c8..8e8989d 100644 (file)
@@ -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 (file)
index 0000000..e50f3ea
--- /dev/null
@@ -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';
+}
+
index 38c542a..29f012c 100644 (file)
@@ -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 (file)
index 0000000..d4684d2
--- /dev/null
@@ -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       <system.h>
+
+/* 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
+
index c4d6597..b5cfdf1 100644 (file)
 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)
index cc47ca1..6af6bcf 100644 (file)
@@ -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
-                       <type1>:<type2>: ... :<typeN>:
+                       <type1>:<type2>: ... :<typeN>:\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*/
+       }
+}
+
index 333fa78..be47943 100644 (file)
@@ -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);