lint update (merge from C compiler)
authordick <none@none>
Fri, 7 Dec 1990 14:42:26 +0000 (14:42 +0000)
committerdick <none@none>
Fri, 7 Dec 1990 14:42:26 +0000 (14:42 +0000)
23 files changed:
lang/cem/cemcom.ansi/.distr
lang/cem/cemcom.ansi/LintPars
lang/cem/cemcom.ansi/Makefile
lang/cem/cemcom.ansi/ch3bin.c
lang/cem/cemcom.ansi/code.c
lang/cem/cemcom.ansi/declar.g
lang/cem/cemcom.ansi/def.str
lang/cem/cemcom.ansi/error.c
lang/cem/cemcom.ansi/idf.c
lang/cem/cemcom.ansi/ival.g
lang/cem/cemcom.ansi/l_em.h [new file with mode: 0644]
lang/cem/cemcom.ansi/l_ev_ord.c
lang/cem/cemcom.ansi/l_lint.c
lang/cem/cemcom.ansi/l_misc.c
lang/cem/cemcom.ansi/l_outdef.c
lang/cem/cemcom.ansi/l_state.str
lang/cem/cemcom.ansi/l_states.c
lang/cem/cemcom.ansi/main.c
lang/cem/cemcom.ansi/program.g
lang/cem/cemcom.ansi/stack.c
lang/cem/cemcom.ansi/statement.g
lang/cem/cemcom.ansi/switch.c
lang/cem/cemcom.ansi/util.c

index a922449..f131817 100644 (file)
@@ -56,7 +56,7 @@ l_brace.str
 l_class.h
 l_comment.h
 l_comment.c
-l_dummy.c
+l_em.h
 l_ev_ord.c
 l_lint.c
 l_lint.h
index 27f6151..46f66e2 100644 (file)
@@ -1,5 +1,6 @@
 !File: lint.h
 #define        LINT            1       /* if defined, 'lint' is produced       */
+#define        ANSI            1       /* tell l_* files it's ANSI             */
 
 
 !File: pathlength.h
@@ -22,7 +23,8 @@
 
 
 !File: nparams.h
-#define        NPARAMS 32      /* maximum number of parameters of macros       */
+#define        NPARAMS 32      /* maximum number of parameters                 */
+#define        STDC_NPARAMS 31 /* ANSI limit on number of parameters           */
 
 
 !File: ifdepth.h
 #define        DENSITY 2       /* see switch.[ch] for an explanation           */
 
 
-!File: lapbuf.h
-#define        LAPBUF  4096    /* size of macro actual parameter buffer        */
+!File: macbuf.h
+#define        LAPBUF  128     /* initial size of macro replacement buffer     */
+#define ARGBUF 128     /* initial size of macro parameter buffer(s)    */
 
 
 !File: strsize.h
 #define ISTRSIZE       32      /* minimum number of bytes allocated for
                                        storing a string                */
-#define RSTRSIZE             /* step size in enlarging the memory for
+#define RSTRSIZE       16      /* step size in enlarging the memory for
                                        the storage of a string         */
 
 
@@ -56,6 +59,7 @@
 #define        SZ_FLOAT        4
 #define        SZ_DOUBLE       8
 #define        SZ_POINTER      4
+#define        SZ_LNGDBL       8       /* for now */
 
 /* target machine alignment requirements       */
 #define        AL_CHAR         1
@@ -65,6 +69,7 @@
 #define        AL_LONG         SZ_WORD
 #define        AL_FLOAT        SZ_WORD
 #define        AL_DOUBLE       SZ_WORD
+#define        AL_LNGDBL       SZ_WORD
 #define        AL_POINTER      SZ_WORD
 #define AL_STRUCT      1
 #define AL_UNION       1
 
 
 !File: textsize.h
-#define ITEXTSIZE       16     /* 1st piece of memory for repl. text   */
+#define ITEXTSIZE       32     /* 1st piece of memory for repl. text   */
 
 
 !File: inputtype.h
 !File: spec_arith.h
 /* describes internal compiler arithmetics */
 #undef SPECIAL_ARITHMETICS     /* something different from native long */
+#undef UNSIGNED_ARITH  unsigned arith
 
 
 !File: static.h
index df5dda2..7dea883 100644 (file)
@@ -84,7 +84,7 @@ CSRC =        main.c idf.c declarator.c decspecs.c struct.c \
        skip.c stack.c type.c ch3mon.c label.c eval.c \
        switch.c conversion.c util.c proto.c \
        pragma.c blocks.c dataflow.c Version.c stab.c\
-       l_lint.c l_states.c l_misc.c l_ev_ord.c l_outdef.c l_comment.c l_dummy.c
+       l_lint.c l_states.c l_misc.c l_ev_ord.c l_outdef.c l_comment.c
 COBJ = main.o idf.o declarator.o decspecs.o struct.o \
        expr.o ch3.o ch3bin.o cstoper.o fltcstoper.o arith.o \
        code.o dumpidf.o error.o field.o\
@@ -93,7 +93,7 @@ COBJ =        main.o idf.o declarator.o decspecs.o struct.o \
        skip.o stack.o type.o ch3mon.o label.o eval.o \
        switch.o conversion.o util.o proto.o \
        pragma.o blocks.o dataflow.o Version.o stab.o \
-       l_lint.o l_states.o l_misc.o l_ev_ord.o l_outdef.o l_comment.o l_dummy.o
+       l_lint.o l_states.o l_misc.o l_ev_ord.o l_outdef.o l_comment.o
 
 # Objects of other generated C files
 GCSRC =        char.c symbol2str.c next.c
@@ -123,8 +123,8 @@ GHSRC =     botch_free.h dataflow.h debug.h density.h errout.h \
        regcount.h
 
 HSRC = LLlex.h align.h arith.h assert.h atw.h class.h \
-        input.h label.h level.h mes.h sizes.h specials.h \
-        file_info.h tokenname.h l_lint.h
+        input.h interface.h label.h level.h mes.h sizes.h specials.h \
+        file_info.h tokenname.h l_em.h l_lint.h
 
 HFILES = $(HSRC) $(GHSRC) $(GHSTRSRC)
 
@@ -496,6 +496,7 @@ arith.o: sizes.h
 arith.o: spec_arith.h
 arith.o: trgt_sizes.h
 arith.o: type.h
+code.o: LLlex.h
 code.o: Lpars.h
 code.o: arith.h
 code.o: assert.h
@@ -508,6 +509,7 @@ code.o: debug.h
 code.o: declar.h
 code.o: decspecs.h
 code.o: def.h
+code.o: l_em.h
 code.o: expr.h
 code.o: file_info.h
 code.o: idf.h
@@ -549,6 +551,7 @@ error.o: LLlex.h
 error.o: arith.h
 error.o: debug.h
 error.o: def.h
+error.o: l_em.h
 error.o: errout.h
 error.o: expr.h
 error.o: file_info.h
@@ -611,6 +614,7 @@ LLmessage.o: file_info.h
 LLmessage.o: idf.h
 LLmessage.o: nopp.h
 LLmessage.o: spec_arith.h
+input.o: dbsymtab.h
 input.o: file_info.h
 input.o: input.h
 input.o: inputtype.h
@@ -621,6 +625,7 @@ domacro.o: arith.h
 domacro.o: assert.h
 domacro.o: botch_free.h
 domacro.o: class.h
+domacro.o: dbsymtab.h
 domacro.o: debug.h
 domacro.o: file_info.h
 domacro.o: idf.h
@@ -688,6 +693,7 @@ stack.o: botch_free.h
 stack.o: dbsymtab.h
 stack.o: debug.h
 stack.o: def.h
+stack.o: l_em.h
 stack.o: idf.h
 stack.o: level.h
 stack.o: lint.h
@@ -778,9 +784,11 @@ switch.o: code.h
 switch.o: dbsymtab.h
 switch.o: debug.h
 switch.o: density.h
+switch.o: l_em.h
 switch.o: expr.h
 switch.o: idf.h
 switch.o: label.h
+switch.o: lint.h
 switch.o: nobitfield.h
 switch.o: nocross.h
 switch.o: nopp.h
@@ -803,6 +811,7 @@ util.o: Lpars.h
 util.o: align.h
 util.o: debug.h
 util.o: def.h
+util.o: l_em.h
 util.o: lint.h
 util.o: nocross.h
 util.o: regcount.h
@@ -919,7 +928,6 @@ l_misc.o: Lpars.h
 l_misc.o: arith.h
 l_misc.o: code.h
 l_misc.o: dbsymtab.h
-l_misc.o: debug.h
 l_misc.o: def.h
 l_misc.o: expr.h
 l_misc.o: file_info.h
@@ -963,6 +971,8 @@ l_outdef.o: assert.h
 l_outdef.o: code.h
 l_outdef.o: dbsymtab.h
 l_outdef.o: debug.h
+l_outdef.o: declar.h
+l_outdef.o: decspecs.h
 l_outdef.o: def.h
 l_outdef.o: expr.h
 l_outdef.o: field.h
@@ -988,10 +998,6 @@ l_comment.o: l_comment.h
 l_comment.o: l_state.h
 l_comment.o: lint.h
 l_comment.o: spec_arith.h
-l_dummy.o: arith.h
-l_dummy.o: label.h
-l_dummy.o: lint.h
-l_dummy.o: spec_arith.h
 tokenfile.o: Lpars.h
 declar.o: LLlex.h
 declar.o: Lpars.h
@@ -1007,7 +1013,6 @@ 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
@@ -1028,11 +1033,11 @@ statement.o: code.h
 statement.o: dbsymtab.h
 statement.o: debug.h
 statement.o: def.h
+statement.o: l_em.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
@@ -1070,7 +1075,7 @@ program.o: def.h
 program.o: expr.h
 program.o: file_info.h
 program.o: idf.h
-program.o: l_state.h
+program.o: l_lint.h
 program.o: label.h
 program.o: lint.h
 program.o: nobitfield.h
@@ -1085,6 +1090,7 @@ ival.o: assert.h
 ival.o: dbsymtab.h
 ival.o: debug.h
 ival.o: def.h
+ival.o: l_em.h
 ival.o: estack.h
 ival.o: expr.h
 ival.o: field.h
index 0c4fe07..ce78205 100644 (file)
@@ -270,10 +270,15 @@ ch3bin(expp, oper, expr)
                break;
 
        case ',':
-               if (is_cp_cst(*expp))
+               if (is_cp_cst(*expp)) {
+#ifdef LINT
+                       hwarning("constant expression ignored");
+#endif LINT
                        *expp = expr;
-               else
+               }
+               else {
                        *expp = new_oper(expr->ex_type, *expp, oper, expr);
+               }
                (*expp)->ex_flags |= EX_COMMA;
                break;
        }
index 962873c..b8724ea 100644 (file)
@@ -8,7 +8,12 @@
 #include       "lint.h"
 #include       "debug.h"
 #include       "dbsymtab.h"
-#include       <em_code.h>
+#ifndef        LINT
+#include       <em.h>
+#else
+#include       "l_em.h"
+#include       "l_lint.h"
+#endif LINT
 #include       "botch_free.h"
 #include       <alloc.h>
 #include       "dataflow.h"
@@ -135,6 +140,7 @@ flush_strings() {
        }
 }
 
+#ifndef        LINT
 end_code()
 {
        /*      end_code() performs the actions to be taken when closing
@@ -147,6 +153,7 @@ end_code()
        C_ms_src((int)(LineNumber - 2), FileName);
        C_close();
 }
+#endif LINT
 
 #ifdef PREPEND_SCOPES
 prepend_scopes()
@@ -592,7 +599,7 @@ loc_init(expr, id)
                        store_val(&vl, tp);
                }
 #else  LINT
-               df->df_set = 1;
+               id->id_def->df_set = 1;
 #endif LINT
                free_expression(expr);
        }
@@ -644,7 +651,9 @@ formal_cvt(hasproto,df)
                    && tp->tp_fund == FLOAT
                    && !hasproto) {
                LoadLocal(df->df_address, double_size);
+#ifndef        LINT
                conversion(double_type, float_type);
+#endif LINT
                StoreLocal(df->df_address, tp->tp_size);
        }
 }
@@ -666,7 +675,6 @@ code_expr(expr, val, code, tlbl, flbl)
 #ifdef DBSYMTAB
        if (options['g']) db_line(expr->ex_file, (unsigned int)expr->ex_line);
 #endif
-
        EVAL(expr, val, code, tlbl, flbl);
 #else  LINT
        lint_expr(expr, code ? USED : IGNORED);
index fd398b0..4cd6090 100644 (file)
@@ -30,7 +30,6 @@
 #include       "level.h"
 #ifdef LINT
 #include       "l_lint.h"
-#include       "l_state.h"
 #endif LINT
 
 extern char    options[];
@@ -643,7 +642,7 @@ parameter_decl(struct proto **plp;)
 
 /*     This is weird. Due to the LR structure of the ANSI C grammar
        we have to duplicate the actions of 'declarator' and
-       'abstract_declarator'. Calling these separate, as in
+       'abstract_declarator'. Calling these separately, as in
 
        parameter_decl:
                decl_specifiers
index 222917c..b023f4d 100644 (file)
@@ -12,7 +12,7 @@ struct def    {               /* for ordinary tags */
        int df_level;
        struct type *df_type;
        int df_sc;              /*      may be:
-                                       GLOBAL, STATIC, EXTERN
+                                       GLOBAL, STATIC, EXTERN,
                                        TYPEDEF,
                                        FORMAL, AUTO,
                                        ENUM, LABEL
@@ -20,7 +20,6 @@ struct def    {               /* for ordinary tags */
        char df_initialized;    /* an initialization has been generated */
        char df_alloc;          /* 0, ALLOC_SEEN or ALLOC_DONE */
        char df_used;           /* set if idf is used */
-       char df_formal_array;   /* to warn if sizeof is taken */
        char *df_file;          /* file containing the definition */
        unsigned int df_line;   /* line number of the definition */
 #ifdef LINT
@@ -28,6 +27,7 @@ struct def    {               /* for ordinary tags */
        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 797da2f..6199891 100644 (file)
@@ -5,9 +5,14 @@
 /* $Header$ */
 /*     E R R O R   A N D  D I A G N O S T I C   R O U T I N E S        */
 
+#include       "lint.h"
 #include       <varargs.h>
 #include       <system.h>
+#ifndef        LINT
 #include       <em.h>
+#else
+#include       "l_em.h"
+#endif LINT
 
 #include       "debug.h"
 #include       "lint.h"
index 305d819..1e0639c 100644 (file)
@@ -266,23 +266,7 @@ declare_idf(ds, dc, lvl)
                                : AUTO;
 
 #ifdef LINT
-       if (    def && def->df_level < lvl
-       &&      !(      lvl == L_FORMAL2
-               ||      def->df_level == L_UNIVERSAL
-               ||      sc == GLOBAL
-               ||      sc == EXTERN
-               )
-       ) {
-               /*      there is already a definition for this non-extern 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"
-               );
-       }
+       check_hiding(idf, lvl, sc);     /* of some idf by this idf */
 #endif LINT
 
        if ((def && 
@@ -332,8 +316,8 @@ declare_idf(ds, dc, lvl)
                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; */
+               newdef->df_set = 0;
+               newdef->df_firstbrace = 0;
 #endif LINT
                /* link it into the name list in the proper place */
                idf->id_def = newdef;
index 5111bc0..9126095 100644 (file)
@@ -7,7 +7,12 @@
 
 {
 #include       "lint.h"
+#ifndef        LINT
 #include       <em.h>
+#else
+#include       "l_em.h"
+#include       "l_lint.h"
+#endif LINT
 #include       "debug.h"
 #include       <alloc.h>
 #include       <assert.h>
@@ -28,9 +33,6 @@
 #include       "def.h"
 #include       "LLlex.h"
 #include       "estack.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)
diff --git a/lang/cem/cemcom.ansi/l_em.h b/lang/cem/cemcom.ansi/l_em.h
new file mode 100644 (file)
index 0000000..f59e218
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * (c) copyright 1990 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
+/*
+ * This file can be considered the em_code.h file of lint.
+ * Those code generating functions that are used by cem and that have not
+ * been defined away by #ifdef LINT, are defined away here. Note that this a
+ * fairly random collection. E.g. it does not include C_open(), since the
+ * standard C-open() C_close() sequence is protected by #ifdef LINT, but it
+ * does include C_close() since the latter is also called in other places,
+ * to terminate the compilation process.
+ */
+
+#define        store_block(sz, al)
+#define        load_block(sz, al)
+
+#define        C_asp(c)
+#define        C_bra(b)
+#define        C_cal(p)
+#define        C_csa(w)
+#define        C_csb(w)
+#define        C_fil_dlb(g,o)
+#define        C_lae_dlb(g,o)
+#define        C_lal(c)
+#define        C_lin(c)
+#define        C_loi(c)
+#define        C_lol(c)
+#define        C_sdl(c)
+#define        C_sti(c)
+#define        C_stl(c)
+
+#define        C_busy()        0
+#define        C_close()
+
+#define        C_df_dlb(l)
+#define        C_df_dnam(s)
+#define        C_df_ilb(l)
+
+#define        C_pro_narg(s)
+#define        C_end(l)
+
+#define        C_exa_dnam(s)
+#define        C_ina_dnam(s)
+#define        C_ina_dlb(l)
+#define        C_exp(s)
+#define        C_inp(s)
+
+#define        C_bss_cst(n,w,i)
+
+#define        C_con_cst(v)
+#define        C_con_icon(v,s)
+#define        C_con_ucon(v,s)
+#define        C_con_fcon(v,s)
+#define        C_con_scon(v,s)
+#define        C_con_dnam(v,s)
+#define        C_con_dlb(v,s)
+#define        C_con_pnam(v)
+
+#define        C_rom_cst(v)
+#define        C_rom_icon(v,s)
+#define        C_rom_scon(v,s)
+#define        C_rom_ilb(v)
+
+#define        C_ldl(l)
+
+#define        C_mes_begin(ms)
+#define        C_mes_end()
+
+#define        C_ms_gto()
+#define        C_ms_par(b)
+#define        C_ms_reg(o,s,t,c)
+
index 5cdda08..be44675 100644 (file)
@@ -12,7 +12,9 @@
 #include       <alloc.h>       /* for st_free */
 #include       "interface.h"
 #include       "assert.h"
+#ifdef ANSI
 #include       <flt_arith.h>
+#endif ANSI
 #include       "arith.h"       /* definition arith */
 #include       "label.h"       /* definition label */
 #include       "expr.h"
index e2629df..73adf19 100644 (file)
@@ -13,7 +13,9 @@
 #include       "debug.h"
 #include       "interface.h"
 #include       "assert.h"
+#ifdef ANSI
 #include       <flt_arith.h>
+#endif ANSI
 #include       "arith.h"       /* definition arith */
 #include       "label.h"       /* definition label */
 #include       "expr.h"
@@ -255,14 +257,6 @@ oper2state(expr, val, used)
        case GREATEREQ:
        case EQUAL:
        case NOTEQUAL:
-               lint_relop(left, right, oper);
-               lint_relop(right, left, 
-                       oper == '<' ? '>' :
-                       oper == '>' ? '<' :
-                       oper == LESSEQ ? GREATEREQ :
-                       oper == GREATEREQ ? LESSEQ :
-                       oper
-               );
                goto dyadic;
 
        /* dyadic operators */
@@ -296,8 +290,10 @@ expr_ignored(expr)
        struct expr *expr;
 {
        switch (expr->ex_class) {
+               int oper;
        case Oper:
-               switch (expr->OP_OPER) {
+               oper = expr->OP_OPER;
+               switch (oper) {
                case '=':
                case TIMESAB:
                case DIVAB:
@@ -312,6 +308,7 @@ expr_ignored(expr)
                case '(':
                case '?':
                case ',':
+                       oper = 0;               /* ignore the ignoring */
                        break;
 
                case PLUSAB:
@@ -320,29 +317,45 @@ expr_ignored(expr)
                case POSTDECR:
                case PLUSPLUS:
                case MINMIN:
-                       /* may hide the operator '*' */
+                       oper = 0;               /* ignore in priciple */
+                       /* may, however, 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");
+                               oper = '*';
                        }
                        break;
 
-               default:
-                       hwarning("result of %s ignored",
-                                               symbol2str(expr->OP_OPER));
+               case '/':
+                       /*      this is a specially weird case: the '/' may
+                               result from pointer subtraction
+                       */
+                       if (    expr->OP_TYPE->tp_fund == INT
+                       &&      expr->OP_LEFT->OP_OPER == '-'
+                       &&      expr->OP_LEFT->OP_TYPE->tp_fund == POINTER
+                       ) {
+                               oper = '-';
+                       }
                        break;
                }
+               if (oper) {
+                       hwarning("result of %s ignored", symbol2str(oper));
+               }
                break;
 
        case Value:
-               hwarning("value as statement");
+               if (expr->VL_CLASS == Const) {
+                       hwarning("constant expression ignored");
+               }
+               else {
+                       hwarning("value ignored");
+               }
                break;
 
        default:                        /* String Float */
-               hwarning("constant as statement");
+               hwarning("constant ignored");
                break;
        }
 }
index e558e53..d0213ca 100644 (file)
 #ifdef LINT
 
 #include       <alloc.h>       /* for st_free */
-#include       "debug.h"
 #include       "interface.h"
+#ifdef ANSI
 #include       <flt_arith.h>
+#endif ANSI
 #include       "arith.h"       /* definition arith */
 #include       "label.h"       /* definition label */
 #include       "expr.h"
@@ -33,6 +34,32 @@ PRIVATE lint_enum_arith();
 PRIVATE lint_conversion();
 PRIVATE int numsize();
 
+check_hiding(idf, lvl, sc)
+       struct idf *idf;
+       int lvl;
+       int sc;
+{
+       /*      Checks if there is already a definition for this non-extern
+               name on a more global level.
+       */
+       struct def *def = idf->id_def;
+       
+       if (    def && def->df_level < lvl
+       &&      ! (     lvl == L_FORMAL2
+               ||      def->df_level == L_UNIVERSAL
+               ||      sc == GLOBAL
+               ||      sc == EXTERN
+               )
+       ) {
+               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"
+               );
+       }
+}
+
 lint_new_oper(expr)
        struct expr *expr;
 {
@@ -53,14 +80,14 @@ lint_new_oper(expr)
                right == 0 ? 0 :                /* for ( without parameters */
                right->ex_type->tp_fund;
 
-       /*      In ch3.c, in ch3asgn(), a combined operator/assignment
+       /*      In ch7.c, in ch7asgn(), a combined operator/assignment
                is hammered into correctness by repeated application of
-               ch3bin(), which calls new_oper(), which calls lint_new_oper().
+               ch7bin(), which calls new_oper(), which calls lint_new_oper().
                These spurious calls understandably cause spurious error
                messages, which we don't like.  So we try to suppress these
                wierd calls here.  This refers to the code marked
                        this is really $#@&*%$# !
-               in ch3asgn().
+               in ch7asgn().
        */
        switch (oper) {
        case PLUSAB:
@@ -104,7 +131,7 @@ lint_new_oper(expr)
                else {
                        /* binary */
                        if (l_fund == ENUM && r_fund == ENUM) {
-                               if (!equal_type(left->ex_type, right->ex_type, 0))
+                               if (left->ex_type != right->ex_type)
                                        warning("subtracting enums of different type");
                                /* update the type, cem does not do it */
                                expr->ex_type = int_type;
@@ -141,8 +168,7 @@ lint_new_oper(expr)
                break;
 
        case '~':
-               if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE
-                                           /* ??? ||  r_fund == LNGDBL */ )
+               if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE)
                        warning("~ on %s", symbol2str(r_fund));
                break;
 
@@ -165,7 +191,7 @@ lint_new_oper(expr)
        case EQUAL:
        case NOTEQUAL:
                if (    (l_fund == ENUM || r_fund == ENUM)
-               &&      !equal_type(left->ex_type, right->ex_type, 0)
+               &&      left->ex_type != right->ex_type
                ) {
                        warning("comparing enum with non-enum");
                }
@@ -287,7 +313,6 @@ numsize(fund)
        case LONG:      return 4;
        case FLOAT:     return 5;
        case DOUBLE:    return 6;
-       case LNGDBL:    return 7;
        default:        return 0;
        }
 }
@@ -303,8 +328,8 @@ lint_ptr_conv(from, to)
 {
 /* X -> X ok                   -- this includes struct -> struct, of any size
  * X -> CHAR ok
- * LNGDBL -> X ok
- * DOUBLE -> FLOAT -> LONG -> INT -> SHORT  ok
+ * DOUBLE -> X ok
+ * FLOAT -> LONG -> INT -> SHORT  ok
  */
        if (from == to)
                return;
@@ -312,18 +337,10 @@ lint_ptr_conv(from, to)
        if (to == CHAR)
                return;
 
-       if (from == LNGDBL)
+       if (from == DOUBLE)
                return;
 
        switch (from) {
-       case DOUBLE:
-               switch(to) {
-               case FLOAT:
-               case INT:
-               case SHORT:
-                       return;
-               }
-               break;
        case FLOAT:
                switch (to) {
                case LONG:
@@ -373,7 +390,7 @@ lint_relop(left, right, oper)
        &&      right->ex_class == Value
        &&      right->VL_CLASS == Const
        ) {
-               if (right->VL_VALUE < 0) {
+               if (!right->ex_type->tp_unsigned && right->VL_VALUE < 0) {
                        warning("unsigned compared to negative constant");
                }
                if (right->VL_VALUE == 0) {
index b29b614..fd3a31a 100644 (file)
 #ifdef LINT
 
 #include       <alloc.h>
-#include       "debug.h"
 #include       "interface.h"
+#ifdef ANSI
 #include       <flt_arith.h>
+#endif ANSI
 #include       "arith.h"
 #include       "assert.h"
 #include       "type.h"
+#include       "declar.h"
+#include       "decspecs.h"
 #include       "LLlex.h"
 #include       "Lpars.h"
 #include       "stack.h"
@@ -34,6 +37,7 @@
 
 extern char *bts2str();
 extern char *symbol2str();
+extern char *strindex();
 
 int stat_number = 9999;                        /* static scope number */
 struct outdef OutDef;
@@ -46,7 +50,6 @@ PRIVATE outargs();
 PRIVATE outarg();
 PRIVATE outargstring();
 PRIVATE outargtype();
-PRIVATE implicit_func_decl();
 PRIVATE fill_arg();
 
 lint_declare_idf(idf, sc)
@@ -69,10 +72,23 @@ lint_declare_idf(idf, sc)
        }
 }
 
+lint_non_function_decl(ds, dc)
+       struct decspecs *ds;
+       struct declarator *dc;
+{
+       register struct def *def = dc->dc_idf->id_def;
+       register int is_function = def->df_type->tp_fund == FUNCTION;
+
+       if (is_function)
+               def2decl(ds->ds_sc);
+       if (def->df_sc != TYPEDEF)
+               outdef();
+}
+
 lint_ext_def(idf, sc)
        struct idf *idf;
 {
-/* At this place the following fields of the outputdefinition can be
+/* At this place the following fields of the output definition can be
  * filled:
  *             name, stat_number, class, file, line, type.
  * For variable definitions and declarations this will be all.
@@ -165,7 +181,7 @@ lint_formals()
                switch (type->tp_fund) {
                case CHAR:
                case SHORT:
-                       type = int_type;
+                       type = (type->tp_unsigned ? uint_type : int_type);
                        break;
                case FLOAT:
                        type = double_type;
@@ -273,7 +289,7 @@ output_def(od)
 /* As the types are output the tp_entries are removed, because they
  * are then not needed anymore.
  */
-       if (od->od_class == XXDF)
+       if (od->od_class == XXDF || !od->od_name || od->od_name[0] == '#')
                return;
 
        if (LINTLIB) {
@@ -435,7 +451,18 @@ outargtype(tp)
        case STRUCT:
        case UNION:
        case ENUM:
-               printf("%s %s", symbol2str(tp->tp_fund), tp->tp_idf->id_text);
+               /* watch out for anonymous identifiers; the count field does
+                  not have to be the same for all compilation units.
+                  Remove it, so that pass 2 does not see it. The only
+                  problem with this is that pass2 will not see a difference
+                  between two non-tagged types declared on the same line.
+               */
+               printf("%s ", symbol2str(tp->tp_fund));
+               if (is_anon_idf(tp->tp_idf)) {
+                       /* skip the #<num>, replace it by '#anonymous id' */
+                       printf("#anonymous id%s", strindex(tp->tp_idf->id_text, ' '));
+               }
+               else printf(tp->tp_idf->id_text);
                break;
 
        case CHAR:
@@ -444,7 +471,6 @@ outargtype(tp)
        case LONG:
        case FLOAT:
        case DOUBLE:
-       case LNGDBL:
        case VOID:
        case ERRONEOUS:
                if (tp->tp_unsigned)
@@ -457,6 +483,7 @@ outargtype(tp)
        }
 }
 
+#ifdef IMPLICIT
 PRIVATE
 implicit_func_decl(idf, file, line)
        struct idf *idf;
@@ -474,6 +501,7 @@ implicit_func_decl(idf, file, line)
        output_def(&od);
        /* The other fields are not used for this class. */
 }
+#endif IMPLICIT
 
 fill_outcall(ex, used)
        struct expr *ex;
@@ -482,10 +510,12 @@ fill_outcall(ex, used)
        register struct idf *idf = ex->OP_LEFT->VL_IDF;
        register struct def *def = idf->id_def;
 
+#ifdef IMPLICIT
        if (def->df_sc == IMPLICIT && !idf->id_def->df_used) {
                /* IFDC, first time */
                implicit_func_decl(idf, ex->ex_file, ex->ex_line);
        }
+#endif IMPLICIT
 
        OutCall.od_type = def->df_type->tp_up;
        OutCall.od_statnr = (def->df_sc == STATIC ? stat_number : 0);
@@ -519,7 +549,10 @@ fill_arg(e)
                arg->ar_class = ArgConst;
                arg->CAA_VALUE = e->VL_VALUE;
        }
-       else if (e->ex_class == Value && e->VL_CLASS == Label) {
+       else if (       e->ex_type == string_type
+               &&      e->ex_class == Value
+               &&      e->VL_CLASS == Label
+               ) {
                /* it may be a string; let's look it up */
                register struct string_cst *sc = str_list;
 
index 2ef9191..5f8f1b2 100644 (file)
  * control of the program.
  */
 
+#define        TEST_VAR        0               /* not a constant */
+#define        TEST_TRUE       1               /* always true */
+#define        TEST_FALSE      2               /* always false */
 
-struct switch_states {
+struct loop_state {                    /* used in lint_end_state only */
+       int lps_test;                   /* is the test a constant? */
+       struct state *lps_body;
+       struct state *lps_loop;
+};
+
+struct switch_state {                  /* used in lint_end_state only */
        struct state *sws_case;
        struct state *sws_break;
        int sws_default_met;
 };
 
+/*     This union describes the (possibly incomplete) state at the end of the
+       mentioned construct.
+*/
+union lint_end_state {                 /* used in lint_stack_entry only */
+       struct state *ule_if;
+       struct loop_state ule_loop;
+       struct switch_state ule_switch;
+};
+
 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 */
+       struct state *ls_current;       /* used by all classes */
+       short ls_class;                 /* IF, WHILE, DO, FOR, SWITCH, CASE */
+       union lint_end_state ls_end;
 };
 
-/* 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 */
 
+/* macros to access the union */
+#define LS_IF          ls_end.ule_if
+#define LS_TEST                ls_end.ule_loop.lps_test
+#define LS_BODY                ls_end.ule_loop.lps_body
+#define LS_LOOP                ls_end.ule_loop.lps_loop
+#define LS_CASE                ls_end.ule_switch.sws_case
+#define LS_BREAK       ls_end.ule_switch.sws_break
+#define LS_DEFAULT_MET ls_end.ule_switch.sws_default_met
+
+/* describes a branch in the program, with its local idfs */
 struct state {
        struct state *next;             /* only used by memory allocator */
        struct auto_def *st_auto_list;
@@ -50,6 +67,7 @@ struct state {
 
 /* ALLOCDEF "state" 15 */
 
+/* describes the state of a local idf in a given branch of the program */
 struct auto_def {
        struct auto_def *next;
        struct idf *ad_idf;
@@ -61,13 +79,14 @@ struct auto_def {
 
 /* ALLOCDEF "auto_def" 20 */
 
-struct expr_state {
+/* describes the state of an idf during expression evaluation */
+struct expr_state {                    /*actually concerns idfs only */
        struct expr_state *next;
-       struct idf *es_idf;
+       struct idf *es_idf;             /* the idf with its offset */
        arith es_offset;
-       int es_used;
-       int es_referred;
-       int es_set;
+       int es_used;                    /* value has been used */
+       int es_referred;                /* address has been taken */
+       int es_set;                     /* has been assigned to */
 };
 
 /* ALLOCDEF "expr_state" 20 */
index 463276a..b7f87fb 100644 (file)
 #ifdef LINT
 
 #include       <alloc.h>       /* for st_free */
-#include       "debug.h"
 #include       "interface.h"
 #include       "assert.h"
+#include       "debug.h"
+#ifdef ANSI
 #include       <flt_arith.h>
-#include       "arith.h"       /* definition arith */
-#include       "label.h"       /* definition label */
+#endif ANSI
+#include       "arith.h"
+#include       "label.h"
 #include       "expr.h"
 #include       "idf.h"
 #include       "def.h"
 #include       "l_comment.h"
 #include       "l_outdef.h"
 
-#define min(a, b) ((a) < (b) ? (a) : (b))
+#ifdef DEBUG
+#define        dbg_lint_stack(m)       /*print_lint_stack(m)   /* or not */
+#else
+#define        dbg_lint_stack(m)
+#endif DEBUG
 
 extern char *symbol2str();
 extern char *func_name;
 extern struct type *func_type;
 extern int func_notypegiven;
 extern char loptions[];
+extern struct stack_level *local_level;
 
 /* global variables for the lint_stack */
-PRIVATE struct lint_stack_entry stack_bottom;
-PRIVATE struct lint_stack_entry *top_ls = &stack_bottom;
+PRIVATE struct lint_stack_entry *top_ls;
 
 /* global variables for the brace stack */
 PRIVATE int brace_count;
-PRIVATE struct brace brace_bottom;
-PRIVATE struct brace *top_br = &brace_bottom;
+PRIVATE struct brace *top_br;
+
+/* global variables for the function return */
+PRIVATE int valreturned;               /* see l_lint.h */
+PRIVATE int return_warned;
 
 PRIVATE end_brace();
 PRIVATE lint_1_local();
 PRIVATE lint_1_global();
+PRIVATE start_loop_stmt();
 PRIVATE check_autos();
-PRIVATE struct auto_def *copy_st_auto_list();
-PRIVATE free_st_auto_list();
+PRIVATE struct auto_def *copy_auto_list();
+PRIVATE free_auto_list();
 PRIVATE struct state *copy_state();
 PRIVATE Free_state();
 PRIVATE remove_settings();
 PRIVATE struct auto_def *merge_autos();
 PRIVATE merge_states();
 PRIVATE struct lint_stack_entry *find_wdf(), *find_wdfc(), *find_cs();
-PRIVATE cont_break_merge();
+PRIVATE cont_merge();
+PRIVATE break_merge();
+PRIVATE struct lint_stack_entry *mk_lint_stack_entry();
 PRIVATE lint_push();
 PRIVATE lint_pop();
 
 lint_init_stack()
 {
-/* Allocate some memory for the global stack_bottom
- */
-       stack_bottom.ls_current = new_state();
+/*     Allocate memory for the global lint-stack elements.
+*/
+       top_ls = new_lint_stack_entry();
+       top_ls->ls_current = new_state();
 }
 
 lint_start_local()
 {
        register struct brace *br = new_brace();
 
+       dbg_lint_stack("lint_start_local");
        brace_count++;
        br->br_count = brace_count;
        br->br_level = level;
@@ -82,24 +96,20 @@ lint_start_local()
        top_br = br;
 }      
 
-lint_local_level(stl)
+lint_end_local(stl)
        struct stack_level *stl;
 {
+
+       dbg_lint_stack("lint_end_local");
        if (s_NOTREACHED) {
                top_ls->ls_current->st_notreached = 1;
+               top_ls->ls_current->st_warned = 0;
                s_NOTREACHED = 0;
        }
 
        if (top_ls->ls_class == CASE && level == top_ls->ls_level) {
+               /* supply missing  break;  at end of switch */
                lint_break_stmt();
-                       /* To prevent a warning for the case
-                        *      switch (cond) {
-                        *      int i;
-                        *      case 0:
-                        *              i = 0;
-                        *              use(i);
-                        *      }
-                        */
        }
 
        check_autos();
@@ -111,6 +121,7 @@ end_brace(stl)
        struct stack_level *stl;
 {
        /*      Check if static variables and labels are used and/or set.
+               Automatic vars have already been checked by check_autos().
        */
        register struct stack_entry *se = stl->sl_entry;
        register struct brace *br;
@@ -125,6 +136,7 @@ end_brace(stl)
                se = se->next;
        }
 
+       /* remove entry from brace stack */
        br = top_br;
        top_br = br->next;
        free_brace(br);
@@ -139,8 +151,9 @@ lint_1_local(idf, def)
 
        if (    (sc == STATIC || sc == LABEL)
        &&      !def->df_used
+       &&      !is_anon_idf(idf)
        ) {
-               def_warning(def, "%s %s declared but not used in function %s",
+               def_warning(def, "%s %s not applied anywhere in function %s",
                        symbol2str(sc), idf->id_text, func_name);
        }
 
@@ -149,6 +162,7 @@ lint_1_local(idf, def)
        &&      !def->df_initialized
        &&      def->df_firstbrace != 0
        &&      def->df_minlevel != level
+       &&      !is_anon_idf(idf)
        ) {
                register int diff = def->df_minlevel - level;
 
@@ -159,11 +173,12 @@ lint_1_local(idf, def)
        }
 }
 
-lint_global_level(stl)
+lint_end_global(stl)
        struct stack_level *stl;
 {
        register struct stack_entry *se = stl->sl_entry;
 
+       dbg_lint_stack("lint_end_global");
        ASSERT(level == L_GLOBAL);
        while (se) {
                register struct idf *idf = se->se_idf;
@@ -188,7 +203,9 @@ lint_1_global(idf, def)
        case STATIC:
        case EXTERN:
        case GLOBAL:
+#ifdef IMPLICIT
        case IMPLICIT:
+#endif IMPLICIT
                if (fund == ERRONEOUS)
                        break;
 
@@ -198,32 +215,19 @@ lint_1_global(idf, def)
                         */
                        output_use(idf);
                }
-               else {
-                       if (sc == STATIC) {
-                               if (def->df_set) {
+
+               if (sc == STATIC && !def->df_used) {
+                       if (def->df_set) {
+                               if (!is_anon_idf(idf) && fund != ERRONEOUS) {
                                        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
-                               ) {
+                       else {
+                               if (!is_anon_idf(idf) && fund != ERRONEOUS) {
                                        def_warning(def,
                                                "%s %s %s not used anywhere",
                                                symbol2str(sc),
@@ -232,6 +236,25 @@ lint_1_global(idf, def)
                                }
                        }
                }
+               if (loptions['x']) {
+                       register char *fn = def->df_file;
+
+                       if (    (sc == EXTERN || sc == GLOBAL)
+                       &&      def->df_alloc == 0
+                       &&      !def->df_set
+                       &&      !def->df_initialized
+                       &&      !def->df_used
+                       &&      strcmp(&fn[strlen(fn)-2], ".c") == 0
+                       &&      !is_anon_idf(idf)
+                       &&      fund != ERRONEOUS
+                       ) {
+                               def_warning(def,
+                                       "%s %s %s not used anywhere",
+                                       symbol2str(sc),
+                                       symbol2str(fund),
+                                       idf->id_text);
+                       }
+               }
                break;
        }
 }
@@ -242,42 +265,44 @@ change_state(idf, to_state)
 {
 /* 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.
+ * 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) {
-               switch (to_state) {
-               case SET:
-                       def->df_set = 1;
-                       break;
-               case USED:
-                       def->df_used = 1;
-                       break;
-               }
+       ASSERT(def);
 
-               if (def->df_firstbrace == 0) {
-                       def->df_firstbrace = brace_count;
-                       def->df_minlevel = level;
-               }
-               else {
-                       register struct brace *br = top_br;
+       switch (to_state) {
+       case SET:
+               def->df_set = 1;
+               break;
+       case USED:
+               def->df_used = 1;
+               break;
+       }
 
-                       /*      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;
+       /* adjust minimum required brace level */
+       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;
        }
 
+       /* search auto_list */
        while(a && a->ad_idf != idf)
                a = a->next;
-       if (a == 0)     /* identifier not in list */
+       if (a == 0)     /* identifier not in list, global definition */
                return;
 
        switch (to_state) {
@@ -287,9 +312,12 @@ change_state(idf, to_state)
                break;
        case USED:
                if (!a->ad_set) {
-                       warning("%s%s uninitialized", idf->id_text,
-                               (a->ad_maybe_set ? " possibly" : "")
-                       );
+                       if (!is_anon_idf(idf)) {
+                               warning("variable %s%s uninitialized",
+                                       idf->id_text,
+                                       (a->ad_maybe_set ? " possibly" : "")
+                               );
+                       }
                        a->ad_maybe_set = 0;
                        a->ad_set = 1;  /* one warning */
                }
@@ -298,30 +326,31 @@ change_state(idf, to_state)
        }
 }
 
-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.
+ * Watch out for formal parameters.
  */
        register struct def *def = idf->id_def;
-       register struct auto_def *a;
 
-       if (!def)
-               return;
+       ASSERT(def);
+
        switch (def->df_sc) {
+               register struct auto_def *a;
        case AUTO:
        case REGISTER:
                if (def->df_level < L_LOCAL)
-                       return;         /* a register formal */
+                       return;         /* a formal */
+
                a = new_auto_def();
+
                a->ad_idf = idf;
-               a->ad_def = idf->id_def;
+               a->ad_def = 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;
        }
@@ -330,43 +359,50 @@ add_auto(idf)     /* to current state on top of lint_stack */
 PRIVATE
 check_autos()
 {
-/* Before leaving a block remove the auto_defs of the automatic
+/* 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;
+       register struct auto_def *a = top_ls->ls_current->st_auto_list;
 
-       ASSERT(!(a1 && a1->ad_def->df_level > level));
-       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,
+       ASSERT(!(a && a->ad_def->df_level > level));
+       while (a && a->ad_def->df_level == level) {
+               struct idf *idf = a->ad_idf;
+               struct def *def = idf->id_def;
+
+               if (!def->df_used && !is_anon_idf(idf)) {
+                       if (def->df_set || a->ad_maybe_set) {
+                               def_warning(def,
                                        "%s set but not used in function %s",
-                                       a2->ad_idf->id_text, func_name);
+                                       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);
+                               def_warning(def,
+                                       "%s not used anywhere in function %s",
+                                       idf->id_text, func_name);
                        }
                }
-               free_auto_def(a2);
+
+               {       /* free a */
+                       register struct auto_def *aux = a;
+                       a = a->next;
+                       free_auto_def(aux);
+               }
        }
-       top_ls->ls_current->st_auto_list = a1;
+       top_ls->ls_current->st_auto_list = a;
 }
 
-check_args_used()
+lint_end_formals()
 {
        register struct stack_entry *se = local_level->sl_entry;
 
+       dbg_lint_stack("lint_end_formals");
        ASSERT(level == L_FORMAL1);
        while (se) {
                register struct def *def = se->se_idf->id_def;
 
                if (    (def && !def->df_used)
                &&      !(f_ARGSUSED || LINTLIB)
+               &&      !is_anon_idf(se->se_idf)
                ) {
                        def_warning(def, "argument %s not used in function %s",
                                        se->se_idf->id_text, func_name);
@@ -376,15 +412,18 @@ check_args_used()
 }
 
 PRIVATE struct auto_def *
-copy_st_auto_list(from_al, lvl)
+copy_auto_list(from_al, lvl)
        struct auto_def *from_al;
+       int lvl;
 {
        struct auto_def *start = 0;
        register struct auto_def **hook = &start;
 
+       /* skip too high levels */
        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();
 
@@ -398,28 +437,27 @@ copy_st_auto_list(from_al, lvl)
 }
 
 PRIVATE
-free_st_auto_list(au)
-       register struct auto_def *au;
-{
+free_auto_list(a)
        register struct auto_def *a;
-
-       while (au) {
-               a = au;
-               au = au->next;
-               free_auto_def(a);
+{
+       while (a) {
+               register struct auto_def *aux = a;
+               a = a->next;
+               free_auto_def(aux);
        }
 }
 
 PRIVATE struct state *
 copy_state(from_st, lvl)
        struct state *from_st;
+       int lvl;
 {
 /* 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_auto_list = copy_auto_list(from_st->st_auto_list, lvl);
        st->st_notreached = from_st->st_notreached;
        st->st_warned = from_st->st_warned;
        return st;
@@ -431,19 +469,20 @@ Free_state(stp)
 {
 /* This function also frees the list of auto_defs
  */
-       free_st_auto_list((*stp)->st_auto_list);
+       free_auto_list((*stp)->st_auto_list);
        free_state(*stp);
        *stp = 0;
 }
 
 PRIVATE
-remove_settings(state, lvl)
-       struct state *state;
+remove_settings(st, lvl)
+       struct state *st;
+       int lvl;
 {
-/* The state of all variables on this level are set to 'not set' and
+/* The states 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;
+       register struct auto_def *a = st->st_auto_list;
 
        while (a && a->ad_def->df_level == lvl) {
                a->ad_set = a->ad_maybe_set = 0;
@@ -459,9 +498,48 @@ remove_settings(state, lvl)
 #define        CASE_BREAK      1
 #define        USE_ONLY        2
 
+PRIVATE
+merge_states(st1, st2, lvl, mode)
+       struct state *st1, *st2;
+       int lvl;
+       int mode;                       /* NORMAL or CASE_BREAK */
+{
+/* 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_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_auto_list(tmp);
+       }
+       else {
+               /* both st1 and st2 reached */
+               st2->st_auto_list =
+                       merge_autos(st1->st_auto_list, st2->st_auto_list,
+                               lvl, mode);
+       }
+}
+
 PRIVATE struct auto_def *
 merge_autos(a1, a2, lvl, mode)
        struct auto_def *a1, *a2;
+       int lvl;
        int mode;
 {
 /* Returns a pointer to the result.
@@ -484,17 +562,23 @@ merge_autos(a1, a2, lvl, mode)
  */
        register struct auto_def *a;
 
+       /* skip too local entries */
        while (a1 && a1->ad_def->df_level > lvl) {
                a1 = a1->next;
        }
+
+       /* discard too local entries */
        while (a2 && a2->ad_def->df_level > lvl) {
-               a = a2;
+               register struct auto_def *aux = a2;
                a2 = a2->next;
-               free_auto_def(a);
+               free_auto_def(aux);
        }
+
        a = a2; /* pointer to the result */
        while (a1) {
                ASSERT(a2);
+
+               /* merge the auto_defs for one idf */
                ASSERT(a1->ad_idf == a2->ad_idf);
                if (a1->ad_used)
                        a2->ad_used = 1;
@@ -520,41 +604,6 @@ merge_autos(a1, a2, lvl, mode)
        return a;
 }
 
-PRIVATE
-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 ********/
 
@@ -567,7 +616,7 @@ find_wdf()
 {
        register struct lint_stack_entry *lse = top_ls;
 
-       while (lse != &stack_bottom) {
+       while (lse) {
                switch (lse->ls_class) {
                case WHILE:
                case DO:
@@ -584,7 +633,7 @@ find_wdfc()
 {
        register struct lint_stack_entry *lse = top_ls;
 
-       while (lse != &stack_bottom) {
+       while (lse) {
                switch (lse->ls_class) {
                case WHILE:
                case DO:
@@ -602,7 +651,7 @@ find_cs()
 {
        register struct lint_stack_entry *lse = top_ls;
 
-       while (lse != &stack_bottom) {
+       while (lse) {
                switch (lse->ls_class) {
                case CASE:
                case SWITCH:
@@ -613,163 +662,227 @@ find_cs()
        return 0;
 }
 
-/******** A C T I O N S ********/
+/******** A C T I O N S : I F ********/
 
 start_if_part(const)
 {
-/* 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();
+       register struct lint_stack_entry *new = mk_lint_stack_entry(IF);
 
+       dbg_lint_stack("start_if_part");
        if (const)
                hwarning("condition in if statement is constant");
 
-       lse->ls_class = IF;
-       lse->ls_current = copy_state(top_ls->ls_current, level);
-       lse->ls_level = level;
-       lint_push(lse);
+       lint_push(new);
+/*     ls_current:     the state at the start of the if-part
+*/
 }
 
 start_else_part()
 {
-/* Move ls_current to LS_IF_STATE
- * ls_current of the stack entry one below is copied to ls_current.
- */
+/*     ls_current:     the state at the end of the if-part
+       ls_previous->ls_current:        the state before the if-part
+*/
+
+       dbg_lint_stack("start_else_part");
        if (s_NOTREACHED) {
                top_ls->ls_current->st_notreached = 1;
+               top_ls->ls_current->st_warned = 0;
                s_NOTREACHED = 0;
        }
-       top_ls->LS_IF_STATE = top_ls->ls_current;
+       top_ls->LS_IF = 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_current =
+               copy_state(top_ls->ls_previous->ls_current, level);
        top_ls->ls_level = level;
+/*     ls_current:     the state before the if-part and the else-part
+       LS_IF:          the state at the end of the if-part
+*/
 }
 
 end_if_else_stmt()
 {
-       Free_state(&top_ls->ls_previous->ls_current);
-       merge_states(top_ls->LS_IF_STATE, top_ls->ls_current,
+/*     ls_current:     state at the end of the else-part
+       LS_IF:          state at the end of the if-part
+*/
+
+       dbg_lint_stack("end_if_else_stmt");
+       merge_states(top_ls->LS_IF, top_ls->ls_current,
                                        top_ls->ls_level, NORMAL);
-       Free_state(&top_ls->LS_IF_STATE);
+       Free_state(&top_ls->LS_IF);
+       Free_state(&top_ls->ls_previous->ls_current);
        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
- */
+/*     No else-part met.
+       ls_current:     state at the end of the if-part
+*/
+
+       dbg_lint_stack("end_if_stmt");
        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();
 }
 
+/******** A C T I O N S : L O O P S ********/
+
+start_while_stmt(expr)
+       struct expr *expr;
+{
+       if (is_cp_cst(expr))    {
+               start_loop_stmt(WHILE, 1, expr->VL_VALUE != (arith)0);
+       }
+       else    {
+               start_loop_stmt(WHILE, 0, 0);
+       }
+}
+
+start_do_stmt()
+{
+       start_loop_stmt(DO, 1, 1);
+}
+
+start_for_stmt(expr)
+       struct expr *expr;
+{
+       if (!expr)      {
+               start_loop_stmt(FOR, 1, 1);
+       }
+       else
+       if (is_cp_cst(expr))    {
+               start_loop_stmt(FOR, 1, expr->VL_VALUE != (arith)0);
+       }
+       else    {
+               start_loop_stmt(FOR, 0, 0);
+       }
+}
+
+PRIVATE
 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();
+/*     If const, the condition is a constant and its value is cond
+*/
+       register struct lint_stack_entry *new = mk_lint_stack_entry(looptype);
 
-       lse->ls_class = looptype;
-       lse->ls_current = copy_state(top_ls->ls_current, level);
-       lse->ls_level = level;
+       dbg_lint_stack("start_loop_stmt");
        if (const && !cond) {
                /* while (0) | for (;0;) */
-               hwarning("condition in %s statement is constant",
+               hwarning("condition in %s statement is always false",
                                                symbol2str(looptype));
-               lse->ls_current->st_notreached = 1;
+               new->ls_current->st_notreached = 1;
        }
        if (const && cond) {
                /* while (1) | for (;;) | do */
-               /*      omitting the copy for LS_END will force this loop
+               /*      omitting the copy for LS_LOOP will force this loop
                        to be treated as a do loop
                */
                top_ls->ls_current->st_notreached = 1;
+               top_ls->ls_current->st_warned = 0;
        }
        else {
-               lse->LS_END = copy_state(top_ls->ls_current, level);
+               new->LS_LOOP = copy_state(top_ls->ls_current, level);
        }
-       lint_push(lse);
+       new->LS_TEST = (!const ? TEST_VAR : cond ? TEST_TRUE : TEST_FALSE);
+       lint_push(new);
+
+/*     ls_current:     the state at the start of the body
+       LS_TEST:        info about the loop test
+       LS_BODY:        0, the state at the end of the body
+       LS_LOOP:        the state at the end of the loop, or 0 if the loop
+                       does not end
+*/
 }
 
-end_loop_stmt()
+end_loop_body()
 {
-       register struct lint_stack_entry *prev_ls = top_ls->ls_previous;
+       register struct lint_stack_entry *lse = find_wdf();
 
-       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();
+       dbg_lint_stack("end_loop_body");
+       ASSERT(lse == top_ls);
+       if (!lse->ls_current->st_notreached)
+               cont_merge(lse);
 }
 
-end_do_stmt(const, cond)
+end_loop_stmt()
 {
-       end_loop_stmt();
-       if (const)
-               hwarning("condition in do-while statement is constant");
-       if (const && cond && top_ls->ls_current->st_notreached) {
+       register struct lint_stack_entry *lse = find_wdf();
+
+       dbg_lint_stack("end_loop_stmt");
+       ASSERT(lse == top_ls);
+       if (lse->LS_TEST != TEST_TRUE)
+               break_merge(lse);
+
+       dbg_lint_stack("end_loop_stmt after break_merge");
+       if (!top_ls->LS_LOOP) {
                /* no break met; this is really an endless loop */
+               hwarning("endless %s loop", symbol2str(top_ls->ls_class));
+               Free_state(&top_ls->ls_current);
        }
        else {
-               top_ls->ls_current->st_notreached = 0;
+               Free_state(&top_ls->ls_current);
+               Free_state(&top_ls->ls_previous->ls_current);
+               top_ls->ls_previous->ls_current = top_ls->LS_LOOP;
        }
+       lint_pop();
 }
 
-PRIVATE
-cont_break_merge(lse)
-       struct lint_stack_entry *lse;
+end_do_stmt(const, cond)
 {
-       /* 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);
+       register struct lint_stack_entry *lse = find_wdf();
+
+       dbg_lint_stack("end_do_stmt");
+       if (const && !cond) {
+               /* do ... while (0) */
+               hwarning("condition in do statement is always false");
        }
+       lse->LS_TEST = (!const ? TEST_VAR : cond ? TEST_TRUE : TEST_FALSE);
+       end_loop_stmt();
+
 }
 
 lint_continue_stmt()
 {
        register struct lint_stack_entry *lse = find_wdf();
 
+       dbg_lint_stack("lint_continue_stmt");
        if (!lse)
                return;         /* not inside a loop statement */
 
-       cont_break_merge(lse);
+       cont_merge(lse);
        top_ls->ls_current->st_notreached = 1;
+       top_ls->ls_current->st_warned = 0;
 }
 
-start_switch_part(expr)
-       struct expr *expr;
+/******** A C T I O N S : S W I T C H ********/
+
+start_switch_part(const)
 {
 /* 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();
+       register struct lint_stack_entry *new = mk_lint_stack_entry(SWITCH);
 
-       if (is_cp_cst(expr))
+       dbg_lint_stack("start_switch_part");
+       if (const)
                hwarning("value in switch statement is constant");
 
-       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;
+       new->LS_CASE = copy_state(top_ls->ls_current, level);
+       new->ls_current->st_notreached = 1;
+       new->ls_current->st_warned = 0;
        top_ls->ls_current->st_notreached = 1;
-       lint_push(lse);
+       top_ls->ls_current->st_warned = 0;
+       lint_push(new);
 }
 
 end_switch_stmt()
 {
+
+       dbg_lint_stack("end_switch_stmt");
        if (top_ls->ls_class == CASE) {
                /* no break after last case or default */
                lint_break_stmt();      /* introduce break */
@@ -814,30 +927,33 @@ end_switch_stmt()
 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();
 
+       dbg_lint_stack("lint_case_stmt");
        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) {
+
+       switch (cs_entry->ls_class) {
+               register struct lint_stack_entry *new;
+
+       case 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);
+
+               new = mk_lint_stack_entry(CASE);
+               remove_settings(new->ls_current, level);
+               lint_push(new);
+               break;
+
+       case CASE:
+               ASSERT(top_ls->ls_previous->ls_class == SWITCH);
                if (dflt) {
                        cs_entry->ls_previous->LS_DEFAULT_MET = 1;
                }
@@ -851,6 +967,11 @@ lint_case_stmt(dflt)
                        copy_state(top_ls->ls_previous->ls_current,
                                        top_ls->ls_previous->ls_level);
                remove_settings(top_ls->ls_current, top_ls->ls_level);
+               break;
+
+       default:
+               NOTREACHED();
+               /*NOTREACHED*/
        }
 }
 
@@ -858,6 +979,7 @@ lint_break_stmt()
 {
        register struct lint_stack_entry *lse = find_wdfc();
 
+       dbg_lint_stack("lint_break_stmt");
        if (!lse)
                return;
 
@@ -867,7 +989,7 @@ lint_break_stmt()
        case DO:
                /* loop break */
                lse->ls_previous->ls_current->st_notreached = 0;
-               cont_break_merge(lse);
+               break_merge(lse);
                break;
 
        case CASE:
@@ -878,115 +1000,146 @@ lint_break_stmt()
                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);
+                       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);
+                       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:
                NOTREACHED();
                /*NOTREACHED*/
        }
        top_ls->ls_current->st_notreached = 1;
+       top_ls->ls_current->st_warned = 0;
 }
 
+PRIVATE
+cont_merge(lse)
+       struct lint_stack_entry *lse;
+{
+       /* merge for continue statements */
+       if (lse->LS_BODY) {
+               merge_states(top_ls->ls_current, lse->LS_BODY,
+                                               lse->ls_level, NORMAL);
+       }
+       else {
+               lse->LS_BODY = copy_state(top_ls->ls_current, lse->ls_level);
+       }
+}
+
+PRIVATE
+break_merge(lse)
+       struct lint_stack_entry *lse;
+{
+       /* merge for break statements */
+       if (lse->LS_LOOP) {
+               merge_states(top_ls->ls_current, lse->LS_LOOP,
+                                               lse->ls_level, NORMAL);
+       }
+       else {
+               lse->LS_LOOP = copy_state(top_ls->ls_current, lse->ls_level);
+       }
+}
+
+/******** A C T I O N S : R E T U R N ********/
+
 lint_start_function()
 {
-       lint_return_stmt(-1);   /* initialization */
+
+       dbg_lint_stack("lint_start_function");
+       valreturned = NORETURN;         /* initialization */
+       return_warned = 0;
        lint_comment_function();
 }
 
 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)
-               );
-       }
+       dbg_lint_stack("lint_end_function");
        /* write the function definition record */
        outdef();
 
-       /* At this stage it is possible that stack_bottom.ls_current is
+       /* At this stage it is possible that top_ls->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.
         */
-       ASSERT(top_ls == &stack_bottom);
-       if (top_ls->ls_current->st_auto_list != 0)
-               free_st_auto_list(top_ls->ls_current->st_auto_list);
+       ASSERT(!top_ls->ls_previous);
+       free_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_implicit_return()
+{
+
+       dbg_lint_stack("lint_implicit_return");
+       if (!top_ls->ls_current->st_notreached) {
+               lint_return_stmt(NOVALRETURNED);
+       }
+}
+
 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;
+
+       dbg_lint_stack("lint_return_stmt");
+       if (valreturned == NORETURN) {
+               /* first return met */
+               register int fund = func_type->tp_fund;
+
+               if (    e == NOVALRETURNED
+               &&      !func_notypegiven
+               &&      fund != VOID
+               &&      fund != ERRONEOUS
+               ) {
+                       warning("function %s declared %s%s but no value returned",
+                               func_name,
+                               (func_type->tp_unsigned && fund != POINTER) ?
+                                       "unsigned " : "",
+                                symbol2str(fund)
+                       );
+                       /* adjust */
+                       e = VALRETURNED;
                }
-               else
-                       ret_e = 1;
-               break;
+               valreturned = e;
+       }
+       else
+       if (valreturned != e && !return_warned) {
+               warning("function %s does not always return a value",
+                       func_name);
+               return_warned = 1;
+       }
+
+       if (!top_ls->ls_current->st_notreached) {
+               set_od_valreturned(valreturned);
        }
-       if (!top_ls->ls_current->st_notreached)
-               set_od_valreturned(e);
        top_ls->ls_current->st_notreached = 1;
+       top_ls->ls_current->st_warned = 0;
 }
 
+/******** A C T I O N S : J U M P ********/
+
 lint_jump_stmt(idf)
        struct idf *idf;
 {
+
+       dbg_lint_stack("lint_jump_stmt");
        top_ls->ls_current->st_notreached = 1;
-       if (!idf->id_def)
-               return;
-       idf->id_def->df_used = 1;
+       top_ls->ls_current->st_warned = 0;
+       if (idf->id_def)
+               idf->id_def->df_used = 1;
 }
 
 lint_label()
@@ -998,6 +1151,7 @@ lint_label()
 */
        register struct auto_def *a = top_ls->ls_current->st_auto_list;
 
+       dbg_lint_stack("lint_label");
        while (a) {
                a->ad_maybe_set = 0;
                a->ad_set = 1;
@@ -1005,12 +1159,17 @@ lint_label()
        }
 }
 
+/******** A C T I O N S : S T A T E M E N T ********/
+
 lint_statement()
 {
-/* Check if this statement can be reached
- */
+/*     Check if this statement can be reached
+*/
+
+       dbg_lint_stack("lint_statement");
        if (s_NOTREACHED) {
                top_ls->ls_current->st_notreached = 1;
+               top_ls->ls_current->st_warned = 0;
                s_NOTREACHED = 0;
        }
        if (DOT == '{' || DOT == ';')
@@ -1030,6 +1189,22 @@ lint_statement()
        }
 }
 
+PRIVATE struct lint_stack_entry *
+mk_lint_stack_entry(cl)
+       int cl;
+{
+/*     Prepare a new stack entry for the lint_stack with class cl.
+       Copy the top ls_current to this entry and set its level.
+*/
+       register struct lint_stack_entry *new = new_lint_stack_entry();
+       
+       new->ls_class = cl;
+       new->ls_current = copy_state(top_ls->ls_current, level);
+       new->ls_level = level;
+
+       return new;
+}
+
 PRIVATE
 lint_push(lse)
        struct lint_stack_entry *lse;
@@ -1049,64 +1224,77 @@ lint_pop()
 #ifdef DEBUG
 /* FOR DEBUGGING */
 
-print_lint_stack()
+PRIVATE
+print_autos(a)
+       struct auto_def *a;
+{
+       while (a) {
+               struct idf *idf = a->ad_idf;
+               struct def *def = idf->id_def;
+
+               print("%s", idf->id_text);
+               print("(lvl=%d)", a->ad_def->df_level);
+               print("(u%ds%dm%d U%dS%d) ",
+                       a->ad_used, a->ad_set, a->ad_maybe_set,
+                       def->df_used, def->df_set
+               );
+               a = a->next;
+       }
+}
+
+PRIVATE
+pr_lint_state(nm, st)
+       char *nm;
+       struct state *st;
+{
+       print("%s: ", nm);
+       if (st) {
+               print("notreached == %d ", st->st_notreached);
+               print_autos(st->st_auto_list);
+       }
+       else {
+               print("NULL");
+       }
+       print("\n");
+}
+
+print_lint_stack(msg)
+       char *msg;
 {
        register struct lint_stack_entry *lse = top_ls;
 
+       print("Lint stack: %s(level=%d)\n", msg, level);
        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");
+               pr_lint_state("  |current", lse->ls_current);
+
                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");
+                       pr_lint_state("   |LS_BREAK", lse->LS_BREAK);
+                       pr_lint_state("   |LS_CASE", lse->LS_CASE);
                        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");
+                       print("   |LS_TEST == %s\n",
+                               lse->LS_TEST == TEST_VAR ? "TEST_VAR" :
+                               lse->LS_TEST == TEST_TRUE ? "TEST_TRUE" :
+                               lse->LS_TEST == TEST_FALSE ? "TEST_FALSE" :
+                               "<<BAD VALUE>>"
+                       );
+                       pr_lint_state("   |LS_BODY", lse->LS_BODY);
+                       pr_lint_state("   |LS_LOOP", lse->LS_LOOP);
                        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");
+                       pr_lint_state("   |LS_IF", lse->LS_IF);
                        break;
+
                default:
                        break;
                }
@@ -1115,17 +1303,6 @@ print_lint_stack()
        print("  |--------------\n\n");
 }
 
-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 DEBUG
 
 #endif LINT
index 2d7f647..7e42dae 100644 (file)
@@ -298,7 +298,10 @@ compile(argc, argv)
 #ifdef PREPEND_SCOPES
                prepend_scopes();
 #endif PREPEND_SCOPES
+
+#ifndef        LINT
                end_code();
+#endif LINT
 
 #ifdef DEBUG
                if (options['u'])       {
index cd7adfb..f361d3f 100644 (file)
@@ -60,7 +60,7 @@
 #include       "expr.h"
 #include       "def.h"
 #ifdef LINT
-#include       "l_state.h"
+#include       "l_lint.h"
 #endif LINT
 
 #ifndef NOPP
@@ -182,10 +182,7 @@ non_function(register struct decspecs *ds; register struct declarator *dc;)
        ]
        {
 #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();
+               lint_non_function_decl(ds, dc);
 #endif LINT
        }
        [
@@ -225,11 +222,11 @@ function(struct decspecs *ds; struct declarator *dc;)
        {
                end_proc(fbytes);
 #ifdef LINT
-               lint_return_stmt(0);    /* implicit return at end of function */
+               lint_implicit_return();
 #endif LINT
                unstack_level();        /* L_FORMAL2 declarations */
 #ifdef LINT
-               check_args_used();
+               lint_end_formals();
 #endif LINT
                unstack_level();        /* L_FORMAL1 declarations */
 #ifdef LINT
index ba7716c..827d6cb 100644 (file)
@@ -7,7 +7,11 @@
 
 #include       "lint.h"
 #include       <system.h>
+#ifndef        LINT
 #include       <em.h>
+#else
+#include       "l_em.h"
+#endif LINT
 #include       "debug.h"
 #include       "botch_free.h"
 #include       <alloc.h>
@@ -109,7 +113,7 @@ unstack_level()
 #endif DEBUG
 
 #ifdef LINT
-       lint_local_level(local_level);
+       lint_end_local(local_level);
 #endif LINT
 
        /*      The implementation below is more careful than strictly
@@ -185,7 +189,7 @@ unstack_world()
        register struct stack_entry *se = local_level->sl_entry;
 
 #ifdef LINT
-       lint_global_level(local_level);
+       lint_end_global(local_level);
 #endif LINT
 
 #ifdef GEN_NM_LIST
index ecdb747..873dd97 100644 (file)
@@ -6,9 +6,14 @@
 /*     STATEMENT SYNTAX PARSER */
 
 {
-#include       <em_code.h>
-
 #include       "lint.h"
+#ifndef        LINT
+#include       <em.h>
+#else
+#include       "l_em.h"
+#include       "l_lint.h"
+#endif LINT
+
 #include       "debug.h"
 #include       "botch_free.h"
 #include       "dbsymtab.h"
 #include       "code.h"
 #include       "stack.h"
 #include       "def.h"
-#ifdef LINT
-#include       "l_lint.h"
-#include       "l_state.h"
-#endif LINT
 #ifdef DBSYMTAB
 #include       <stb.h>
 #endif /* DBSYMTAB */
@@ -215,18 +216,14 @@ 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);
+                       start_while_stmt(expr);
 #endif LINT
-                       }
                }
        ')'
        statement
@@ -236,6 +233,7 @@ while_statement
                        unstack_stmt();
                        free_expression(expr);
 #ifdef LINT
+                       end_loop_body();
                        end_loop_stmt();
 #endif LINT
                }
@@ -253,13 +251,17 @@ do_statement
                {       C_df_ilb(l_body);
                        stack_stmt(l_break, l_continue);
 #ifdef LINT
-                       start_loop_stmt(DO, 1, 1);
+                       start_do_stmt();
 #endif LINT
                }
        statement
        WHILE
        '('
-               {       C_df_ilb(l_continue);
+               {
+#ifdef LINT
+                       end_loop_body();
+#endif LINT
+                       C_df_ilb(l_continue);
                }
        expression(&expr)
                {
@@ -295,9 +297,6 @@ 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
@@ -320,17 +319,10 @@ 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
                        }
                }
        ]?
@@ -339,13 +331,13 @@ for_statement
        ')'
                {
 #ifdef LINT
-                       start_loop_stmt(FOR, const, cond);
+                       start_for_stmt(e_test);
 #endif LINT
                }
        statement
                {
 #ifdef LINT
-                       end_loop_stmt();
+                       end_loop_body();
 #endif LINT
                        C_df_ilb(l_continue);
                        if (e_incr)
@@ -357,6 +349,9 @@ for_statement
                        free_expression(e_init);
                        free_expression(e_test);
                        free_expression(e_incr);
+#ifdef LINT
+                       end_loop_stmt();
+#endif LINT
                }
 ;
 
@@ -372,7 +367,7 @@ switch_statement
                {
                        code_startswitch(&expr);
 #ifdef LINT
-                       start_switch_part(expr);
+                       start_switch_part(is_cp_cst(expr));
 #endif LINT
                }
        ')'
@@ -435,7 +430,7 @@ return_statement
                        do_return_expr(expr);
                        free_expression(expr);
 #ifdef LINT
-                       lint_return_stmt(1);
+                       lint_return_stmt(VALRETURNED);
 #endif LINT
                }
        |
@@ -443,7 +438,7 @@ return_statement
                {
                        do_return();
 #ifdef LINT
-                       lint_return_stmt(0);
+                       lint_return_stmt(NOVALRETURNED);
 #endif LINT
                }
        ]
index 9427107..124c1e3 100644 (file)
@@ -5,7 +5,12 @@
 /* $Header$ */
 /*     S W I T C H - S T A T E M E N T  A D M I N I S T R A T I O N    */
 
+#include       "lint.h"
+#ifndef        LINT
 #include       <em.h>
+#else
+#include       "l_em.h"
+#endif LINT
 #include       "debug.h"
 #include       "botch_free.h"
 #include       <alloc.h>
@@ -73,6 +78,9 @@ code_startswitch(expp)
        sh->sh_type = (*expp)->ex_type; /* the expression switched      */
        /* sh->sh_entries = (struct case_entry *) 0; /* case-entry list */
        sh->sh_expr = *expp;
+#ifdef LINT
+       code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
+#endif
        sh->next = switch_stack;        /* push onto switch-stack       */
        switch_stack = sh;
        C_bra(l_table);                 /* goto start of switch_table   */
@@ -92,7 +100,9 @@ code_endswitch()
        C_bra(sh->sh_break);            /* skip the switch table now    */
        C_df_ilb(sh->sh_table);         /* switch table entry           */
        /* evaluate the switch expr.    */
+#ifndef LINT
        code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
+#endif
        tablabel = data_label();        /* the rom must have a label    */
        C_df_dlb(tablabel);
        C_rom_ilb(sh->sh_default);
index 495e1ab..4ffe7ed 100644 (file)
        allowing re-use.
 */
 
+#include       "lint.h"
+#ifndef        LINT
 #include       <em.h>
+#else
+#include       "l_em.h"
+#endif LINT
+#include       <em_arith.h>
 #include       <em_reg.h>
 #include       <alloc.h>
 #include       <em_mes.h>
 
-#include       "lint.h"
 #include       "debug.h"
 #include       "util.h"
 #include       "use_tmp.h"