introduction of lint source code, governed by ifdef LINT
authordick <none@none>
Tue, 20 Sep 1988 16:44:27 +0000 (16:44 +0000)
committerdick <none@none>
Tue, 20 Sep 1988 16:44:27 +0000 (16:44 +0000)
35 files changed:
lang/cem/cemcom/LLlex.c
lang/cem/cemcom/LintPars [new file with mode: 0644]
lang/cem/cemcom/Makefile
lang/cem/cemcom/Parameters
lang/cem/cemcom/Resolve
lang/cem/cemcom/blocks.c
lang/cem/cemcom/ch7.c
lang/cem/cemcom/code.c
lang/cem/cemcom/conversion.c
lang/cem/cemcom/declar.g
lang/cem/cemcom/def.str
lang/cem/cemcom/error.c
lang/cem/cemcom/eval.c
lang/cem/cemcom/expr.c
lang/cem/cemcom/expression.g
lang/cem/cemcom/field.c
lang/cem/cemcom/idf.c
lang/cem/cemcom/ival.g
lang/cem/cemcom/l_class.h [new file with mode: 0644]
lang/cem/cemcom/l_comment.c [new file with mode: 0644]
lang/cem/cemcom/l_dummy.c [new file with mode: 0644]
lang/cem/cemcom/l_ev_ord.c [new file with mode: 0644]
lang/cem/cemcom/l_lint.c [new file with mode: 0644]
lang/cem/cemcom/l_lint.h [new file with mode: 0644]
lang/cem/cemcom/l_misc.c [new file with mode: 0644]
lang/cem/cemcom/l_outdef.c [new file with mode: 0644]
lang/cem/cemcom/l_outdef.str [new file with mode: 0644]
lang/cem/cemcom/l_state.str [new file with mode: 0644]
lang/cem/cemcom/l_states.c [new file with mode: 0644]
lang/cem/cemcom/main.c
lang/cem/cemcom/options.c
lang/cem/cemcom/program.g
lang/cem/cemcom/stack.c
lang/cem/cemcom/statement.g
lang/cem/cemcom/util.c

index 9b6bbf3..21a7487 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /*                 L E X I C A L   A N A L Y Z E R                     */
 
+#include       "lint.h"
 #include       <alloc.h>
 #include       "nofloat.h"
 #include       "idfsize.h"
@@ -72,6 +73,9 @@ LLlex()
                ASIDE = 0;
        }
        else {          /* read ahead and return the old one    */
+#ifdef LINT
+               move_NOT2s();
+#endif LINT
                dot = ahead;
                /*      the following test is performed due to the dual
                        task of LLlex(): it is also called for parsing the
@@ -472,6 +476,10 @@ skipcomment()
 
        NoUnstack++;
        LoadChar(c);
+#ifdef LINT
+       lint_comment(-2);
+       lint_comment(c);
+#endif LINT
        do {
                while (c != '*') {
                        if (class(c) == STNL)
@@ -482,8 +490,14 @@ skipcomment()
                                return;
                        }
                        LoadChar(c);
+#ifdef LINT
+                       lint_comment(c);
+#endif LINT
                } /* last Character seen was '*' */
                LoadChar(c);
+#ifdef LINT
+               lint_comment(c);
+#endif LINT
        } while (c != '/');
        NoUnstack--;
 }
diff --git a/lang/cem/cemcom/LintPars b/lang/cem/cemcom/LintPars
new file mode 100644 (file)
index 0000000..4bfd2a9
--- /dev/null
@@ -0,0 +1,139 @@
+!File: lint.h
+#define        LINT            1       /* if defined, 'lint' is produced       */
+
+
+!File: pathlength.h
+#define PATHLENGTH     1024    /* max. length of path to file          */
+
+
+!File: errout.h
+#define        ERROUT          STDERR  /* file pointer for writing messages    */
+#define        MAXERR_LINE     5       /* maximum number of error messages given
+                                       on the same input line.         */
+
+
+!File: idfsize.h
+#define        IDFSIZE 64      /* maximum significant length of an identifier  */
+
+
+!File: numsize.h
+#define        NUMSIZE 256     /* maximum length of a numeric constant         */
+
+
+!File: nparams.h
+#define        NPARAMS 32      /* maximum number of parameters of macros       */
+
+
+!File: ifdepth.h
+#define        IFDEPTH 256     /* maximum number of nested if-constructions    */
+
+
+!File: density.h
+#define        DENSITY 2       /* see switch.[ch] for an explanation           */
+
+
+!File: lapbuf.h
+#define        LAPBUF  4096    /* size of macro actual parameter buffer        */
+
+
+!File: strsize.h
+#define ISTRSIZE       32      /* minimum number of bytes allocated for
+                                       storing a string                */
+#define RSTRSIZE       8       /* step size in enlarging the memory for
+                                       the storage of a string         */
+
+
+!File: target_sizes.h
+#define MAXSIZE                8       /* the maximum of the SZ_* constants    */
+
+/* target machine sizes        */
+#define        SZ_CHAR         (arith)1
+#define        SZ_SHORT        (arith)2
+#define SZ_WORD                (arith)4
+#define        SZ_INT          (arith)4
+#define        SZ_LONG         (arith)4
+#ifndef NOFLOAT
+#define        SZ_FLOAT        (arith)4
+#define        SZ_DOUBLE       (arith)8
+#endif NOFLOAT
+#define        SZ_POINTER      (arith)4
+
+/* target machine alignment requirements       */
+#define        AL_CHAR         1
+#define        AL_SHORT        SZ_SHORT
+#define AL_WORD                SZ_WORD
+#define        AL_INT          SZ_WORD
+#define        AL_LONG         SZ_WORD
+#ifndef NOFLOAT
+#define        AL_FLOAT        SZ_WORD
+#define        AL_DOUBLE       SZ_WORD
+#endif NOFLOAT
+#define        AL_POINTER      SZ_WORD
+#define AL_STRUCT      1
+#define AL_UNION       1
+
+
+!File: botch_free.h
+#undef BOTCH_FREE      1       /* when defined, botch freed memory, as a check */
+
+
+!File: dataflow.h
+#undef DATAFLOW        1       /* produce some compile-time xref       */
+
+
+!File: debug.h
+#undef DEBUG           1       /* perform various self-tests           */
+
+
+!File: use_tmp.h
+#undef USE_TMP         1       /* collect exa, exp, ina and inp commands
+                                       and let them precede the rest of
+                                       the generated compact code      */
+
+
+!File: parbufsize.h
+#define PARBUFSIZE     1024
+
+
+!File: textsize.h
+#define ITEXTSIZE      8       /* 1st piece of memory for repl. text   */
+#define RTEXTSIZE      8       /* stepsize for enlarging repl.text     */
+
+
+!File: inputtype.h
+#define INP_READ_IN_ONE        1       /* read input file in one       */
+
+
+!File: nopp.h
+#undef NOPP            1       /* if NOT defined, use built-int preprocessor */
+
+
+!File: nobitfield.h
+#undef NOBITFIELD      1       /* if NOT defined, implement bitfields  */
+
+
+!File: spec_arith.h
+/* describes internal compiler arithmetics */
+#undef SPECIAL_ARITHMETICS     /* something different from native long */
+
+
+!File: static.h
+#define GSTATIC                        /* for large global "static" arrays */
+
+
+!File: nofloat.h
+#undef NOFLOAT         1       /* if NOT defined, floats are implemented */
+
+
+!File: noRoption.h
+#undef NOROPTION       1       /* if NOT defined, R option is implemented */
+
+
+!File: nocross.h
+#undef NOCROSS         1       /* if NOT defined, cross compiler */
+
+
+!File: regcount.h
+#undef REGCOUNT                1       /* count occurrences for register messages */
+
+
index 20f61dc..65050ad 100644 (file)
@@ -28,6 +28,8 @@ OLIBS = $(INPLIB) $(EMMESOLIB) $(EMOLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) \
        $(ALLOCLIB) $(MALLOC) $(SYSLIB)
 CELIBS = $(INPLIB) $(EMMESCELIB) $(EMCELIB) $(PRTLIB) $(STRLIB) \
        $(ALLOCLIB) $(MALLOC) $(SYSLIB)
+LLIBS = $(INPLIB) $(EMMESLIB) $(PRTLIB) $(STRLIB) \
+       $(ALLOCLIB) $(MALLOC) $(SYSLIB)
 LIB_INCLUDES = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg
 EM_INCLUDES = -I$(EMHOME)/h
 SYSLLIB = $(EMHOME)/modules/lib/llib-lsystem.ln
@@ -66,7 +68,8 @@ CSRC =        main.c idf.c declarator.c decspecs.c struct.c \
        input.c domacro.c replace.c init.c options.c \
        scan.c skip.c stack.c type.c ch7mon.c label.c eval.c \
        switch.c conversion.c util.c \
-       blocks.c dataflow.c Version.c
+       blocks.c dataflow.c Version.c \
+       l_lint.c l_states.c l_misc.c l_ev_ord.c l_outdef.c l_comment.c l_dummy.c
 COBJ = main.o idf.o declarator.o decspecs.o struct.o \
        expr.o ch7.o ch7bin.o cstoper.o arith.o \
        asm.o code.o dumpidf.o error.o field.o\
@@ -74,7 +77,8 @@ COBJ =        main.o idf.o declarator.o decspecs.o struct.o \
        input.o domacro.o replace.o init.o options.o \
        scan.o skip.o stack.o type.o ch7mon.o label.o eval.o \
        switch.o conversion.o util.o \
-       blocks.o dataflow.o Version.o
+       blocks.o dataflow.o Version.o \
+       l_lint.o l_states.o l_misc.o l_ev_ord.o l_outdef.o l_comment.o l_dummy.o
 
 # Objects of other generated C files
 GCSRC =        char.c symbol2str.c next.c
@@ -82,16 +86,18 @@ GOBJ =      char.o symbol2str.o next.o
 
 STRSRC = code.str declar.str decspecs.str def.str expr.str field.str \
        estack.str util.str \
-       idf.str macro.str stack.str stmt.str struct.str switch.str type.str
+       idf.str macro.str stack.str stmt.str struct.str switch.str type.str \
+       l_brace.str l_state.str l_outdef.str
 # generated source files
 GHSTRSRC = code.h declar.h decspecs.h def.h expr.h field.h \
        estack.h util.h \
-       idf.h macro.h stack.h stmt.h struct.h switch.h type.h
+       idf.h macro.h stack.h stmt.h struct.h switch.h type.h \
+       l_brace.h l_state.h l_outdef.h
 GSRC = $(GCSRC)  $(GHSTRSRC)
 
 # .h files generated by `make hfiles LLfiles'; PLEASE KEEP THIS UP-TO-DATE!
 GHSRC =        botch_free.h dataflow.h debug.h density.h errout.h \
-       idfsize.h ifdepth.h inputtype.h lapbuf.h \
+       idfsize.h ifdepth.h inputtype.h lapbuf.h lint.h \
        nobitfield.h nofloat.h nopp.h noRoption.h nocross.h \
        nparams.h numsize.h parbufsize.h pathlength.h Lpars.h \
        strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h \
@@ -99,7 +105,7 @@ GHSRC =      botch_free.h dataflow.h debug.h density.h errout.h \
 
 HSRC = LLlex.h align.h arith.h assert.h atw.h class.h \
         input.h interface.h label.h level.h mes.h sizes.h specials.h \
-        file_info.h tokenname.h
+        file_info.h tokenname.h l_lint.h
 
 HFILES = $(HSRC) $(GHSRC) $(GHSTRSRC)
 
@@ -111,6 +117,12 @@ GENERATED = tab tokenfile.g Lpars.h LLfiles LL.output lint.out \
 OBJ =  $(COBJ) $(LOBJ) $(GOBJ)
 SRC =  $(CSRC) $(LCSRC) $(GCSRC)
 
+LINT = /usr/bin/lint
+LINTFLAGS =
+
+MYLINT = ../lint
+MYLINTFLAGS = #-xh
+
 #EXCLEXCLEXCLEXCL
 
 .SUFFIXES: .str .h
@@ -135,6 +147,11 @@ CEmain:    Cfiles
        sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) "COPTIONS="-DCODE_EXPANDER $(CURRDIR)/cemain ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve cemain ; fi'
        @rm -f nmclash.o a.out *.o
 
+Lnt:   Cfiles
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) $(CURRDIR)/lnt ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve lnt ; fi'
+       make "EMHOME="$(EMHOME) $(CURRDIR)/lnt
+       @rm -f nmclash.o a.out
+
 install:       Main
        rm -f $(EMHOME)/lib/em_cemcom $(EMHOME)/man/em_cemcom.6
        cp $(CURRDIR)/main $(EMHOME)/lib/em_cemcom
@@ -162,6 +179,10 @@ lint:      Cfiles
        sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) Xlint ; else sh Resolve Xlint ; fi'
        @rm -f nmclash.o a.out
 
+mylint:        Cfiles
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) Xmylint ; else sh Resolve Xmylint ; fi'
+       @rm -f nmclash.o a.out
+
 longnames:     $(SRC) $(HFILES)
        sh -c 'if test -f longnames ; then : ; else touch longnames ; fi ; $(PRID) -l7 longnames $? > Xlongnames ; mv Xlongnames longnames'
 
@@ -208,6 +229,9 @@ switch.h:   make.allocd
 type.h:                make.allocd
 estack.h:      make.allocd
 util.h:                make.allocd
+l_brace.h:     make.allocd
+l_state.h:     make.allocd
+l_outdef.h:    make.allocd
 
 depend:        Cfiles
        sed '/^#AUTOAUTO/,$$d' Makefile >Makefile.new
@@ -234,8 +258,15 @@ $(CURRDIR)/cemain: $(OBJ) $(CURRDIR)/Makefile
        $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(CELIBS) -o $(CURRDIR)/cemain 
        size $(CURRDIR)/cemain
 
-Xlint:
-       lint $(CDEFS) $(LINTFLAGS) $(SRC)
+$(CURRDIR)/lnt:                $(OBJ) $(CURRDIR)/Makefile
+       $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(LLIBS) -o $(CURRDIR)/lnt 
+       size $(CURRDIR)/lnt
+
+Xlint: $(SRC)
+       $(LINT) $(CDEFS) $(LINTFLAGS) $(SRC)
+
+Xmylint:       $(SRC)
+       $(MYLINT) $(CDEFS) $(MYLINTFLAGS) $(SRC)
 
 #AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
 main.o: LLlex.h
@@ -249,6 +280,7 @@ main.o: idf.h
 main.o: input.h
 main.o: inputtype.h
 main.o: level.h
+main.o: lint.h
 main.o: noRoption.h
 main.o: nobitfield.h
 main.o: nocross.h
@@ -276,6 +308,7 @@ idf.o: idf.h
 idf.o: idfsize.h
 idf.o: label.h
 idf.o: level.h
+idf.o: lint.h
 idf.o: noRoption.h
 idf.o: nobitfield.h
 idf.o: nocross.h
@@ -305,9 +338,12 @@ declarator.o: target_sizes.h
 declarator.o: type.h
 decspecs.o: Lpars.h
 decspecs.o: arith.h
+decspecs.o: assert.h
+decspecs.o: debug.h
 decspecs.o: decspecs.h
 decspecs.o: def.h
 decspecs.o: level.h
+decspecs.o: lint.h
 decspecs.o: noRoption.h
 decspecs.o: nobitfield.h
 decspecs.o: nofloat.h
@@ -325,6 +361,7 @@ struct.o: field.h
 struct.o: file_info.h
 struct.o: idf.h
 struct.o: level.h
+struct.o: lint.h
 struct.o: noRoption.h
 struct.o: nobitfield.h
 struct.o: nocross.h
@@ -348,6 +385,7 @@ expr.o: file_info.h
 expr.o: idf.h
 expr.o: label.h
 expr.o: level.h
+expr.o: lint.h
 expr.o: noRoption.h
 expr.o: nobitfield.h
 expr.o: nocross.h
@@ -365,6 +403,7 @@ ch7.o: def.h
 ch7.o: expr.h
 ch7.o: idf.h
 ch7.o: label.h
+ch7.o: lint.h
 ch7.o: nobitfield.h
 ch7.o: nofloat.h
 ch7.o: nopp.h
@@ -401,7 +440,6 @@ cstoper.o: target_sizes.h
 cstoper.o: type.h
 arith.o: Lpars.h
 arith.o: arith.h
-arith.o: botch_free.h
 arith.o: expr.h
 arith.o: field.h
 arith.o: idf.h
@@ -427,8 +465,10 @@ code.o: def.h
 code.o: expr.h
 code.o: file_info.h
 code.o: idf.h
+code.o: l_lint.h
 code.o: label.h
 code.o: level.h
+code.o: lint.h
 code.o: noRoption.h
 code.o: nobitfield.h
 code.o: nocross.h
@@ -450,6 +490,7 @@ dumpidf.o: expr.h
 dumpidf.o: field.h
 dumpidf.o: idf.h
 dumpidf.o: label.h
+dumpidf.o: lint.h
 dumpidf.o: nobitfield.h
 dumpidf.o: nofloat.h
 dumpidf.o: nopp.h
@@ -461,10 +502,12 @@ dumpidf.o: type.h
 error.o: LLlex.h
 error.o: arith.h
 error.o: debug.h
+error.o: def.h
 error.o: errout.h
 error.o: expr.h
 error.o: file_info.h
 error.o: label.h
+error.o: lint.h
 error.o: nofloat.h
 error.o: nopp.h
 error.o: spec_arith.h
@@ -479,6 +522,7 @@ field.o: expr.h
 field.o: field.h
 field.o: idf.h
 field.o: label.h
+field.o: lint.h
 field.o: nobitfield.h
 field.o: nocross.h
 field.o: nofloat.h
@@ -507,6 +551,7 @@ LLlex.o: file_info.h
 LLlex.o: idf.h
 LLlex.o: idfsize.h
 LLlex.o: input.h
+LLlex.o: lint.h
 LLlex.o: nocross.h
 LLlex.o: nofloat.h
 LLlex.o: nopp.h
@@ -575,6 +620,7 @@ options.o: class.h
 options.o: dataflow.h
 options.o: idf.h
 options.o: idfsize.h
+options.o: lint.h
 options.o: macro.h
 options.o: noRoption.h
 options.o: nobitfield.h
@@ -610,6 +656,7 @@ stack.o: debug.h
 stack.o: def.h
 stack.o: idf.h
 stack.o: level.h
+stack.o: lint.h
 stack.o: mes.h
 stack.o: noRoption.h
 stack.o: nobitfield.h
@@ -625,6 +672,7 @@ type.o: arith.h
 type.o: botch_free.h
 type.o: def.h
 type.o: idf.h
+type.o: lint.h
 type.o: nobitfield.h
 type.o: nocross.h
 type.o: nofloat.h
@@ -640,6 +688,7 @@ ch7mon.o: def.h
 ch7mon.o: expr.h
 ch7mon.o: idf.h
 ch7mon.o: label.h
+ch7mon.o: lint.h
 ch7mon.o: nobitfield.h
 ch7mon.o: nofloat.h
 ch7mon.o: nopp.h
@@ -651,6 +700,7 @@ label.o: def.h
 label.o: idf.h
 label.o: label.h
 label.o: level.h
+label.o: lint.h
 label.o: noRoption.h
 label.o: nobitfield.h
 label.o: nofloat.h
@@ -670,6 +720,7 @@ eval.o: expr.h
 eval.o: idf.h
 eval.o: label.h
 eval.o: level.h
+eval.o: lint.h
 eval.o: mes.h
 eval.o: nobitfield.h
 eval.o: nocross.h
@@ -700,6 +751,7 @@ switch.o: switch.h
 switch.o: type.h
 conversion.o: Lpars.h
 conversion.o: arith.h
+conversion.o: lint.h
 conversion.o: nobitfield.h
 conversion.o: nocross.h
 conversion.o: nofloat.h
@@ -710,6 +762,7 @@ conversion.o: type.h
 util.o: Lpars.h
 util.o: align.h
 util.o: def.h
+util.o: lint.h
 util.o: nocross.h
 util.o: nofloat.h
 util.o: regcount.h
@@ -723,6 +776,7 @@ blocks.o: align.h
 blocks.o: arith.h
 blocks.o: atw.h
 blocks.o: label.h
+blocks.o: lint.h
 blocks.o: nocross.h
 blocks.o: nofloat.h
 blocks.o: sizes.h
@@ -730,10 +784,116 @@ blocks.o: spec_arith.h
 blocks.o: stack.h
 blocks.o: target_sizes.h
 dataflow.o: dataflow.h
+l_lint.o: LLlex.h
+l_lint.o: Lpars.h
+l_lint.o: arith.h
+l_lint.o: code.h
+l_lint.o: def.h
+l_lint.o: expr.h
+l_lint.o: file_info.h
+l_lint.o: idf.h
+l_lint.o: l_lint.h
+l_lint.o: l_outdef.h
+l_lint.o: l_state.h
+l_lint.o: label.h
+l_lint.o: level.h
+l_lint.o: lint.h
+l_lint.o: nobitfield.h
+l_lint.o: nofloat.h
+l_lint.o: nopp.h
+l_lint.o: spec_arith.h
+l_lint.o: stack.h
+l_lint.o: type.h
+l_states.o: LLlex.h
+l_states.o: Lpars.h
+l_states.o: arith.h
+l_states.o: assert.h
+l_states.o: code.h
+l_states.o: debug.h
+l_states.o: def.h
+l_states.o: expr.h
+l_states.o: file_info.h
+l_states.o: idf.h
+l_states.o: l_brace.h
+l_states.o: l_lint.h
+l_states.o: l_outdef.h
+l_states.o: l_state.h
+l_states.o: label.h
+l_states.o: level.h
+l_states.o: lint.h
+l_states.o: nobitfield.h
+l_states.o: nofloat.h
+l_states.o: nopp.h
+l_states.o: spec_arith.h
+l_states.o: stack.h
+l_states.o: type.h
+l_misc.o: LLlex.h
+l_misc.o: Lpars.h
+l_misc.o: arith.h
+l_misc.o: code.h
+l_misc.o: def.h
+l_misc.o: expr.h
+l_misc.o: file_info.h
+l_misc.o: idf.h
+l_misc.o: l_state.h
+l_misc.o: label.h
+l_misc.o: level.h
+l_misc.o: lint.h
+l_misc.o: nobitfield.h
+l_misc.o: nofloat.h
+l_misc.o: nopp.h
+l_misc.o: spec_arith.h
+l_misc.o: stack.h
+l_misc.o: type.h
+l_ev_ord.o: LLlex.h
+l_ev_ord.o: Lpars.h
+l_ev_ord.o: arith.h
+l_ev_ord.o: code.h
+l_ev_ord.o: def.h
+l_ev_ord.o: expr.h
+l_ev_ord.o: file_info.h
+l_ev_ord.o: idf.h
+l_ev_ord.o: l_lint.h
+l_ev_ord.o: l_state.h
+l_ev_ord.o: label.h
+l_ev_ord.o: level.h
+l_ev_ord.o: lint.h
+l_ev_ord.o: nobitfield.h
+l_ev_ord.o: nofloat.h
+l_ev_ord.o: nopp.h
+l_ev_ord.o: spec_arith.h
+l_ev_ord.o: stack.h
+l_ev_ord.o: type.h
+l_outdef.o: LLlex.h
+l_outdef.o: Lpars.h
+l_outdef.o: arith.h
+l_outdef.o: def.h
+l_outdef.o: expr.h
+l_outdef.o: field.h
+l_outdef.o: file_info.h
+l_outdef.o: idf.h
+l_outdef.o: l_class.h
+l_outdef.o: l_lint.h
+l_outdef.o: l_outdef.h
+l_outdef.o: label.h
+l_outdef.o: level.h
+l_outdef.o: lint.h
+l_outdef.o: nobitfield.h
+l_outdef.o: nofloat.h
+l_outdef.o: nopp.h
+l_outdef.o: spec_arith.h
+l_outdef.o: stack.h
+l_outdef.o: struct.h
+l_outdef.o: type.h
+l_comment.o: arith.h
+l_comment.o: l_state.h
+l_comment.o: lint.h
+l_comment.o: spec_arith.h
 tokenfile.o: Lpars.h
 declar.o: LLlex.h
 declar.o: Lpars.h
 declar.o: arith.h
+declar.o: code.h
 declar.o: debug.h
 declar.o: declar.h
 declar.o: decspecs.h
@@ -742,8 +902,11 @@ declar.o: expr.h
 declar.o: field.h
 declar.o: file_info.h
 declar.o: idf.h
+declar.o: l_lint.h
+declar.o: l_state.h
 declar.o: label.h
 declar.o: level.h
+declar.o: lint.h
 declar.o: nobitfield.h
 declar.o: nocross.h
 declar.o: nofloat.h
@@ -763,7 +926,10 @@ statement.o: def.h
 statement.o: expr.h
 statement.o: file_info.h
 statement.o: idf.h
+statement.o: l_lint.h
+statement.o: l_state.h
 statement.o: label.h
+statement.o: lint.h
 statement.o: nobitfield.h
 statement.o: nofloat.h
 statement.o: nopp.h
@@ -773,10 +939,12 @@ statement.o: type.h
 expression.o: LLlex.h
 expression.o: Lpars.h
 expression.o: arith.h
+expression.o: code.h
 expression.o: expr.h
 expression.o: file_info.h
 expression.o: idf.h
 expression.o: label.h
+expression.o: lint.h
 expression.o: noRoption.h
 expression.o: nobitfield.h
 expression.o: nofloat.h
@@ -793,7 +961,9 @@ program.o: def.h
 program.o: expr.h
 program.o: file_info.h
 program.o: idf.h
+program.o: l_state.h
 program.o: label.h
+program.o: lint.h
 program.o: nobitfield.h
 program.o: nofloat.h
 program.o: nopp.h
@@ -804,6 +974,7 @@ ival.o: LLlex.h
 ival.o: Lpars.h
 ival.o: arith.h
 ival.o: assert.h
+ival.o: code.h
 ival.o: debug.h
 ival.o: def.h
 ival.o: estack.h
@@ -811,8 +982,10 @@ ival.o: expr.h
 ival.o: field.h
 ival.o: file_info.h
 ival.o: idf.h
+ival.o: l_lint.h
 ival.o: label.h
 ival.o: level.h
+ival.o: lint.h
 ival.o: noRoption.h
 ival.o: nobitfield.h
 ival.o: nocross.h
index 153888b..226c447 100644 (file)
@@ -1,3 +1,7 @@
+!File: lint.h
+#undef LINT            1       /* if defined, 'lint' is produced       */
+
+
 !File: pathlength.h
 #define PATHLENGTH     1024    /* max. length of path to file          */
 
index 6e19e0f..95334d1 100755 (executable)
@@ -12,7 +12,7 @@ esac
 PW=`pwd`
 options=
 case $1 in
-main|emain)
+main|emain|lnt)
        target=$PW/$1
        ;;
 omain)
index e7282ac..1684995 100644 (file)
@@ -5,6 +5,9 @@
 /* $Header$ */
 /*     B L O C K   S T O R I N G   A N D   L O A D I N G       */
 
+#include       "lint.h"
+#ifndef        LINT
+
 #include <em.h>
 #include <em_reg.h>
 #include "arith.h"
@@ -161,3 +164,5 @@ copy_loop(sz, src, dst)
 }
 #endif STB
 
+#endif LINT
+
index 3fd3919..597debc 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /*     S E M A N T I C   A N A L Y S I S -- C H A P T E R  7 RM        */
 
+#include       "lint.h"
 #include       "nofloat.h"
 #include       "debug.h"
 #include       "nobitfield.h"
@@ -218,6 +219,10 @@ ch7cast(expp, oper, tp)
                if (oper != CAST)
                        expr_warning(*expp, "incompatible pointers in %s",
                                                        symbol2str(oper));
+#ifdef LINT
+               if (oper == CAST)
+                       lint_ptr_conv(oldtp->tp_up->tp_fund, tp->tp_up->tp_fund);
+#endif LINT
                (*expp)->ex_type = tp;  /* free conversion */
        }
        else
index fea6ff8..40b48e2 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /*     C O D E - G E N E R A T I N G   R O U T I N E S         */
 
+#include       "lint.h"
 #include       <em.h>
 #include       "botch_free.h"
 #include       <alloc.h>
 #include       "assert.h"
 #include       "noRoption.h"
 #include       "file_info.h"
+#ifdef LINT
+#include       "l_lint.h"
+#endif LINT
+
 label lab_count = 1;
 label datlab_count = 1;
 
@@ -49,6 +54,7 @@ static int    pro_id;
 extern char options[];
 extern char *symbol2str();
 
+#ifndef        LINT
 init_code(dst_file)
        char *dst_file;
 {
@@ -64,6 +70,8 @@ init_code(dst_file)
        C_insertpart(tmp_id = C_getid());
 #endif USE_TMP
 }
+#endif LINT
+
 static struct string_cst *str_list = 0;
 
 code_string(val, len, dlb)
@@ -262,6 +270,7 @@ end_proc(fbytes)
        if (return_expr_occurred) C_asp(-func_size);
        C_df_ilb(return_label);
        prc_exit();
+#ifndef        LINT
        if (return_expr_occurred) {
                if (func_res_label != 0)        {
                        C_lae_dlb(func_res_label, (arith)0);
@@ -273,6 +282,8 @@ end_proc(fbytes)
                        C_ret(func_size);
        }
        else    C_ret((arith) 0);
+#endif LINT
+
        /* getting the number of "local" bytes is posponed until here,
           because copying the function result in "func_res_label" may
           need temporaries! However, local_level is now L_FORMAL2, because
@@ -466,6 +477,7 @@ loc_init(expr, id)
        }
        else    {       /* not embraced */
                ch7cast(&expr, '=', tp);        /* may modify expr */
+#ifndef        LINT
                {
                        struct value vl;
 
@@ -475,6 +487,9 @@ loc_init(expr, id)
                        vl.vl_value = (arith)0;
                        store_val(&vl, tp);
                }
+#else  LINT
+               id->id_def->df_set = 1;
+#endif LINT
                free_expression(expr);
        }
 }
@@ -522,6 +537,9 @@ formal_cvt(df)
        }
 }
 
+#ifdef LINT
+/*ARGSUSED*/
+#endif LINT
 code_expr(expr, val, code, tlbl, flbl)
        struct expr *expr;
        label tlbl, flbl;
@@ -530,9 +548,13 @@ code_expr(expr, val, code, tlbl, flbl)
                generator.  If line number trace is wanted, it generates a
                lin instruction.  EVAL() is called directly.
        */
+#ifndef        LINT
        if (! options['L'])     /* profiling    */
                C_lin((arith)(expr->ex_line));
        EVAL(expr, val, code, tlbl, flbl);
+#else  LINT
+       pre_lint_expr(expr, RVAL, code ? USED : IGNORED);
+#endif LINT
 }
 
 /*     The FOR/WHILE/DO/SWITCH stacking mechanism:
index 903f245..2e17b85 100644 (file)
@@ -5,6 +5,9 @@
 /* $Header$ */
 /*     C O N V E R S I O N - C O D E  G E N E R A T O R        */
 
+#include       "lint.h"
+#ifndef        LINT
+
 #include       "nofloat.h"
 #include       <em.h>
 #include       "arith.h"
@@ -149,3 +152,5 @@ convtype(tp)
        return 0;
 }
 
+#endif LINT
+
index 2a6e5a5..718b673 100644 (file)
@@ -6,6 +6,7 @@
 /*     DECLARATION SYNTAX PARSER       */
 
 {
+#include       "lint.h"
 #include       <alloc.h>
 #include       "nobitfield.h"
 #include       "debug.h"
 #include       "expr.h"
 #include       "sizes.h"
 #include       "level.h"
+#ifdef LINT
+#include       "l_lint.h"
+#include       "l_state.h"
+#endif LINT
+
 extern char options[];
 }
 
@@ -158,6 +164,9 @@ init_declarator(register struct decspecs *ds;)
        {
                reject_params(&Dc);
                declare_idf(ds, &Dc, level);
+#ifdef LINT
+               lint_declare_idf(Dc.dc_idf, ds->ds_sc);
+#endif LINT
        }
        [
                initializer(Dc.dc_idf, ds->ds_sc)
@@ -166,6 +175,9 @@ init_declarator(register struct decspecs *ds;)
        ]
 ]
        {
+#ifdef LINT
+               add_auto(Dc.dc_idf);
+#endif LINT
                remove_declarator(&Dc);
        }
 ;
@@ -193,6 +205,9 @@ initializer(struct idf *idf; int sc;)
                */
        ]
        {
+#ifdef LINT
+               lint_statement();
+#endif LINT
                if (globalflag) {
                        struct expr ex;
                        code_declaration(idf, &ex, level, sc);
@@ -208,6 +223,10 @@ initializer(struct idf *idf; int sc;)
 #ifdef DEBUG
                        print_expr("initializer-expression", expr);
 #endif DEBUG
+#ifdef LINT
+                       change_state(idf, SET);
+                       pre_lint_expr(expr, RVAL, USED);
+#endif LINT
                        code_declaration(idf, expr, level, sc);
                }
                init_idf(idf);
index 3c30fb6..8d719f2 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /* IDENTIFIER DEFINITION DESCRIPTOR */
 
+#include       "lint.h"
 
 struct def     {               /* for ordinary tags */
        struct def *next;
@@ -21,6 +22,11 @@ struct def   {               /* for ordinary tags */
        char df_used;           /* set if idf is used */
        char *df_file;          /* file containing the definition */
        unsigned int df_line;   /* line number of the definition */
+#ifdef LINT
+       char df_set;
+       int df_firstbrace;      /* brace number of its first occurrence */
+       int df_minlevel;        /* the lowest level needed for this def */
+#endif LINT
        char df_formal_array;   /* to warn if sizeof is taken */
        arith df_address;
 };
index 68f4bd7..3aef50d 100644 (file)
@@ -9,6 +9,7 @@
 #include       <system.h>
 #include       <em.h>
 
+#include       "lint.h"
 #include       "nopp.h"
 #include       "errout.h"
 #include       "debug.h"
 int err_occurred = 0;
 
 extern char options[];
+#ifdef LINT
+extern char loptions[];
+#endif LINT
+
 /*     There are three general error-message functions:
                lexerror()      lexical and pre-processor error messages
                error()         syntactic and semantic error messages
@@ -110,6 +115,54 @@ expr_warning(va_alist)                     /* expr, fmt, args */
        va_end(ap);
 }
 
+#ifdef LINT
+
+/*VARARGS*/
+def_warning(va_alist)                  /* def, fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               register struct def *def = va_arg(ap, struct def *);
+
+               _error(WARNING, def->df_file, def->df_line, ap);
+       }
+       va_end(ap);
+}
+
+
+/*VARARGS*/
+hwarning(va_alist)                     /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               if (loptions['h'])
+                       _error(WARNING, dot.tk_file, dot.tk_line, ap);
+       }
+       va_end(ap);
+}
+
+/*VARARGS*/
+awarning(va_alist)                     /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               if (loptions['a'])
+                       _error(WARNING, dot.tk_file, dot.tk_line, ap);
+       }
+       va_end(ap);
+}
+
+#endif LINT
+
 /*VARARGS*/
 lexerror(va_alist)                     /* fmt, args */
        va_dcl
@@ -186,9 +239,11 @@ _error(class, fn, ln, ap)
        /*      _error attempts to limit the number of error messages
                for a given line to MAXERR_LINE.
        */
+#ifndef        LINT
        static char *last_fn = 0;
        static unsigned int last_ln = 0;
        static int e_seen = 0;
+#endif LINT
        char *remark;
        char *fmt = va_arg(ap, char *);
        
@@ -215,7 +270,11 @@ _error(class, fn, ln, ap)
        /* the remark */
        switch (class)  {       
        case WARNING:
+#ifndef        LINT
                remark = "(warning)";
+#else  LINT
+               remark = 0;
+#endif LINT
                break;
 
        case ERROR:
@@ -233,6 +292,7 @@ _error(class, fn, ln, ap)
                /*NOTREACHED*/;
        }
        
+#ifndef        LINT
        if (ln == last_ln && fn && last_fn && strcmp(fn, last_fn) == 0) {
                /* we've seen this place before */
                e_seen++;
@@ -249,6 +309,20 @@ _error(class, fn, ln, ap)
                last_ln = ln;
                e_seen = 0;
        }
+#endif LINT
+
+#ifdef LINT
+       if (    /* there is a file name */
+               fn
+       &&      /* the file name is global */
+               fn[0] == '/'
+       &&      /* it is not a .c file */
+               strcmp(&fn[strlen(fn)-2], ".c") != 0
+       ) {
+               /* we skip this message */
+               return;
+       }
+#endif LINT
        
        if (fn)
                fprint(ERROUT, "\"%s\", line %u: ", fn, ln);
index f28278a..04264e1 100644 (file)
@@ -5,6 +5,9 @@
 /* $Header$ */
 /* EXPRESSION-CODE GENERATOR */
 
+#include       "lint.h"
+#ifndef        LINT
+
 #include       "nofloat.h"
 #include       <em.h>
 #include       <em_reg.h>
@@ -969,3 +972,5 @@ load_cst(val, siz)
        }
 }
 
+#endif LINT
+
index 5b8d8ef..21b8815 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /* EXPRESSION TREE HANDLING */
 
+#include       "lint.h"
 #include       "nofloat.h"
 #include       "botch_free.h"
 #include       <alloc.h>
@@ -181,7 +182,9 @@ idf2expr(expr)
                expr->ex_type = error_type;
        }
        else {
+#ifndef        LINT
                def->df_used = 1;
+#endif LINT
                expr->ex_type = def->df_type;
                if (expr->ex_type == error_type)
                        expr->ex_flags |= EX_ERROR;
@@ -196,12 +199,14 @@ idf2expr(expr)
                expr->VL_CLASS = Const;
                expr->VL_VALUE = def->df_address;
        }
+#ifndef        LINT
        else
        if (def->df_sc == STATIC && def->df_level >= L_LOCAL) {
                expr->VL_CLASS = Label;
                expr->VL_LBL = def->df_address;
                expr->VL_VALUE = (arith)0;
        }
+#endif LINT
        else {
                expr->VL_CLASS = Name;
                expr->VL_IDF = idf;
index d26ed5f..a22c187 100644 (file)
@@ -6,6 +6,7 @@
 /*     EXPRESSION SYNTAX PARSER        */
 
 {
+#include       "lint.h"
 #include       "arith.h"
 #include       "LLlex.h"
 #include       "type.h"
@@ -207,6 +208,10 @@ conditional_expression(struct expr **expp;)
 #endif
                        ch7bin(&e1, ':', e2);
                        opnd2test(expp, '?');
+#ifdef LINT
+                       if (is_cp_cst(*expp))
+                               hwarning("condition in ?: is constant");
+#endif LINT
                        ch7bin(expp, '?', e1);
                }
        ]?
index 0555e28..3b94431 100644 (file)
@@ -5,6 +5,9 @@
 /* $Header$ */
 /*     BITFIELD EXPRESSION EVALUATOR   */
 
+#include       "lint.h"
+#ifndef        LINT
+
 #include       "nobitfield.h"
 
 #ifndef NOBITFIELD
@@ -174,3 +177,5 @@ eval_field(expr, code)
 }
 #endif NOBITFIELD
 
+#endif LINT
+
index 4a1a801..3d5e47b 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /*     IDENTIFIER  FIDDLING & SYMBOL TABLE HANDLING    */
 
+#include       "lint.h"
 #include       <em_reg.h>
 #include       "nofloat.h"
 #include       "debug.h"
@@ -266,6 +267,22 @@ declare_idf(ds, dc, lvl)
        }
 #endif
 
+#ifdef LINT
+       if (    def && def->df_level < lvl
+       &&      !(lvl == L_FORMAL2 || def->df_level == L_UNIVERSAL)
+       ) {
+               /*      there is already a definition for this name
+                       on a more global level
+               */
+               warning("%s is already defined as a %s",
+                       idf->id_text,
+                       def->df_level == L_GLOBAL ? "global" :
+                       def->df_level == L_FORMAL2 ? "formal" :
+                               "more global local"
+               );
+       }
+#endif LINT
+
        if (def && 
            ( def->df_level == lvl ||
              ( lvl != L_GLOBAL && def->df_level > lvl )
@@ -326,6 +343,11 @@ declare_idf(ds, dc, lvl)
                newdef->df_sc = sc;
                newdef->df_file = idf->id_file;
                newdef->df_line = idf->id_line;
+#ifdef LINT
+               newdef->df_set = (type->tp_fund == ARRAY);
+               newdef->df_firstbrace = 0;
+#endif LINT
+
                /* link it into the name list in the proper place */
                idf->id_def = newdef;
                update_ahead(idf);
index 88fd557..82a371e 100644 (file)
@@ -6,6 +6,7 @@
 /* CODE FOR THE INITIALISATION OF GLOBAL VARIABLES */
 
 {
+#include       "lint.h"
 #include       "nofloat.h"
 #include       <em.h>
 #include       "debug.h"
 #include       "noRoption.h"
 #include       "estack.h"
 #include       "code.h"
+#ifdef LINT
+#include       "l_lint.h"
+#endif LINT
+
 #define con_nullbyte() C_con_ucon("0", (arith)1)
 #define aggregate_type(tp) ((tp)->tp_fund == ARRAY || (tp)->tp_fund == STRUCT)
 
@@ -48,6 +53,9 @@ initial_value(register struct type **tpp; register struct expr **expp;) :
 [
        assignment_expression(expp)
                {
+#ifdef LINT
+                       pre_lint_expr(*expp, RVAL, USED);
+#endif LINT
                        if ((*expp)->ex_type->tp_fund == ARRAY)
                                array2pointer(*expp);
                        if (tpp) {
diff --git a/lang/cem/cemcom/l_class.h b/lang/cem/cemcom/l_class.h
new file mode 100644 (file)
index 0000000..2a77e54
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
+/*     Lint class constants    */
+
+#define        LFDF    'a'     /* Library Function Definition */
+#define        LVDF    'b'     /* Library Variable Definition */
+#define        EFDF    'c'     /* External Function Definition */
+#define        EVDF    'd'     /* External Variable Definition */
+#define        EFDC    'e'     /* External Function Declaration */
+#define        EVDC    'f'     /* External Variable Declaration */
+#define        IFDC    'g'     /* Implicit Function Declaration */
+#define        SFDF    'h'     /* Static Function Definition */
+#define        SVDF    'i'     /* Static Variable Definition */
+#define        FC      'j'     /* Function Call */
+#define        VU      'k'     /* Variable Usage */
+#define        XXDF    'l'     /* Ignore Class */
+
diff --git a/lang/cem/cemcom/l_comment.c b/lang/cem/cemcom/l_comment.c
new file mode 100644 (file)
index 0000000..fd5b21a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint-specific comment handling  */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       "arith.h"
+#include       "l_state.h"
+
+static int NOTREACHED;
+static int VARARGSn = -1;
+static int ARGSUSED;
+int LINTLIB;
+
+int s_NOTREACHED;
+int f_VARARGSn;
+int f_ARGSUSED;
+
+set_not_reached()
+{
+       NOTREACHED = 1;
+}
+
+move_NOT2s()
+{
+       s_NOTREACHED = NOTREACHED;
+       NOTREACHED = 0;
+}
+
+set_varargs(n)
+{
+       VARARGSn = n;
+}
+
+move_VAR2f()
+{
+       f_VARARGSn = VARARGSn;
+       VARARGSn = -1;
+}
+
+set_argsused(n)
+{
+       ARGSUSED = n;
+}
+
+move_ARG2f()
+{
+       f_ARGSUSED = ARGSUSED;
+       ARGSUSED = 0;
+}
+
+set_lintlib()
+{
+       LINTLIB = 1;
+}
+
+#define IN_SPACE       0
+#define IN_WORD                1
+#define IN_COMMENT     2
+
+lint_comment(c)
+       int c;
+{
+/* This function is called with every character between /_* and *_/ (the
+ * _underscores are used because comment in C doesn't nest).
+ * It looks for pseudocomments.
+ * In this version it is allowed that 'keyword' is followed by rubbish.
+ * At the start of each comment the function should be initialized by
+ * calling it with c = -2.
+ * I am not sure if this way of information hiding is a good solution.
+ */
+       static int position;    /* IN_SPACE, IN_WORD, IN_COMMENT */
+       static char buf[12];
+       static int i;           /* next free position in buf */
+
+       if (c == -2) {
+               position = IN_SPACE;
+               i = 0;
+               return;
+       }
+       if (position == IN_COMMENT)
+               return;
+       if (position == IN_SPACE) {
+               if (c == ' ' || c == '\t')
+                       return;
+               position = IN_WORD;
+       }
+       /* position == IN_WORD */
+       if (c == ' ' || c == '\t' || c == '*') {
+               position = IN_COMMENT;
+               check_pseudo(buf, i);
+       }
+       else
+       if (i < 12)
+               buf[i++] = (char)c;
+       else
+               position = IN_COMMENT;
+}
+
+#include       <ctype.h>
+
+check_pseudo(buf, i)
+       char *buf;
+{
+/* Look if the i characters in buf are aequivalent with one of the
+ * strings N_OTREACHED, V_ARARGS[n], A_RGSUSED, L_INTLIBRARY
+ * (the u_nderscores are there to not confuse (UNIX) lint)
+ */
+       buf[i++] = '\0';
+       if (!strcmp(buf, "NOTREACHED"))
+               set_not_reached();
+       else if (!strcmp(buf, "ARGSUSED"))
+               set_argsused(1);
+       else if (!strcmp(buf, "LINTLIBRARY"))
+               set_lintlib();
+       else if (!strncmp(buf, "VARARGS", 7)) {
+               if (i == 8)
+                       set_varargs(0);
+               else if (i == 9 && isdigit(buf[7]))
+                       set_varargs(atoi(&buf[7]));
+       }
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom/l_dummy.c b/lang/cem/cemcom/l_dummy.c
new file mode 100644 (file)
index 0000000..ef4f8f9
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *The following functions are hacked to null-functions (i.e. they
+ * do nothing). This needs another solution in the future.
+ */
+#include       "arith.h"
+#include       "label.h"
+
+C_close(){}
+int C_busy(){return 0;}
+
+
+/* More routines */
+/* ARGSUSED */
+CC_bhcst(ps_xxx,n,w,i) arith n,w; {}
+/* ARGSUSED */
+CC_crcst(ps_xxx,v) arith v; {}
+/* ARGSUSED */
+CC_crdlb(ps_xxx,v,s) label v; arith s; {}
+/* ARGSUSED */
+CC_crdnam(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_crfcon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_cricon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_crilb(ps_xxx,v) label v; {}
+/* ARGSUSED */
+CC_crpnam(ps_xxx,v) char *v; {}
+/* ARGSUSED */
+CC_crscon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_crucon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_cst(l) {}
+/* ARGSUSED */
+CC_dfdlb(l) label l; {}
+/* ARGSUSED */
+CC_dfdnam(s) char *s; {}
+/* ARGSUSED */
+CC_dfilb(l) label l; {}
+/* ARGSUSED */
+CC_end(l) arith l; {}
+CC_msend() {}
+/* ARGSUSED */
+CC_msstart(ms) {}
+/* ARGSUSED */
+CC_opcst(op_xxx,c) arith c; {}
+/* ARGSUSED */
+CC_opdlb(op_xxx,g,o) label g; arith o; {}
+/* ARGSUSED */
+CC_opilb(op_xxx,b) label b; {}
+/* ARGSUSED */
+CC_oppnam(op_xxx,p) char *p; {}
+/* ARGSUSED */
+CC_pronarg(s) char *s; {}
+/* ARGSUSED */
+CC_psdlb(ps_xxx,l) label l; {}
+/* ARGSUSED */
+CC_psdnam(ps_xxx,s) char *s; {}
+/* ARGSUSED */
+CC_pspnam(ps_xxx,s) char *s; {}
+/* ARGSUSED */
+CC_scon(v,s) char *s; {}
diff --git a/lang/cem/cemcom/l_ev_ord.c b/lang/cem/cemcom/l_ev_ord.c
new file mode 100644 (file)
index 0000000..810c5c9
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint evaluation order checking  */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_lint.h"
+#include       "l_state.h"
+
+extern char *symbol2str();
+
+check_and_merge(espp, esp, com_oper)
+       struct expr_state **espp, *esp;
+{
+/* Checks for undefined evaluation orders in case of a commutative operator.
+ * In addition the sets of used and set variables of both expressions are
+ * united.
+ * *espp will be pointing to this new list. esp is used for this list.
+ */
+       register struct expr_state **pp, *p1, *p2;
+
+       for (p1 = *espp; p1; p1 = p1->next) {
+               p2 = esp;
+               pp = &esp;
+               while (p2) {
+                       if (    /* p1 and p2 are the same */
+                               p1->es_idf == p2->es_idf
+                       &&      p1->es_offset == p2->es_offset
+                       ) {
+                               if (com_oper)
+                                       check_ev_order(p1, p2, com_oper);
+                               p1->es_used |= p2->es_used;
+                               p1->es_set |= p2->es_set;
+                               *pp = p2->next;
+                               free_expr_state(p2);
+                               p2 = *pp;
+                       }
+                       else {
+                               pp = &p2->next;
+                               p2 = p2->next;
+                       }
+               }
+       }
+       /* The rest of the list esp is pointing to, is put in front of the list
+        * *espp is now pointing to.
+        * *espp will be pointing to this new list.
+        */
+       if (!esp)
+               return;
+       p1 = *espp;
+       *espp = esp;
+       while (esp->next)
+               esp = esp->next;
+       esp->next = p1;
+}
+
+check_ev_order(esp1, esp2, com_oper)
+       struct expr_state *esp1, *esp2;
+{
+       if (    (esp1->es_used && esp2->es_set)
+       ||      (esp1->es_set && esp2->es_used)
+       ||      (esp1->es_set && esp2->es_set)
+       ) {
+               warning("result of %s depends on evaluation order on %s",
+                       symbol2str(com_oper),
+                       esp1->es_idf->id_text);
+       }
+}
+
+add_expr_state(value, to_state, espp)
+       struct value value;
+       struct expr_state **espp;
+{
+       register struct expr_state *esp = *espp;
+
+       if (value.vl_class != Name) {
+               crash("(add_expr_state) invalid vl_class");
+               /*NOTREACHED*/
+       }
+       while ( esp
+       &&      !(      esp->es_idf == value.vl_data.vl_idf
+               &&      esp->es_offset == value.vl_value
+               )
+       ) {
+               esp = esp->next;
+       }
+       if (!esp) {     /* create new expr_state */
+               esp = new_expr_state();
+               esp->es_idf = value.vl_data.vl_idf;
+               esp->es_offset = value.vl_value;
+               esp->next = *espp;
+               *espp = esp;
+       }
+       if (to_state == SET)
+               esp->es_set = 1;
+       else    /* USED */
+               esp->es_used = 1;
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom/l_lint.c b/lang/cem/cemcom/l_lint.c
new file mode 100644 (file)
index 0000000..6f6be68
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint main routines      */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_lint.h"
+#include       "l_state.h"
+#include       "l_outdef.h"
+
+extern char options[128];
+extern char *symbol2str();
+
+struct expr_state *lint_expr();
+
+lint_init()
+{
+/* Allocate some memory for the global stack_bottom
+ * and some other initializations
+ */
+
+       extern struct lint_stack_entry stack_bottom;
+
+       stack_bottom.ls_current = new_state();
+}
+
+pre_lint_expr(expr, val, used)
+       struct expr *expr;
+{
+/* Introduced to dispose the returned expression states */
+
+       register struct expr_state *esp;
+
+       esp = lint_expr(expr, val, used);
+       free_expr_states(esp);
+}
+
+free_expr_states(esp)
+       register struct expr_state *esp;
+{
+       register struct expr_state *esp2;
+
+       while (esp) {
+               esp2 = esp;
+               esp = esp->next;
+               free_expr_state(esp2);
+       }
+}
+
+struct expr_state *
+lint_expr(expr, val, used)
+       register struct expr *expr;
+{
+/* Main function to process an expression tree.
+ * It returns a structure containing information about which variables
+ * are set and which are used in the expression.
+ * In addition it sets 'used' and 'set' fields of the corresponding
+ * variables in the current state.
+ * If the value of an operation without side-effects is not used,
+ * a warning is given.
+ */
+       struct expr_state *esp1 = 0, *esp2 = 0;
+
+       if (used == IGNORED) {
+               expr_ignored(expr);
+       }
+
+       switch (expr->ex_class) {
+       case Value:
+               switch (expr->VL_CLASS) {
+               case Const:
+               case Label:
+                       return(0);
+
+               case Name:
+               {
+                       register struct idf *idf = expr->VL_IDF;
+
+                       if (!idf || !idf->id_def)
+                               return(0);
+
+                       if (    val == LVAL
+                       ||      (       val == RVAL
+                               &&      expr->ex_type->tp_fund == POINTER
+                               &&      !expr->ex_lvalue
+                               )
+                       ) {
+                               change_state(idf, SET);
+                               idf->id_def->df_file =
+                                       Salloc(dot.tk_file,
+                                               strlen(dot.tk_file) + 1);
+                               idf->id_def->df_line = dot.tk_line;
+                       }
+                       if (val == RVAL) {
+                               change_state(idf, USED);
+                               add_expr_state(expr->EX_VALUE, USED, &esp1);
+                       }
+                       return(esp1);
+               }
+
+               default:
+                       crash("(lint_expr) bad value class\n");
+                       /* NOTREACHED */
+               }
+
+       case Oper:
+       {
+               register int oper = expr->OP_OPER;
+               register struct expr *left = expr->OP_LEFT;
+               register struct expr *right = expr->OP_RIGHT;
+
+               switch (oper) {
+               case '=':
+               case PLUSAB:
+               case MINAB:
+               case TIMESAB:
+               case DIVAB:
+               case MODAB:
+               case LEFTAB:
+               case RIGHTAB:
+               case ANDAB:
+               case XORAB:
+               case ORAB:
+                       lint_conversion(oper, right->ex_type, left->ex_type);
+                       /* for cases like i += l; */
+                       esp1 = lint_expr(right, RVAL, USED);
+                       if (oper != '=') {
+                               /* i += 1; is interpreted as i = i + 1; */
+                               esp2 = lint_expr(left, RVAL, USED);
+                               check_and_merge(&esp1, esp2, oper);
+                       }
+                       esp2 = lint_expr(left, LVAL, USED);
+                       /* for cases like i = i + 1; and i not set, this
+                       ** order is essential
+                       */
+                       check_and_merge(&esp1, esp2, oper);
+                       if (    left->ex_class == Value
+                       &&      left->VL_CLASS == Name
+                       ) {
+                               add_expr_state(left->EX_VALUE, SET, &esp1);
+                       }
+                       return(esp1);
+
+               case POSTINCR:
+               case POSTDECR:
+               case PLUSPLUS:
+               case MINMIN:
+                       /* i++; is parsed as i = i + 1;
+                        * This isn't quite correct :
+                        * The first statement doesn't USE i,
+                        * the second does.
+                        */
+                       esp1 = lint_expr(left, RVAL, USED);
+                       esp2 = lint_expr(left, LVAL, USED);
+                       check_and_merge(&esp1, esp2, oper);
+                       if (    left->ex_class == Value
+                       &&      left->VL_CLASS == Name
+                       ) {
+                               add_expr_state(left->EX_VALUE, SET, &esp1);
+                               add_expr_state(left->EX_VALUE, USED, &esp1);
+                       }
+                       return(esp1);
+
+               case '-':
+               case '*':
+                       if (left == 0)  /* unary */
+                               return(lint_expr(right, RVAL, USED));
+                       esp1 = lint_expr(left, RVAL, USED);
+                       esp2 = lint_expr(right, RVAL, USED);
+                       check_and_merge(&esp1, esp2, oper);
+                       return(esp1);
+
+               case '(':
+                       if (right != 0) {
+                               /* function call with parameters */
+                               register struct expr *ex = right;
+
+                               while ( ex->ex_class == Oper
+                               &&      ex->OP_OPER == PARCOMMA
+                               ) {
+                                       esp2 = lint_expr(ex->OP_RIGHT, RVAL,
+                                                        USED);
+                                       check_and_merge(&esp1, esp2, oper);
+                                       ex = ex->OP_LEFT;
+                               }
+                               esp2 = lint_expr(ex, RVAL, USED);
+                               check_and_merge(&esp1, esp2, oper);
+                       }
+                       if (    left->ex_class == Value
+                       &&      left->VL_CLASS == Name
+                       ) {
+                               fill_outcall(expr,
+                                       expr->ex_type->tp_fund == VOID ?
+                                       VOIDED : used
+                               );
+                               outcall();
+                               left->VL_IDF->id_def->df_used = 1;
+                       }
+                       else {
+                               esp2 = lint_expr(left, val, USED);
+                               check_and_merge(&esp1, esp2, oper);
+                       }
+                       return(esp1);
+
+               case '.':
+                       return(lint_expr(left, val, USED));
+
+               case ARROW:
+                       return(lint_expr(left, RVAL, USED));
+
+               case '~':
+               case '!':
+                       return(lint_expr(right, RVAL, USED));
+
+               case '?':
+                       esp1 = lint_expr(left, RVAL, USED);
+                       esp2 = lint_expr(right->OP_LEFT, RVAL, USED);
+                       check_and_merge(&esp1, esp2, 0);
+                       esp2 = lint_expr(right->OP_RIGHT, RVAL, USED);
+                       check_and_merge(&esp1, esp2, 0);
+                       return(esp1);
+
+               case INT2INT:
+               case INT2FLOAT:
+               case FLOAT2INT:
+               case FLOAT2FLOAT:
+                       lint_conversion(oper, right->ex_type, left->ex_type);
+                       return(lint_expr(right, RVAL, USED));
+
+               case '<':
+               case '>':
+               case LESSEQ:
+               case GREATEREQ:
+               case EQUAL:
+               case NOTEQUAL:
+                       lint_relop(left, right, oper);
+                       lint_relop(right, left, 
+                               oper == '<' ? '>' :
+                               oper == '>' ? '<' :
+                               oper == LESSEQ ? GREATEREQ :
+                               oper == GREATEREQ ? LESSEQ :
+                               oper
+                       );
+                       /*FALLTHROUGH*/
+               case '+':
+               case '/':
+               case '%':
+               case ',':
+               case LEFT:
+               case RIGHT:
+               case '&':
+               case '|':
+               case '^':
+               case OR:
+               case AND:
+                       esp1 = lint_expr(left, RVAL,
+                                               oper == ',' ? IGNORED : USED);
+                       esp2 = lint_expr(right, RVAL,
+                                               oper == ',' ? used : USED);
+                       if (oper == OR || oper == AND || oper == ',')
+                               check_and_merge(&esp1, esp2, 0);
+                       else
+                               check_and_merge(&esp1, esp2, oper);
+                       return(esp1);
+
+               default:
+                       return(0);      /* for initcomma */
+               }
+       }
+
+       default:
+               return(0);
+       }
+}
+
+expr_ignored(expr)
+       struct expr *expr;
+{
+       switch (expr->ex_class) {
+       case Oper:
+               switch (expr->OP_OPER) {
+               case '=':
+               case TIMESAB:
+               case DIVAB:
+               case MODAB:
+               case LEFTAB:
+               case RIGHTAB:
+               case ANDAB:
+               case XORAB:
+               case ORAB:
+               case AND:                       /* doubtful but useful */
+               case OR:                        /* doubtful but useful */
+               case '(':
+               case '?':
+               case ',':
+                       break;
+
+               case PLUSAB:
+               case MINAB:
+               case POSTINCR:
+               case POSTDECR:
+               case PLUSPLUS:
+               case MINMIN:
+                       /* may hide the operator * */
+                       if (    /* operation on a pointer */
+                               expr->OP_TYPE->tp_fund == POINTER
+                       &&      /* the result is dereferenced, e.g. *p++; */
+                               expr->ex_type == expr->OP_TYPE->tp_up
+                       ) {
+                               hwarning("result of * ignored");
+                       }
+                       break;
+
+               default:
+                       hwarning("result of %s ignored",
+                                               symbol2str(expr->OP_OPER));
+                       break;
+               }
+               break;
+
+       case Value:
+               hwarning("identifier as statement");
+               break;
+
+       case String:
+       case Float:
+               hwarning("constant as statement");
+               break;
+       }
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom/l_lint.h b/lang/cem/cemcom/l_lint.h
new file mode 100644 (file)
index 0000000..3a59bfa
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     LINT FLAGS      */
+
+#define        USED            0
+#define        IGNORED         1
+#define        SET             2
+#define        VOIDED          3
+
+/* for od_valreturned */
+#define        NOVALRETURNED   0
+#define        VALRETURNED     1
+#define        NORETURN        2               /* end of function NOTREACHED */
+
diff --git a/lang/cem/cemcom/l_misc.c b/lang/cem/cemcom/l_misc.c
new file mode 100644 (file)
index 0000000..84e68d7
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint miscellaneous routines     */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_state.h"
+
+extern char *symbol2str();
+extern struct type *func_type;
+
+lint_conversion(oper, from_type, to_type)
+       struct type *from_type, *to_type;
+{
+       register int from = from_type->tp_fund;
+       register int to = to_type->tp_fund;
+
+       switch (oper) {
+       case RETURN:    /* not really an oper, but it works */
+       case INT2INT:
+       case '=':
+       case PLUSAB:
+       case MINAB:
+       case TIMESAB:
+       case DIVAB:
+       case MODAB:
+       case LEFTAB:
+       case RIGHTAB:
+       case ANDAB:
+       case XORAB:
+       case ORAB:
+               if (    (from == LONG && to != LONG)
+               ||      (from == DOUBLE && to != DOUBLE)
+               ) {
+                       awarning("conversion from %s to %s may lose accuracy",
+                               symbol2str(from), symbol2str(to));
+               }
+       }
+}
+
+lint_ret_conv(from_type)
+       struct type *from_type;
+{
+       lint_conversion(RETURN, from_type, func_type);
+}
+
+lint_ptr_conv(from, to)
+       short from, to;
+{
+/* X -> X ok                   -- this includes struct -> struct, of any size
+ * X -> CHAR ok
+ * DOUBLE -> X ok
+ * FLOAT -> LONG -> INT -> SHORT  ok
+ */
+       if (from == to)
+               return;
+
+       if (to == CHAR)
+               return;
+
+       if (from == DOUBLE)
+               return;
+
+       switch (from) {
+       case FLOAT:
+               switch (to) {
+               case LONG:
+               case INT:
+               case SHORT:
+                       return;
+               }
+               break;
+       case LONG:
+               switch (to) {
+               case INT:
+               case SHORT:
+                       return;
+               }
+               break;
+       case INT:
+               switch (to) {
+               case SHORT:
+                       return;
+               }
+               break;
+       }
+
+       if (from == CHAR) {
+               hwarning("pointer to char may not align correctly for a %s",
+                       symbol2str(to));
+       }
+       else {
+               warning("pointer to %s may not align correctly for a %s",
+                       symbol2str(from), symbol2str(to));
+       }
+}
+
+lint_relop(left, right, oper)
+       struct expr *left, *right;
+       int oper;       /* '<', '>', LESSEQ, GREATEREQ, EQUAL, NOTEQUAL */
+{
+       /* <unsigned> <relop> <neg-const|0> is doubtful */
+       if (    left->ex_type->tp_unsigned
+       &&      right->ex_class == Value
+       &&      right->VL_CLASS == Const
+       ) {
+               if (right->VL_VALUE < 0) {
+                       warning("unsigned compared to negative constant");
+               }
+               if (right->VL_VALUE == 0) {
+                       switch (oper) {
+                       case '<':
+                               warning("unsigned < 0 will always fail");
+                               break;
+
+                       case LESSEQ:
+                               warning("unsigned <= 0 is probably wrong");
+                               break;
+
+                       case GREATEREQ:
+                               warning("unsigned >= 0 will always succeed");
+                               break;
+                       }
+               }
+       }
+
+       /* <char> <relop> <neg-const> is undefined */
+       if (    left->ex_type->tp_fund == CHAR
+       &&      right->ex_class == Value
+       &&      right->VL_CLASS == Const
+       &&      (right->VL_VALUE < 0 || right->VL_VALUE > 127)
+       ) {
+               warning("character compared to negative constant");
+       }
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom/l_outdef.c b/lang/cem/cemcom/l_outdef.c
new file mode 100644 (file)
index 0000000..8df4351
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint outdef construction        */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>
+#include       "arith.h"
+#include       "type.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "def.h"
+#include       "struct.h"
+#include       "field.h"
+#include       "idf.h"
+#include       "level.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "l_lint.h"
+#include       "l_outdef.h"
+#include       "l_class.h"
+
+extern char *symbol2str();
+
+extern int f_VARARGSn, LINTLIB;
+int stat_number = 9999;                        /* static scope number */
+struct outdef OutDef, OutCall;
+
+lint_declare_idf(idf, sc)
+       struct idf *idf;
+       int sc;
+{
+       register struct def *def = idf->id_def;
+       register int is_function = def->df_type->tp_fund == FUNCTION;
+
+       if (level == L_GLOBAL) {
+               lint_ext_def(idf, sc);
+               if (is_function)
+                       def2decl(sc);
+               if (sc != TYPEDEF)
+                       outdef();
+       }
+       else
+       if (level >= L_LOCAL && sc != STATIC && is_function) {
+               local_EFDC(idf);
+       }
+}
+
+lint_ext_def(idf, sc)
+       struct idf *idf;
+{
+/* At this place the following fields of the outputdefinition can be
+ * filled:
+ *             name, stat_number, class, file, line, type.
+ * For variable definitions and declarations this will be all.
+ * For functions the fields nrargs and argtps are filled after parsing
+ * the arguments.
+ * The returns-field is known at the end of the function definition.
+ * sc indicates the storage class defined by the declaration specifier.
+ */
+       register struct def *def = idf->id_def;
+       register struct type *type = def->df_type;
+
+       OutDef.od_name = idf->id_text;
+       OutDef.od_statnr = (sc == STATIC ? stat_number : 0);
+
+       switch (type->tp_fund) {
+       case ERRONEOUS:
+               OutDef.od_class = XXDF;
+               break;
+       case FUNCTION:
+               /* For the moment assume it will be a definition.
+                * If no compound_statement follows, it is a declaration,
+                * in which case the class will be adjusted by def2decl().
+                */
+               OutDef.od_class = (sc == STATIC ? SFDF : EFDF);
+               break;
+       default:        /* a variable */
+               OutDef.od_class =
+                       sc == EXTERN ? EVDC :
+                       sc == STATIC ? SVDF : EVDF;
+               break;
+       }
+       OutDef.od_file = def->df_file;
+       OutDef.od_line = def->df_line;
+       OutDef.od_type = (type->tp_fund == FUNCTION ? type->tp_up : type);
+       OutDef.od_valreturned = NORETURN;
+}
+
+def2decl(sc)
+       int sc;
+{
+/* It was assumed we were parsing a function definition.
+ * There was no compound statement following, so actually it was a
+ * declaration. This function updates the class.
+ */
+       OutDef.od_class = (sc == STATIC ? XXDF : EFDC);
+}
+
+set_od_valreturned(n)
+{
+       OutDef.od_valreturned = n;
+}
+
+local_EFDC(idf)
+       struct idf *idf;
+{
+       struct outdef od;
+
+       od.od_class = EFDC;
+       od.od_statnr = 0;
+       od.od_name = idf->id_text;
+       od.od_file = idf->id_def->df_file;
+       od.od_line = idf->id_def->df_line;
+       od.od_type = idf->id_def->df_type->tp_up;
+       output_def(&od);
+       /* The other fields are not used for this class. */
+}
+
+lint_formals()
+{
+/* Make a list of tp_entries containing the types of the formal
+ * parameters of the function definition currently parsed.
+ */
+       register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
+       register struct tp_entry **hook = &OutDef.od_entry;
+
+       OutDef.od_nrargs = 0;
+       while (se) {
+               register struct type *type = se->se_idf->id_def->df_type;
+               register struct tp_entry *te = new_tp_entry();
+
+               switch (type->tp_fund) {
+               /*      Do the conversions on the formals that could not be
+                       done in declare_idf().
+                       It is, unfortunately, impossible not to do them,
+                       since the corresponding actuals will have been
+                       converted to generate proper code and we do not
+                       want to duplicate the whole of expression handling
+                       for lint.
+               */
+               case CHAR:
+               case SHORT:
+                       type = int_type;
+                       break;
+               case FLOAT:
+                       type = double_type;
+                       break;
+               }
+               te->te_type = type;
+               te->te_class = !Const;
+               *hook = te;
+               hook = &te->next;
+
+               OutDef.od_nrargs++;
+               se = se->next;
+       }
+       if (f_VARARGSn > OutDef.od_nrargs) {
+               warning("VARARGS%d function has only %d arguments",
+                       f_VARARGSn, OutDef.od_nrargs);
+               f_VARARGSn = OutDef.od_nrargs;
+       }
+}
+
+output_use(idf)
+       struct idf *idf;
+{
+/* Output the usage-definition of the variable described by idf.
+ */
+       OutDef.od_name = idf->id_text;
+       OutDef.od_statnr = (idf->id_def->df_sc == STATIC ? stat_number : 0);
+       OutDef.od_class = VU;
+       OutDef.od_file = FileName;
+       OutDef.od_line = LineNumber;
+       OutDef.od_type = idf->id_def->df_type;
+       outdef();
+}
+
+outdef()
+{
+       output_def(&OutDef);
+}
+
+outcall()
+{
+       output_def(&OutCall);
+}
+
+output_def(od)
+       struct outdef *od;
+{
+/* As the types are output the tp_entries are removed, because they
+ * are then not needed anymore.
+ */
+       if (od->od_class == XXDF)
+               return;
+
+       if (LINTLIB) {
+               switch (od->od_class) {
+               case EFDF:
+                       od->od_class = LFDF;
+                       break;
+               case EVDF:
+                       od->od_class = LVDF;
+                       break;
+               case SFDF:
+                       /* remove tp_entries */
+                       while (od->od_entry) {
+                               register struct tp_entry *tmp = od->od_entry;
+                               od->od_entry = od->od_entry->next;
+                               free_tp_entry(tmp);
+                       }
+                       return;
+               default:
+                       return;
+               }
+       }
+       printf("%s:%d:%c", od->od_name, od->od_statnr, od->od_class);
+       switch (od->od_class) {
+       case EFDF:
+       case SFDF:
+       case LFDF:
+               if (f_VARARGSn != -1) {
+                       printf(":%d", -1 - f_VARARGSn);
+                       outtypes(od->od_entry, f_VARARGSn);
+               }
+               else {
+                       printf(":%d", od->od_nrargs);
+                       outtypes(od->od_entry, od->od_nrargs);
+               }
+               od->od_entry = 0;
+               printf(":%d", od->od_valreturned);
+               break;
+       case FC:
+               printf(":%d", od->od_nrargs);
+               outtypes(od->od_entry, od->od_nrargs);
+               od->od_entry = 0;
+               printf(":%d", od->od_valused);
+               break;
+       case EVDF:
+       case SVDF:
+       case LVDF:
+       case EFDC:
+       case EVDC:
+       case IFDC:
+       case VU:
+               break;
+       default:
+               crash("(output_def) illegal class");
+               /*NOTREACHED*/
+       }
+       printf(":");
+       outtype(od->od_type);
+       printf(":%u:%s\n", od->od_line, od->od_file);
+}
+
+outtypes(te, n)
+       struct tp_entry *te;
+{
+/* Output n types in the tp_entry-list and remove all the entries */
+
+       register struct tp_entry *tmp;
+
+       while (n--) {
+               if (!te) {
+                       crash("(outtypes) not enough tp_entries");
+                       /*NOTREACHED*/
+               }
+               printf(":");
+               if (te->te_class == Const && te->te_value >= 0) {
+                       /* constant non-negative actual parameter */
+                       printf("+");
+               }
+               outtype(te->te_type);
+               if (te->te_type->tp_fund == FUNCTION) {
+                       /* UGLY PATCH !!! ??? */
+                       /*      function names as operands are sometimes
+                               FUNCTION and sometimes POINTER to FUNCTION,
+                               depending on opaque circumstances.  E.g., in
+                                       f(main, main);
+                               the first main is PtF and the second is F.
+                       */
+                       printf("*");
+               }
+               tmp = te;
+               te = te->next;
+               free_tp_entry(tmp);
+       }
+       /* remove the remaining entries */
+       while (te) {
+               tmp = te;
+               te = te->next;
+               free_tp_entry(tmp);
+       }
+}
+
+outtype(tp)
+       struct type *tp;
+{
+       switch (tp->tp_fund) {
+       case POINTER:
+               outtype(tp->tp_up);
+               printf("*");
+               break;
+
+       case ARRAY:
+               outtype(tp->tp_up);
+               printf("*");    /* compatible with [] */
+               break;
+
+       case FUNCTION:
+               outtype(tp->tp_up);
+               printf("()");
+               break;
+
+       case STRUCT:
+       case UNION:
+       case ENUM:
+               printf("%s %s", symbol2str(tp->tp_fund), tp->tp_idf->id_text);
+               break;
+
+       case CHAR:
+       case INT:
+       case SHORT:
+       case LONG:
+       case FLOAT:
+       case DOUBLE:
+       case VOID:
+       case ERRONEOUS:
+               if (tp->tp_unsigned)
+                       printf("unsigned ");
+               printf("%s", symbol2str(tp->tp_fund));
+               break;
+       default:
+               crash("(outtype) illegal tp_fund");
+               /*NOTREACHED*/
+       }
+}
+
+implicit_func_decl(idf, file, line)
+       struct idf *idf;
+       char *file;
+       unsigned int line;
+{
+       struct outdef od;
+
+       od.od_class = IFDC;
+       od.od_statnr = 0;
+       od.od_name = idf->id_text;
+       od.od_file = file;
+       od.od_line = line;
+       od.od_type = idf->id_def->df_type->tp_up;
+       output_def(&od);
+       /* The other fields are not used for this class. */
+}
+
+fill_outcall(ex, used)
+       struct expr *ex;
+       int used;
+{
+       register struct idf *idf = ex->OP_LEFT->VL_IDF;
+       register struct def *def = idf->id_def;
+
+       if (def->df_sc == IMPLICIT) {
+               implicit_func_decl(idf, ex->ex_file, ex->ex_line);
+       }
+
+       OutCall.od_type = def->df_type->tp_up;
+       OutCall.od_statnr = (def->df_sc == STATIC ? stat_number : 0);
+       OutCall.od_class = FC;
+       OutCall.od_name = idf->id_text;
+       OutCall.od_file = ex->ex_file;
+       OutCall.od_line = ex->ex_line;
+       OutCall.od_entry = (struct tp_entry *)0;
+       OutCall.od_nrargs = 0;
+
+       if ((ex = ex->OP_RIGHT) != 0) { /* function call with arguments */
+               /* store types of argument expressions in tp_entries */
+               while (ex->ex_class == Oper && ex->OP_OPER == PARCOMMA) {
+                       fill_arg(ex->OP_RIGHT);
+                       ex = ex->OP_LEFT;
+               }
+               fill_arg(ex);
+       }
+       OutCall.od_valused = used;      /* USED, IGNORED or VOIDED */
+}
+
+fill_arg(e)
+       struct expr *e;
+{
+       register struct tp_entry *te;
+
+       te = new_tp_entry();
+       te->te_type = e->ex_type;
+       if (is_cp_cst(e)) {
+               te->te_class = Const;
+               te->te_value = e->VL_VALUE;
+       }
+       else {
+               te->te_class = !Const;
+               te->te_value = (arith) 0;
+       }
+       te->next = OutCall.od_entry;
+       OutCall.od_entry = te;
+       OutCall.od_nrargs++;
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom/l_outdef.str b/lang/cem/cemcom/l_outdef.str
new file mode 100644 (file)
index 0000000..9f768c2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint output definition  */
+
+struct tp_entry {
+       struct tp_entry *next;
+       struct type *te_type;
+       int te_class;                   /* for constant parameters */
+       arith te_value;
+};
+
+/* ALLOCDEF "tp_entry" 10 */
+
+struct outdef {
+       char od_class;
+       int od_statnr;
+       char *od_name;
+       char *od_file;
+       unsigned int od_line;
+       int od_nrargs;
+       struct tp_entry *od_entry;      /* a list of the types of the
+                                        * formal parameters */
+       int od_valreturned;
+               /* NOVALRETURNED, VALRETURNED, NORETURN; see l_lint.h */
+       int od_valused;
+               /* USED, IGNORED, SET, VOIDED; see l_lint.h */
+       struct type *od_type;
+};
diff --git a/lang/cem/cemcom/l_state.str b/lang/cem/cemcom/l_state.str
new file mode 100644 (file)
index 0000000..8263325
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint state stack        */
+
+/* These datastructures are used to implement a stack on which the
+ * state of automatic variables (including register variables) is
+ * kept.
+ * In this way it is possible to account for the flow of
+ * control of the program.
+ */
+
+
+struct switch_states {
+       struct state *sws_case;
+       struct state *sws_break;
+       int sws_default_met;
+};
+
+struct lint_stack_entry {
+       struct lint_stack_entry *next;
+       struct lint_stack_entry *ls_previous;
+       short ls_class;         /* IF, WHILE, DO, FOR, SWITCH, CASE */
+       int ls_level;
+       struct state *ls_current;               /* used by all classes */
+       union {
+               struct state *u_if_state;       /* used for IF-class */
+               struct state *u_end;            /* used for loop-classes */
+               struct switch_states u_switch;
+       } ls_states;    /* not used for CASE-class */
+};
+
+/* macros to access the union */
+#define LS_IF_STATE    ls_states.u_if_state
+#define LS_END         ls_states.u_end
+#define LS_CASE                ls_states.u_switch.sws_case
+#define LS_BREAK       ls_states.u_switch.sws_break
+#define LS_DEFAULT_MET ls_states.u_switch.sws_default_met
+
+/* ALLOCDEF "lint_stack_entry" 10 */
+
+struct state {
+       struct state *next;             /* only used by memory allocator */
+       struct auto_def *st_auto_list;
+       int st_notreached;              /* set if not reached */
+       int st_warned;                  /* set if warning issued */
+};
+
+/* ALLOCDEF "state" 15 */
+
+struct auto_def {
+       struct auto_def *next;
+       struct idf *ad_idf;
+       struct def *ad_def;
+       int ad_used;
+       int ad_set;
+       int ad_maybe_set;
+};
+
+/* ALLOCDEF "auto_def" 20 */
+
+struct expr_state {
+       struct expr_state *next;
+       struct idf *es_idf;
+       arith es_offset;
+       int es_used;
+       int es_set;
+};
+
+/* ALLOCDEF "expr_state" 20 */
+
diff --git a/lang/cem/cemcom/l_states.c b/lang/cem/cemcom/l_states.c
new file mode 100644 (file)
index 0000000..e9d4452
--- /dev/null
@@ -0,0 +1,1102 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint status checking    */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "assert.h"
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_lint.h"
+#include       "l_brace.h"
+#include       "l_state.h"
+#include       "l_outdef.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+extern char *symbol2str();
+extern char *func_name;
+extern struct type *func_type;
+extern int func_notypegiven;
+extern char loptions[];
+extern int s_NOTREACHED;
+
+/* global variables for the lint_stack */
+struct lint_stack_entry stack_bottom;
+struct lint_stack_entry *top_ls = &stack_bottom;
+
+/* global variables for the brace stack */
+int brace_count;
+struct brace brace_bottom;
+struct brace *top_br = &brace_bottom;
+
+static print_autos();
+
+lint_start_local()
+{
+       register struct brace *br = new_brace();
+
+       brace_count++;
+       br->br_count = brace_count;
+       br->br_level = level;
+       br->next = top_br;
+       top_br = br;
+}      
+
+lint_local_level(stl)
+       struct stack_level *stl;
+{
+       if (s_NOTREACHED) {
+               top_ls->ls_current->st_notreached = 1;
+               s_NOTREACHED = 0;
+       }
+
+       if (top_ls->ls_class == CASE && level == top_ls->ls_level) {
+               lint_break_stmt();
+                       /* To prevent a warning for the case
+                        *      switch (cond) {
+                        *      int i;
+                        *      case 0:
+                        *              i = 0;
+                        *              use(i);
+                        *      }
+                        */
+       }
+
+       check_autos();
+       end_brace(stl);
+}
+
+end_brace(stl)
+       struct stack_level *stl;
+{
+       /*      Check if static variables and labels are used and/or set.
+       */
+       register struct stack_entry *se = stl->sl_entry;
+       register struct brace *br;
+
+       while (se) {
+               register struct idf *idf = se->se_idf;
+               register struct def *def = idf->id_def;
+
+               if (def) {
+                       lint_1_local(idf, def);
+               }
+               se = se->next;
+       }
+
+       br = top_br;
+       top_br = br->next;
+       free_brace(br);
+}
+
+lint_1_local(idf, def)
+       struct idf *idf;
+       struct def *def;
+{
+       register int sc = def->df_sc;
+
+       if (    (sc == STATIC || sc == LABEL)
+       &&      !def->df_used
+       ) {
+               def_warning(def, "%s %s declared but not used in function %s",
+                       symbol2str(sc), idf->id_text, func_name);
+       }
+
+       if (    loptions['h']
+       &&      sc == AUTO
+       &&      !def->df_initialized
+       &&      def->df_firstbrace != 0
+       &&      def->df_minlevel != level
+       ) {
+               register int diff = def->df_minlevel - level;
+
+               def_warning(def,
+                       "local %s could be declared %d level%s deeper",
+                       idf->id_text, diff, (diff == 1 ? "" : "s")
+               );
+       }
+}
+
+lint_global_level(stl)
+       struct stack_level *stl;
+{
+       register struct stack_entry *se = stl->sl_entry;
+
+       ASSERT(level == L_GLOBAL);
+       while (se) {
+               register struct idf *idf = se->se_idf;
+               register struct def *def = idf->id_def;
+
+               if (def) {
+                       lint_1_global(idf, def);
+               }
+               se = se->next;
+       }
+}
+
+lint_1_global(idf, def)
+       struct idf *idf;
+       struct def *def;
+{
+       register int sc = def->df_sc;
+       register int fund = def->df_type->tp_fund;
+
+       switch (sc) {
+       case STATIC:
+       case EXTERN:
+       case GLOBAL:
+       case IMPLICIT:
+               if (fund == ERRONEOUS)
+                       break;
+
+               if (def->df_set || def->df_used) {
+                       /* Output a line to the intermediate file for
+                        * used external variables (including functions)
+                        */
+                       output_use(idf);
+               }
+               else {
+                       if (sc == STATIC) {
+                               if (def->df_set) {
+                                       def_warning(def,
+                                               "%s %s %s set but not used",
+                                               symbol2str(sc),
+                                               symbol2str(fund),
+                                               idf->id_text);
+                               }
+                               else {
+                                       def_warning(def,
+                                               "%s %s %s not used anywhere",
+                                               symbol2str(sc),
+                                               symbol2str(fund),
+                                               idf->id_text);
+                               }
+                       }
+                       if (loptions['x']) {
+                               register char *fn = def->df_file;
+
+                               if (    (sc == EXTERN || sc == GLOBAL)
+                               &&      def->df_alloc == 0
+                               &&      !def->df_set
+                               &&      !def->df_initialized
+                               &&      strcmp(&fn[strlen(fn)-2], ".c") == 0
+                               ) {
+                                       def_warning(def,
+                                               "%s %s %s not used anywhere",
+                                               symbol2str(sc),
+                                               symbol2str(fund),
+                                               idf->id_text);
+                               }
+                       }
+               }
+               break;
+       }
+}
+
+change_state(idf, to_state)
+       struct idf *idf;
+{
+/* Changes the state of the variable identified by idf in the current state
+ * on top of the stack.
+ * For non-automatic variables, the fields in the def-descriptor are set too.
+ */
+       register struct def *def = idf->id_def;
+       register struct auto_def *a = top_ls->ls_current->st_auto_list;
+
+       if (def) {
+               if (to_state == SET)
+                       def->df_set = 1;
+               else
+                       def->df_used = 1;
+
+               if (def->df_firstbrace == 0) {
+                       def->df_firstbrace = brace_count;
+                       def->df_minlevel = level;
+               }
+               else {
+                       register struct brace *br = top_br;
+
+                       /*      find the smallest brace range from which
+                               firstbrace is visible
+                       */
+                       while (br && br->br_count > def->df_firstbrace) {
+                               br = br->next;
+                       }
+                       ASSERT(br && def->df_minlevel >= br->br_level);
+                       def->df_minlevel = br->br_level;
+               }
+       }
+
+       while(a && a->ad_idf != idf)
+               a = a->next;
+       if (a == 0)     /* identifier not in list */
+               return;
+
+       if (to_state == SET) {
+               a->ad_maybe_set = 0;
+               a->ad_set = 1;
+               return;
+       }
+       /* else to_state == USED */
+       if (!a->ad_set) {
+               warning("%s%s uninitialized", idf->id_text,
+                       (a->ad_maybe_set ? " possibly" : "")
+               );
+               a->ad_maybe_set = 0;
+               a->ad_set = 1;  /* one warning */
+       }
+       a->ad_used = 1;
+}
+
+extern struct stack_level *local_level;
+
+add_auto(idf)  /* to current state on top of lint_stack */
+       struct idf *idf;
+{
+/* Check if idf's definition is really an auto (or register).
+ * It could be a static or extern too.
+ * Watch out for register formal parameters.
+ */
+       register struct def *def = idf->id_def;
+       register struct auto_def *a;
+
+       if (!def)
+               return;
+       switch (def->df_sc) {
+       case AUTO:
+       case REGISTER:
+               if (def->df_level < L_LOCAL)
+                       return;         /* a register formal */
+               a = new_auto_def();
+               a->ad_idf = idf;
+               a->ad_def = idf->id_def;
+               a->ad_used = def->df_used;
+               a->ad_set = def->df_set;
+               a->next = top_ls->ls_current->st_auto_list;
+               top_ls->ls_current->st_auto_list = a;
+       }
+}
+
+check_autos()
+{
+/* Before leaving a block remove the auto_defs of the automatic
+ * variables on this level and check if they are used
+ */
+       register struct auto_def *a1 = top_ls->ls_current->st_auto_list;
+       register struct auto_def *a2;
+
+       if (a1 && a1->ad_def->df_level > level) {
+               crash("(check_autos) corrupt level in st_auto_list");
+               /*NOTREACHED*/
+       }
+       while (a1 && a1->ad_def->df_level == level) {
+               a2 = a1;
+               a1 = a1->next;
+               if (!a2->ad_used) {
+                       if (a2->ad_set || a2->ad_maybe_set) {
+                               def_warning(a2->ad_def,
+                                       "%s set but not used in function %s",
+                                       a2->ad_idf->id_text, func_name);
+                       }
+                       else {
+                               def_warning(a2->ad_def,
+                                       "%s neither set nor used in function %s",
+                                       a2->ad_idf->id_text, func_name);
+                       }
+               }
+               free_auto_def(a2);
+       }
+       top_ls->ls_current->st_auto_list = a1;
+}
+
+check_args_used()
+{
+       register struct stack_entry *se = local_level->sl_entry;
+       extern int f_ARGSUSED;
+
+       if (level != L_FORMAL1) {
+               crash("(check_args_used) invalid level %d", level);
+               /*NOTREACHED*/
+       }
+       while (se) {
+               register struct def *def = se->se_idf->id_def;
+
+               if (def && !def->df_used && !loptions['v'] && !f_ARGSUSED) {
+                       def_warning(def, "argument %s not used in function %s",
+                                       se->se_idf->id_text, func_name);
+               }
+               se = se->next;
+       }
+}
+
+struct auto_def *
+copy_st_auto_list(from_al, lvl)
+       struct auto_def *from_al;
+{
+       struct auto_def *start = 0;
+       register struct auto_def **hook = &start;
+
+       while (from_al && from_al->ad_def->df_level > lvl) {
+               from_al = from_al->next;
+       }
+       while (from_al) {
+               register struct auto_def *a = new_auto_def();
+
+               *hook = a;
+               *a = *from_al;
+               hook = &a->next;
+               from_al = from_al->next;
+       }
+
+       return(start);
+}
+
+free_st_auto_list(au)
+       register struct auto_def *au;
+{
+       register struct auto_def *a;
+
+       while (au) {
+               a = au;
+               au = au->next;
+               free_auto_def(a);
+       }
+}
+
+struct state *
+copy_state(from_st, lvl)
+       struct state *from_st;
+{
+/* Memory for the struct state and the struct auto_defs is allocated
+ * by this function
+ */
+       register struct state *st = new_state();
+
+       st->st_auto_list = copy_st_auto_list(from_st->st_auto_list, lvl);
+       st->st_notreached = from_st->st_notreached;
+       st->st_warned = from_st->st_warned;
+       return(st);
+}
+
+static
+Free_state(stp)
+       struct state **stp;
+{
+/* This function also frees the list of auto_defs
+ */
+       free_st_auto_list((*stp)->st_auto_list);
+       free_state(*stp);
+       *stp = 0;
+}
+
+remove_settings(state, lvl)
+       struct state *state;
+{
+/* The state of all variables on this level are set to 'not set' and
+ * 'not maybe set'. (I think you have to read this twice.)
+ */
+       register struct auto_def *a = state->st_auto_list;
+
+       while (a && a->ad_def->df_level == lvl) {
+               a->ad_set = a->ad_maybe_set = 0;
+               a = a->next;
+       }
+}
+
+
+/******** M E R G E ********/
+
+/* modes for merging */
+#define        NORMAL          0
+#define        CASE_BREAK      1
+#define        USE_ONLY        2
+
+struct auto_def *
+merge_autos(a1, a2, lvl, mode)
+       struct auto_def *a1, *a2;
+       int mode;
+{
+/* Returns a pointer to the result.
+ * a1 is left unchanged.
+ * a2 is used to create this result.
+ * The fields are set as follows:
+ *     a1_set + a2_set         -> set
+ *             + a?_maybe_set  -> maybe set
+ *             ELSE            -> NOT set && NOT maybe set
+ *     *       + a?_used       -> used
+ *
+ * For mode == CASE_BREAK:
+ * First a2 is taken as the result, then
+ * variables NOT set in a2 and set or maybe set in a1 become 'maybe set'
+ *
+ * For mode == USE_ONLY:
+ * Start with a2 as the result.
+ * Variables used in a1 become used in a2.
+ * The rest of the result is not changed.
+ */
+       register struct auto_def *a;
+
+       while (a1 && a1->ad_def->df_level > lvl) {
+               a1 = a1->next;
+       }
+       while (a2 && a2->ad_def->df_level > lvl) {
+               a = a2;
+               a2 = a2->next;
+               free_auto_def(a);
+       }
+       a = a2; /* pointer to the result */
+       while (a1) {
+               if (!a2) {
+                       crash("(merge_autos) a1 longer than a2");
+                       /*NOTREACHED*/
+               }
+               if (a1->ad_idf != a2->ad_idf) {
+                       crash("(merge_autos) identifiers should be the same %s %s",
+                               a1->ad_idf->id_text, a2->ad_idf->id_text);
+                       /*NOTREACHED*/
+               }
+
+               if (a1->ad_used)
+                       a2->ad_used = 1;
+
+               if (mode != USE_ONLY) {
+                       if (    (       !a2->ad_set
+                               &&      (a1->ad_set || a1->ad_maybe_set)
+                               )
+                       ||      (       mode == NORMAL
+                               &&      !a1->ad_set
+                               &&      (a2->ad_set || a2->ad_maybe_set)
+                               )
+                       ) {
+                               a2->ad_set = 0;
+                               a2->ad_maybe_set = 1;
+                       }
+               }
+
+               a1 = a1->next;
+               a2 = a2->next;
+       }
+       if (a2) {
+               crash("(merge_autos) a2 longer than a1");
+               /*NOTREACHED*/
+       }
+       return(a);
+}
+
+merge_states(st1, st2, lvl, mode)
+       struct state *st1, *st2;
+       int mode;
+{
+/* st2 becomes the result.
+ * st1 is left unchanged.
+ * The resulting state is the state the program gets in if st1 OR st2
+ * becomes the state. (E.g. the states at the end of an if-part and an
+ * end-part are merged by this function.)
+ */
+       if (st1->st_notreached) {
+               if (mode == NORMAL || st2->st_notreached) {
+                       st2->st_auto_list =
+                               merge_autos(st1->st_auto_list,
+                                       st2->st_auto_list, lvl, USE_ONLY);
+               }
+       }
+       else if (st2->st_notreached) {
+               register struct auto_def *tmp = st2->st_auto_list;
+
+               st2->st_auto_list = copy_st_auto_list(st1->st_auto_list, lvl);
+               st2->st_notreached = 0;
+               st2->st_warned = 0;
+               st2->st_auto_list = merge_autos(tmp, st2->st_auto_list,
+                                                       lvl, USE_ONLY);
+               free_st_auto_list(tmp);
+       }
+       else {
+               st2->st_auto_list =
+                       merge_autos(st1->st_auto_list, st2->st_auto_list,
+                               lvl, mode);
+       }
+}
+
+
+/******** L I N T   S T A C K   S E A R C H I N G ********/
+
+/* The next four find-functions search the lint_stack for an entry.
+ * The letters mean : w: WHILE; d: DO; f: FOR; s: SWITCH; c: CASE.
+ */
+
+struct lint_stack_entry *
+find_wdf()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse != &stack_bottom) {
+               switch (lse->ls_class)
+               case WHILE:
+               case DO:
+               case FOR:
+                       return(lse);
+               lse = lse->ls_previous;
+       }
+       return(0);
+}
+
+struct lint_stack_entry *
+find_wdfc()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse != &stack_bottom) {
+               switch (lse->ls_class)
+               case WHILE:
+               case DO:
+               case FOR:
+               case CASE:
+                       return(lse);
+               lse = lse->ls_previous;
+       }
+       return(0);
+}
+
+struct lint_stack_entry *
+find_cs()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse != &stack_bottom) {
+               switch (lse->ls_class)
+               case CASE:
+               case SWITCH:
+                       return(lse);
+               lse = lse->ls_previous;
+       }
+       return(0);
+}
+
+/******** A C T I O N S ********/
+
+start_if_part()
+{
+/* Push a new stack entry on the lint_stack with class == IF
+ * copy the ls_current to the top of this stack
+ */
+       register struct lint_stack_entry *lse = new_lint_stack_entry();
+
+       lse->ls_class = IF;
+       lse->ls_current = copy_state(top_ls->ls_current, level);
+       lse->ls_level = level;
+       lint_push(lse);
+}
+
+start_else_part()
+{
+/* Move ls_current to LS_IF_STATE
+ * ls_current of the stack entry one below is copied to ls_current.
+ */
+       if (s_NOTREACHED) {
+               top_ls->ls_current->st_notreached = 1;
+               s_NOTREACHED = 0;
+       }
+       top_ls->LS_IF_STATE = top_ls->ls_current;
+       /* this is the reason why ls_current is a pointer */
+       top_ls->ls_current = copy_state(top_ls->ls_previous->ls_current,
+                                                               level);
+       top_ls->ls_level = level;
+}
+
+end_if_else_stmt()
+{
+       Free_state(&top_ls->ls_previous->ls_current);
+       merge_states(top_ls->LS_IF_STATE, top_ls->ls_current,
+                                       top_ls->ls_level, NORMAL);
+       Free_state(&top_ls->LS_IF_STATE);
+       top_ls->ls_previous->ls_current = top_ls->ls_current;
+       lint_pop();
+}
+
+end_if_stmt()
+{
+/* No else-part met; merge ls_current with ls_current of previous
+ * stack entry
+ */
+       merge_states(top_ls->ls_current, top_ls->ls_previous->ls_current,
+                                               top_ls->ls_level, NORMAL);
+       Free_state(&top_ls->ls_current);
+       lint_pop();
+}
+
+start_loop_stmt(looptype, const, cond)
+{
+/* If const, the condition is constant and given in cond */
+       register struct lint_stack_entry *lse = new_lint_stack_entry();
+
+       lse->ls_class = looptype;
+       lse->ls_current = copy_state(top_ls->ls_current, level);
+       lse->ls_level = level;
+       if (const && !cond) {
+               /* while (0) | for (;0;) */
+               hwarning("condition in %s statement is constant",
+                                               symbol2str(looptype));
+               lse->ls_current->st_notreached = 1;
+       }
+       if (const && cond) {
+               /* while (1) | for (;;) | do */
+               /*      omitting the copy for LS_END will force this loop
+                       to be treated as a do loop
+               */
+               top_ls->ls_current->st_notreached = 1;
+       }
+       else {
+               lse->LS_END = copy_state(top_ls->ls_current, level);
+       }
+       lint_push(lse);
+}
+
+end_loop_stmt()
+{
+       register struct lint_stack_entry *prev_ls = top_ls->ls_previous;
+
+       lint_continue_stmt();
+       top_ls->LS_END->st_notreached = prev_ls->ls_current->st_notreached;
+       top_ls->LS_END->st_warned = prev_ls->ls_current->st_warned;
+       Free_state(&top_ls->ls_current);
+       Free_state(&prev_ls->ls_current);
+       prev_ls->ls_current = top_ls->LS_END;
+       lint_pop();
+}
+
+end_do_stmt(const, cond)
+{
+       end_loop_stmt();
+       if (const)
+               hwarning("constant do condition");
+       if (const && cond && top_ls->ls_current->st_notreached) {
+               /* no break met; this is really an endless loop */
+       }
+       else {
+               top_ls->ls_current->st_notreached = 0;
+       }
+}
+
+cont_break_merge(lse)
+       struct lint_stack_entry *lse;
+{
+       /* merge for continue and break statements */
+       if (lse->LS_END) {
+               merge_states(top_ls->ls_current, lse->LS_END,
+                                               lse->ls_level, NORMAL);
+       }
+       else {
+               lse->LS_END = copy_state(top_ls->ls_current, lse->ls_level);
+       }
+}
+
+lint_continue_stmt()
+{
+       register struct lint_stack_entry *lse = find_wdf();
+
+       if (!lse)
+               return;         /* not inside a loop statement */
+
+       cont_break_merge(lse);
+       top_ls->ls_current->st_notreached = 1;
+}
+
+start_switch_part()
+{
+/* ls_current of a SWITCH entry has different meaning from ls_current of
+ * other entries. It keeps track of which variables are used in all
+ * following case parts. (Needed for variables declared in a compound
+ * switch-block.)
+ */
+       register struct lint_stack_entry *lse = new_lint_stack_entry();
+
+       lse->ls_class = SWITCH;
+       lse->ls_current = copy_state(top_ls->ls_current, level);
+       lse->ls_level = level;
+       lse->LS_CASE = copy_state(top_ls->ls_current, level);
+       lse->ls_current->st_notreached = 1;
+       top_ls->ls_current->st_notreached = 1;
+       lint_push(lse);
+}
+
+end_switch_stmt()
+{
+       if (top_ls->ls_class == CASE) {
+               /* no break after last case or default */
+               lint_break_stmt();      /* introduce break */
+       }
+
+       if (!top_ls->LS_DEFAULT_MET) {
+               top_ls->ls_current->st_notreached = 0;
+               if (top_ls->LS_BREAK) {
+                       merge_states(top_ls->ls_current, top_ls->LS_BREAK,
+                                               top_ls->ls_level, NORMAL);
+                       Free_state(&top_ls->ls_current);
+               }
+               else {
+                       top_ls->LS_BREAK = top_ls->ls_current;
+               }
+       }
+       else {
+               Free_state(&top_ls->ls_current);
+       }
+
+       if (top_ls->LS_BREAK) {
+               merge_states(top_ls->LS_CASE, top_ls->LS_BREAK,
+                                               top_ls->ls_level, CASE_BREAK);
+               Free_state(&top_ls->LS_CASE);
+       }
+       else {
+               top_ls->LS_BREAK = top_ls->LS_CASE;
+       }
+
+       top_ls->LS_BREAK->st_notreached =
+                       top_ls->ls_previous->ls_current->st_notreached;
+                               /* yack */
+       Free_state(&top_ls->ls_previous->ls_current);
+
+       if (!top_ls->LS_DEFAULT_MET)
+               top_ls->LS_BREAK->st_notreached = 0;
+       top_ls->ls_previous->ls_current = top_ls->LS_BREAK;
+
+       lint_pop();
+}
+
+lint_case_stmt(dflt)
+{
+/* A default statement is just a special case statement */
+
+       register struct lint_stack_entry *lse;
+       register struct lint_stack_entry *cs_entry = find_cs();
+
+       if (!cs_entry)
+               return;         /* not inside switch */
+       if (cs_entry != top_ls) {
+               warning("%s statement in strange context",
+                       dflt ? "default" : "case");
+               return;
+       }
+       if (cs_entry->ls_class == SWITCH) {
+               if (dflt) {
+                       cs_entry->LS_DEFAULT_MET = 1;
+               }
+               lse = new_lint_stack_entry();
+               lse->ls_class = CASE;
+               lse->ls_current = copy_state(top_ls->ls_current, level);
+               remove_settings(lse->ls_current, level);
+               lse->ls_level = level;
+               lint_push(lse);
+       }
+       else {
+               ASSERT(cs_entry->ls_class == CASE);
+               if (dflt) {
+                       cs_entry->ls_previous->LS_DEFAULT_MET = 1;
+               }
+               merge_states(top_ls->ls_current, top_ls->ls_previous->LS_CASE,
+                               top_ls->ls_previous->ls_level, NORMAL);
+               merge_states(top_ls->ls_current,
+                               top_ls->ls_previous->ls_current,
+                               top_ls->ls_previous->ls_level, NORMAL);
+               Free_state(&top_ls->ls_current);
+               top_ls->ls_current =
+                       copy_state(top_ls->ls_previous->ls_current,
+                                       top_ls->ls_previous->ls_level);
+               remove_settings(top_ls->ls_current, top_ls->ls_level);
+       }
+}
+
+lint_break_stmt()
+{
+       register struct lint_stack_entry *lse = find_wdfc();
+
+       if (!lse)
+               return;
+
+       switch (lse->ls_class) {
+       case WHILE:
+       case FOR:
+       case DO:
+               /* loop break */
+               lse->ls_previous->ls_current->st_notreached = 0;
+               cont_break_merge(lse);
+               break;
+
+       case CASE:
+               /* case break */
+               if (!top_ls->ls_current->st_notreached) {
+                       lse->ls_previous->ls_previous->ls_current->st_notreached = 0;
+               }
+               merge_states(lse->ls_current, lse->ls_previous->ls_current,
+                                       lse->ls_previous->ls_level, NORMAL);
+               if (lse->ls_previous->LS_BREAK) {
+                       merge_states(top_ls->ls_current, lse->ls_previous->LS_BREAK,
+                                       lse->ls_previous->ls_level, NORMAL);
+               }
+               else {
+                       lse->ls_previous->LS_BREAK = copy_state(top_ls->ls_current,
+                                                lse->ls_previous->ls_level);
+               }
+               if (lse == top_ls) {
+                       Free_state(&lse->ls_current);
+                       lint_pop();
+               }
+               break;
+       default:
+               /* bad break */
+               crash("find_wdfc() returned invalid entry");
+               /*NOTREACHED*/
+       }
+       top_ls->ls_current->st_notreached = 1;
+}
+
+lint_start_function()
+{
+       lint_return_stmt(-1);   /* initialization */
+       move_ARG2f();
+       move_VAR2f();
+}
+
+lint_end_function()
+{
+       extern struct outdef OutDef;
+       register int fund = func_type->tp_fund;
+
+       if (    OutDef.od_valreturned == NOVALRETURNED
+       &&      !func_notypegiven
+       &&      fund != VOID
+       ) {
+               warning("function %s declared %s%s but no value returned",
+                       func_name,
+                       (func_type->tp_unsigned && fund != POINTER) ?
+                               "unsigned " : "",
+                        symbol2str(fund)
+               );
+       }
+       /* write the function definition record */
+       outdef();
+
+       /* At this stage it is possible that stack_bottom.ls_current is
+        * pointing to a state with a list of auto_defs.
+        * These auto_defs must be freed and the state must be filled
+        * with zeros.
+        */
+       if (top_ls != &stack_bottom) {
+               crash("(lint_end_function) top_ls != &stack_bottom");
+               /*NOTREACHED*/
+       }
+       if (top_ls->ls_current->st_auto_list != 0)
+               free_st_auto_list(top_ls->ls_current->st_auto_list);
+       top_ls->ls_current->st_auto_list = 0;
+       top_ls->ls_current->st_notreached = 0;
+       top_ls->ls_current->st_warned = 0;
+}
+
+lint_return_stmt(e)
+       int e;
+{
+/* The statics of this function are initialized by calling it with e = -1. */
+
+       static int ret_e;
+                               /*-1    no return met yet
+                                * 0    return; met
+                                * 1    return with expression met
+                                */
+       static int warned;
+
+       switch (e) {
+       case -1:
+               ret_e = -1;
+               warned = 0;
+               return;
+       case 0:
+               if (top_ls->ls_current->st_notreached)
+                       break;
+               if (ret_e == 1 && !warned) {
+                       warning("function %s does not always return a value",
+                               func_name);
+                       warned = 1;
+               }
+               else
+                       ret_e = 0;
+               break;
+       case 1:
+               if (top_ls->ls_current->st_notreached)
+                       break;
+               if (ret_e == 0 && !warned) {
+                       warning("function %s does not always return a value",
+                               func_name);
+                       warned = 1;
+               }
+               else
+                       ret_e = 1;
+               break;
+       }
+       if (!top_ls->ls_current->st_notreached)
+               set_od_valreturned(e);
+       top_ls->ls_current->st_notreached = 1;
+}
+
+lint_jump_stmt(idf)
+       struct idf *idf;
+{
+       top_ls->ls_current->st_notreached = 1;
+       if (!idf->id_def)
+               return;
+       idf->id_def->df_used = 1;
+}
+
+lint_label()
+{
+/*     When meeting a label, we should take the intersection of all
+       settings at all goto's leading this way, but this cannot reasonably
+       be done.  So we assume that the user knows what he is doing and set
+       all automatic variables to set.
+*/
+       register struct auto_def *a = top_ls->ls_current->st_auto_list;
+
+       hwarning("all auto variables assumed initialized at label");
+       while (a) {
+               a->ad_maybe_set = 0;
+               a->ad_set = 1;
+               a = a->next;
+       }
+}
+
+lint_statement()
+{
+/* Check if this statement can be reached
+ */
+       if (s_NOTREACHED) {
+               top_ls->ls_current->st_notreached = 1;
+               s_NOTREACHED = 0;
+       }
+       if (DOT == '{' || DOT == ';')
+               return;
+       if (top_ls->ls_current->st_warned)
+               return;
+       if (top_ls->ls_current->st_notreached) {
+               if (DOT != CASE && DOT != DEFAULT && AHEAD != ':') {
+                       if (DOT != BREAK || !loptions['b'])
+                               warning("statement cannot be reached");
+                       top_ls->ls_current->st_warned = 1;
+               }
+               else {
+                       top_ls->ls_current->st_notreached = 0;
+                       top_ls->ls_current->st_warned = 0;
+               }
+       }
+}
+
+lint_push(lse)
+       struct lint_stack_entry *lse;
+{
+       lse->ls_previous = top_ls;
+       top_ls->next = lse;
+       top_ls = lse;
+}
+
+lint_pop()
+{
+       top_ls = top_ls->ls_previous;
+       free_lint_stack_entry(top_ls->next);
+}
+
+
+/* FOR DEBUGGING */
+
+print_lint_stack()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse) {
+               print("  |-------------- level %d ------------\n",
+                                       lse->ls_level);
+               print("  |cur: ");
+               if (lse->ls_current) {
+                       print_autos(lse->ls_current->st_auto_list);
+                       print("  |st_notreached == %d\n",
+                               lse->ls_current->st_notreached);
+               }
+               else
+                       print("\n");
+               print("  |class == %s\n",
+                       lse->ls_class ? symbol2str(lse->ls_class) : "{");
+               switch (lse->ls_class) {
+               case SWITCH:
+                       print("  |LS_BREAK: ");
+                       if (lse->LS_BREAK) {
+                               print_autos(lse->LS_BREAK->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_BREAK->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       print("  |LS_CASE:  ");
+                       if (lse->LS_CASE) {
+                               print_autos(lse->LS_CASE->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_CASE->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       break;
+               case DO:
+               case WHILE:
+               case FOR:
+                       print("  |LS_END:  ");
+                       if (lse->LS_END) {
+                               print_autos(lse->LS_END->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_END->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       break;
+               case IF:
+                       print("  |LS_IF_STATE: ");
+                       if (lse->LS_IF_STATE) {
+                               print_autos(lse->LS_IF_STATE->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_IF_STATE->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       break;
+               default:
+                       break;
+               }
+               lse = lse->ls_previous;
+       }
+       print("  |--------------\n\n");
+}
+
+static
+print_autos(a)
+       register struct auto_def *a;
+{
+       while (a) {
+               print("%s", a->ad_idf->id_text);
+               print("(l=%d)", a->ad_def->df_level);
+               print("(U%dS%dM%d) ", a->ad_used, a->ad_set, a->ad_maybe_set);
+               a = a->next;
+       }
+       print("\n");
+}
+#endif LINT
index 71b520b..b8104bf 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /* MAIN PROGRAM */
 
+#include       "lint.h"
 #include       "nofloat.h"
 #include       <system.h>
 #include       "nopp.h"
@@ -95,6 +96,9 @@ main(argc, argv)
        inc_max = 10;
 
        init_pp();      /* initialise the preprocessor macros   */
+#ifdef LINT
+       lint_init();
+#endif LINT
 #endif NOPP
 
        /*      Note: source file "-" indicates that the source is supplied
@@ -130,7 +134,10 @@ compile(argc, argv)
        char *argv[];
 {
        char *result;
+#ifndef        LINT
        register char *destination = 0;
+#endif LINT
+
 #ifdef DEBUG
 #ifndef NOPP
        int pp_only = options['E'] || options['P'] || options['C'];
@@ -139,14 +146,17 @@ compile(argc, argv)
 
        switch (argc) {
        case 1:
+#ifndef        LINT
 #ifdef DEBUG
 #ifndef NOPP
                if (!pp_only)
 #endif NOPP
 #endif
                        fatal("%s: destination file not specified", prog_name);
+#endif LINT
                break;
 
+#ifndef        LINT
        case 2:
                destination = argv[1];
                break;
@@ -154,8 +164,14 @@ compile(argc, argv)
                nmlist = argv[2];
                destination = argv[1];
                break;
+#endif LINT
+
        default:
+#ifndef        LINT
                fatal("use: %s source destination [namelist]", prog_name);
+#else  LINT
+               fatal("use: %s source", prog_name);
+#endif LINT
                break;
        }
 
@@ -185,8 +201,11 @@ compile(argc, argv)
 #endif NOPP
 #endif DEBUG
        {
+#ifndef        LINT
                init_code(destination && strcmp(destination, "-") != 0 ?
                                        destination : 0);
+#endif LINT
+
                /* compile the source text                      */
                C_program();
 
index ec61dc1..e873061 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /*     U S E R   O P T I O N - H A N D L I N G         */
 
+#include       "lint.h"
 #include       "botch_free.h"
 #include       <alloc.h>
 #include       "nofloat.h"
@@ -29,6 +30,10 @@ extern int inc_total;
 #endif NOPP
 
 char options[128];                     /* one for every char   */
+#ifdef LINT
+char loptions[128];                    /* one for every char   */
+#endif LINT
+
 extern int idfsize;
 
 static int txt2int();
@@ -45,13 +50,18 @@ next_option:                        /* to allow combined one-char options */
                break;
 
        default:
+#ifndef        LINT
                fatal("illegal option: %c", opt);
+#else  LINT
+               warning("illegal option: %c", opt);
+#endif LINT
                break;
 
        case '-':
                options[*text++] = 1;   /* flags, debug options etc.    */
                goto next_option;
 
+#ifndef        LINT
 #ifdef DATAFLOW
        case 'd':
 #endif DATAFLOW
@@ -59,16 +69,28 @@ next_option:                        /* to allow combined one-char options */
        case 'L' :                      /* no fil/lin */
        case 'n':                       /* use no registers */
        case 'w':                       /* no warnings will be given */
-#ifndef        NOROPTION
-       case 'R':                       /* strict version */
-#endif
                options[opt] = 1;
                goto next_option;
-#ifdef NOROPTION
-       case 'R':
+#endif LINT
+
+#ifdef LINT
+       case 'h':       /* heuristic tests */
+       case 'v':       /* no complaints about unused arguments */
+       case 'a':       /* check long->int int->long conversions */
+       case 'b':       /* don't report unreachable break-statements */
+       case 'x':       /* complain about unused extern declared variables */
+       case 'u':       /* no "used but not defined"; for pass 2 */
+               loptions[opt] = 1;
+               goto next_option;
+#endif LINT
+
+       case 'R':                       /* strict version */
+#ifndef        NOROPTION
+               options[opt] = 1;
+#else  NOROPTION
                warning("-R option not implemented");
+#endif NOROPTION
                goto next_option;
-#endif
 
 #ifdef ___XXX___
 deleted, is now a debug-flag
@@ -180,6 +202,14 @@ deleted, is now a debug-flag
                break;
 #endif ___XXX___
 
+#ifdef LINT
+       case 'S' : {            /* -Sint :      static scope number for lint */
+               extern int stat_number;
+               stat_number = txt2int(&text);
+               break;
+       }
+#endif LINT
+
        case 'T' : {
 #ifdef USE_TMP
                extern char *C_tmpdir;
@@ -209,6 +239,7 @@ deleted, is now a debug-flag
                break;
        }
 
+#ifndef        LINT
        case 'V' :      /* set object sizes and alignment requirements  */
 #ifdef NOCROSS
                warning("-V option ignored");
@@ -294,6 +325,7 @@ deleted, is now a debug-flag
                break;
        }
 #endif NOCROSS
+#endif LINT
        }
 }
 
index ebeeada..64a1158 100644 (file)
@@ -45,6 +45,7 @@
 %start         If_expr, control_if_expression;
 
 {
+#include       "lint.h"
 #include       "nopp.h"
 #include       "arith.h"
 #include       "LLlex.h"
 #include       "code.h"
 #include       "expr.h"
 #include       "def.h"
+#ifdef LINT
+#include       "l_state.h"
+#endif LINT
+
 #ifndef NOPP
 extern arith ifval;
 #endif NOPP
@@ -121,6 +126,9 @@ external_definition
                declarator(&Dc)
                {
                        declare_idf(&Ds, &Dc, level);
+#ifdef LINT
+                       lint_ext_def(Dc.dc_idf, Ds.ds_sc);
+#endif LINT
                }
                [%if (Dc.dc_idf->id_def->df_type->tp_fund == FUNCTION)
                        /*      int i (1) {2, 3}
@@ -156,6 +164,12 @@ non_function(register struct decspecs *ds; register struct declarator *dc;)
                { code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); }
        ]
        {
+#ifdef LINT
+               if (dc->dc_idf->id_def->df_type->tp_fund == FUNCTION)
+                       def2decl(ds->ds_sc);
+               if (dc->dc_idf->id_def->df_sc != TYPEDEF)
+                       outdef();
+#endif LINT
        }
        [
                ','
@@ -171,6 +185,9 @@ function(struct decspecs *ds; struct declarator *dc;)
        }
 :
        {       register struct idf *idf = dc->dc_idf;
+#ifdef LINT
+               lint_start_function();
+#endif LINT
                init_idf(idf);
                stack_level();          /* L_FORMAL1 declarations */
                declare_params(dc);
@@ -180,11 +197,23 @@ function(struct decspecs *ds; struct declarator *dc;)
        declaration*
        {
                declare_formals(&fbytes);
+#ifdef LINT
+               lint_formals();
+#endif LINT
        }
        compound_statement
        {
                end_proc(fbytes);
+#ifdef LINT
+               lint_return_stmt(0);    /* implicit return at end of function */
+#endif LINT
                unstack_level();        /* L_FORMAL2 declarations */
+#ifdef LINT
+               check_args_used();
+#endif LINT
                unstack_level();        /* L_FORMAL1 declarations */
+#ifdef LINT
+               lint_end_function();
+#endif LINT
        }
 ;
index aee78b9..3be2dec 100644 (file)
@@ -5,6 +5,7 @@
 /* $Header$ */
 /*     S T A C K / U N S T A C K  R O U T I N E S      */
 
+#include       "lint.h"
 #include       "nofloat.h"
 #include       <system.h>
 #include       <em.h>
@@ -51,6 +52,9 @@ stack_level() {
        stl->sl_level = ++level;
        stl->sl_max_block = loclev->sl_max_block;
        local_level = stl;
+#ifdef LINT
+       lint_start_local();
+#endif LINT
 }
 
 stack_idf(idf, stl)
@@ -96,6 +100,10 @@ unstack_level()
                dumpidftab("before unstackidfs", 0);
 #endif DEBUG
 
+#ifdef LINT
+       lint_local_level(local_level);
+#endif LINT
+
        /*      The implementation below is more careful than strictly
                necessary. Optimists may optimize it afterwards.
        */
@@ -168,6 +176,10 @@ unstack_world()
        */
        register struct stack_entry *se = local_level->sl_entry;
 
+#ifdef LINT
+       lint_global_level(local_level);
+#endif LINT
+
        open_name_list();
 
        while (se)      {
index 05e4eb2..6014736 100644 (file)
@@ -8,6 +8,7 @@
 {
 #include       <em.h>
 
+#include       "lint.h"
 #include       "debug.h"
 #include       "botch_free.h"
 
 #include       "code.h"
 #include       "stack.h"
 #include       "def.h"
+#ifdef LINT
+#include       "l_lint.h"
+#include       "l_state.h"
+#endif LINT
+
 extern int level;
 }
 
@@ -31,6 +37,9 @@ extern int level;
 /* 9 */
 statement
        {
+#ifdef LINT
+               lint_statement();
+#endif LINT
        }
 :
 %if (AHEAD != ':')
@@ -57,12 +66,18 @@ statement
        BREAK
        {
                code_break();
+#ifdef LINT
+               lint_break_stmt();
+#endif LINT
        }
        ';'
 |
        CONTINUE
        {
                code_continue();
+#ifdef LINT
+               lint_continue_stmt();
+#endif LINT
        }
        ';'
 |
@@ -104,6 +119,9 @@ label
                                        grz: printf("A labelled statement\n");
                                }
                */
+#ifdef LINT
+               lint_label();
+#endif LINT
                define_label(idf);
                C_df_ilb((label)idf->id_def->df_address);
        }
@@ -126,6 +144,9 @@ if_statement
                                /*      The comparison has been optimized
                                        to a 0 or 1.
                                */
+#ifdef LINT
+                               hwarning("condition in if is constant");
+#endif LINT
                                if (expr->VL_VALUE == (arith)0) {
                                        C_bra(l_false);
                                }
@@ -136,21 +157,33 @@ if_statement
                                C_df_ilb(l_true);
                        }
                        free_expression(expr);
+#ifdef LINT
+                       start_if_part();
+#endif LINT
                }
        ')'
        statement
        [%prefer
                ELSE
                        {
+#ifdef LINT
+                               start_else_part();
+#endif LINT
                                C_bra(l_end);
                                C_df_ilb(l_false);
                        }
                statement
                        {       C_df_ilb(l_end);
+#ifdef LINT
+                               end_if_else_stmt();
+#endif LINT
                        }
        |
                empty
                        {       C_df_ilb(l_false);
+#ifdef LINT
+                               end_if_stmt();
+#endif LINT
                        }
        ]
 ;
@@ -176,10 +209,17 @@ while_statement
                                if (expr->VL_VALUE == (arith)0) {
                                        C_bra(l_break);
                                }
+#ifdef LINT
+                               start_loop_stmt(WHILE, 1,
+                                       expr->VL_VALUE != (arith)0);
+#endif LINT
                        }
                        else    {
                                code_expr(expr, RVAL, TRUE, l_body, l_break);
                                C_df_ilb(l_body);
+#ifdef LINT
+                               start_loop_stmt(WHILE, 0, 0);
+#endif LINT
                        }
                }
        ')'
@@ -189,6 +229,9 @@ while_statement
                        C_df_ilb(l_break);
                        unstack_stmt();
                        free_expression(expr);
+#ifdef LINT
+                       end_loop_stmt();
+#endif LINT
                }
 ;
 
@@ -202,6 +245,9 @@ do_statement
        DO
                {       C_df_ilb(l_body);
                        stack_stmt(l_break, l_continue);
+#ifdef LINT
+                       start_loop_stmt(DO, 1, 1);
+#endif LINT
                }
        statement
        WHILE
@@ -215,9 +261,15 @@ do_statement
                                if (expr->VL_VALUE == (arith)1) {
                                        C_bra(l_body);
                                }
+#ifdef LINT
+                               end_do_stmt(1, expr->VL_VALUE != (arith)0);
+#endif LINT
                        }
                        else    {
                                code_expr(expr, RVAL, TRUE, l_body, l_break);
+#ifdef LINT
+                               end_do_stmt(0, 0);
+#endif LINT
                        }
                        C_df_ilb(l_break);
                }
@@ -235,6 +287,9 @@ for_statement
                label l_continue = text_label();
                label l_body = text_label();
                label l_test = text_label();
+#ifdef LINT
+               int const = 1, cond = 1;        /* the default case */
+#endif LINT
        }
 :
        FOR
@@ -257,10 +312,17 @@ for_statement
                                if (e_test->VL_VALUE == (arith)0)       {
                                        C_bra(l_break);
                                }
+#ifdef LINT
+                               const = 1,
+                                       cond = e_test->VL_VALUE != (arith)0;
+#endif LINT
                        }
                        else    {
                                code_expr(e_test, RVAL, TRUE, l_body, l_break);
                                C_df_ilb(l_body);
+#ifdef LINT
+                               const = 0, cond = 0;
+#endif LINT
                        }
                }
        ]?
@@ -268,9 +330,15 @@ for_statement
        expression(&e_incr)?
        ')'
                {
+#ifdef LINT
+                       start_loop_stmt(FOR, const, cond);
+#endif LINT
                }
        statement
                {
+#ifdef LINT
+                       end_loop_stmt();
+#endif LINT
                        C_df_ilb(l_continue);
                        if (e_incr)
                                code_expr(e_incr, RVAL, FALSE,
@@ -294,10 +362,22 @@ switch_statement
        expression(&expr)
                {
                        code_startswitch(&expr);
+#ifdef LINT
+                       start_switch_part();
+                       /* the following is a trick to detect a constant
+                        * expression in a switch
+                        */
+                       opnd2test(&expr, SWITCH);
+                       if (is_cp_cst(expr))
+                               hwarning("switch value is constant");
+#endif LINT
                }
        ')'
        statement
                {
+#ifdef LINT
+                       end_switch_stmt();
+#endif LINT
                        code_endswitch();
                        free_expression(expr);
                }
@@ -311,6 +391,9 @@ case_statement
        CASE
        constant_expression(&expr)
                {
+#ifdef LINT
+                       lint_case_stmt(0);
+#endif LINT
                        code_case(expr);
                        free_expression(expr);
                }
@@ -322,6 +405,9 @@ default_statement
 :
        DEFAULT
                {
+#ifdef LINT
+                       lint_case_stmt(1);
+#endif LINT
                        code_default();
                }
        ':'
@@ -336,13 +422,23 @@ return_statement
        [
                expression(&expr)
                {
+#ifdef LINT
+                       lint_ret_conv(expr->ex_type);
+#endif LINT
+
                        do_return_expr(expr);
                        free_expression(expr);
+#ifdef LINT
+                       lint_return_stmt(1);
+#endif LINT
                }
        |
                empty
                {
                        do_return();
+#ifdef LINT
+                       lint_return_stmt(0);
+#endif LINT
                }
        ]
        ';'
@@ -358,6 +454,9 @@ jump
                {
                        apply_label(idf);
                        C_bra((label)idf->id_def->df_address);
+#ifdef LINT
+                       lint_jump_stmt(idf);
+#endif LINT
                }
 ;
 
index 5426fcc..b51cf68 100644 (file)
@@ -16,6 +16,7 @@
 #include       <alloc.h>
 #include       <em_mes.h>
 
+#include       "lint.h"
 #include       "util.h"
 #include       "use_tmp.h"
 #include       "regcount.h"
@@ -224,6 +225,7 @@ StoreLocal(off, sz)
        }
 }
 
+#ifndef        LINT
 AddrLocal(off)
        arith off;
 {
@@ -232,3 +234,4 @@ AddrLocal(off)
        if (p) p->t_regtype = -1;
        C_lal(off);
 }
+#endif LINT