diff --git a/lang/cem/cemcom/Makefile b/lang/cem/cemcom/Makefile index 766165bb0..1c744df85 100644 --- a/lang/cem/cemcom/Makefile +++ b/lang/cem/cemcom/Makefile @@ -125,7 +125,7 @@ SRC = $(CSRC) $(LCSRC) $(GCSRC) LINT = /usr/bin/lint LINTFLAGS = -MYLINT = ../lint +MYLINT = ../lpass2/lint MYLINTFLAGS = #-xh #EXCLEXCLEXCLEXCL diff --git a/lang/cem/cemcom/idf.c b/lang/cem/cemcom/idf.c index 8a48ccf9a..e648e8327 100644 --- a/lang/cem/cemcom/idf.c +++ b/lang/cem/cemcom/idf.c @@ -274,9 +274,13 @@ declare_idf(ds, dc, lvl) #ifdef LINT if ( def && def->df_level < lvl - && !(lvl == L_FORMAL2 || def->df_level == L_UNIVERSAL) + && !( lvl == L_FORMAL2 + || def->df_level == L_UNIVERSAL + || sc == GLOBAL + || sc == EXTERN + ) ) { - /* there is already a definition for this name + /* there is already a definition for this non-extern name on a more global level */ warning("%s is already defined as a %s", diff --git a/lang/cem/cemcom/l_comment.c b/lang/cem/cemcom/l_comment.c index cd2bfb5f0..64e8ed753 100644 --- a/lang/cem/cemcom/l_comment.c +++ b/lang/cem/cemcom/l_comment.c @@ -14,6 +14,9 @@ #include #include "arith.h" #include "l_state.h" +#include "l_comment.h" + +extern char loptions[]; /* Since the lexical analyser does a one-token look-ahead, pseudo- comments are read too soon. This is remedied by first storing them @@ -25,6 +28,7 @@ static int notreached; static int varargsN = -1; static int argsused; static int formatN; +static int formatVAR; static char *format; static char *prev_format; @@ -34,6 +38,13 @@ int f_VARARGSn; /* function with variable # of args */ int f_ARGSUSED; /* function does not use all args */ int f_FORMATn; /* argument f_FORMATn is f_FORMAT */ char *f_FORMAT; +int f_FORMATvar; /* but the formal argument may be + absent because of varargs.h */ + +lint_init_comment() +{ + LINTLIB = loptions['L']; +} lint_comment_ahead() { @@ -43,7 +54,7 @@ lint_comment_ahead() lint_comment_function() { - f_ARGSUSED = argsused; + f_ARGSUSED = argsused | loptions['v']; argsused = 0; f_VARARGSn = varargsN; @@ -55,6 +66,9 @@ lint_comment_function() if (format) prev_format = format; format = 0; + + f_FORMATvar = formatVAR; + formatVAR = 0; } static char buf[1000]; @@ -97,14 +111,22 @@ lint_end_comment() } else if (strncmp(bufpos, "VARARGS", 7) == 0) { - varargsN = isdigit(bufpos[7]) ? atoi(&bufpos[7]) : 0; + bufpos += 7; + varargsN = isdigit(*bufpos) ? atoi(bufpos) : 0; } else if (strncmp(bufpos, "FORMAT", 6) == 0 && isdigit(bufpos[6])) { - int argn = bufpos[6] - '0'; + register int argn; + bufpos += 6; + argn = *bufpos++ - '0'; varargsN = argn + 1; - make_format(argn, &bufpos[7]); + if (*bufpos == 'v') { + /* something like FORMAT3v */ + formatVAR = 1; + bufpos++; + } + make_format(argn, bufpos); } } diff --git a/lang/cem/cemcom/l_comment.h b/lang/cem/cemcom/l_comment.h index 9b8776da7..9340b0820 100644 --- a/lang/cem/cemcom/l_comment.h +++ b/lang/cem/cemcom/l_comment.h @@ -10,4 +10,6 @@ extern int f_VARARGSn; /* function with variable # of args */ extern int f_ARGSUSED; /* function does not use all args */ extern int f_FORMATn; /* argument f_FORMATn is f_FORMAT */ extern char *f_FORMAT; +extern int f_FORMATvar; /* but the formal argument may be + absent because of varargs.h */ diff --git a/lang/cem/cemcom/l_lint.c b/lang/cem/cemcom/l_lint.c index 45c2259de..f28e47f64 100644 --- a/lang/cem/cemcom/l_lint.c +++ b/lang/cem/cemcom/l_lint.c @@ -36,13 +36,8 @@ static struct expr_state *lint_oper(); 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(); + lint_init_comment(); + lint_init_stack(); } pre_lint_expr(expr, val, used) @@ -357,7 +352,7 @@ expr_ignored(expr) break; case Value: - hwarning("identifier as statement"); + hwarning("value as statement"); break; default: /* String Float */ diff --git a/lang/cem/cemcom/l_outdef.c b/lang/cem/cemcom/l_outdef.c index 24f670bc7..eba9c38b1 100644 --- a/lang/cem/cemcom/l_outdef.c +++ b/lang/cem/cemcom/l_outdef.c @@ -22,6 +22,7 @@ #include "idf.h" #include "level.h" #include "label.h" +#include "code.h" #include "expr.h" #include "l_lint.h" #include "l_comment.h" @@ -157,8 +158,10 @@ lint_formals() } if (f_FORMAT && nrargs == f_FORMATn) { - if ( type->tp_fund != POINTER - || type->tp_up->tp_fund != CHAR + if ( !f_FORMATvar + && ( type->tp_fund != POINTER + || type->tp_up->tp_fund != CHAR + ) ) { warning("format parameter %d is not pointer to char", nrargs); @@ -180,19 +183,47 @@ lint_formals() se = se->next; } + if (f_FORMAT) { + /* f_FORMAT has not been consumed, perhaps due to + a varargs-like construction; add erroneous ArgFormals + until f_FORMATn, then an ArgString, if necessary. + */ + if (!f_FORMATvar) { + warning("FORMAT%d function has only %d argument%s", + f_FORMATn, nrargs, nrargs == 1 ? "" : "s" + ); + } + + while (nrargs < f_FORMATn) { + register struct argument *arg = new_argument(); + + arg->ar_type = error_type; + arg->ar_class = ArgFormal; + *hook = arg; + hook = &arg->next; + nrargs++; + } + if (nrargs == f_FORMATn) { + register struct argument *arg = new_argument(); + + arg->ar_type = string_type; + arg->ar_class = ArgString; + arg->CAS_VALUE = f_FORMAT; + arg->CAS_LEN = strlen(f_FORMAT); + f_FORMAT = 0; + *hook = arg; + hook = &arg->next; + nrargs++; + } + /* life is full of duplicated code; this is no good */ + } + if (f_VARARGSn > nrargs) { warning("VARARGS%d function has only %d argument%s", f_VARARGSn, nrargs, nrargs == 1 ? "" : "s" ); f_VARARGSn = nrargs; } - if (f_FORMAT) { - warning("FORMAT%d function has only %d argument%s", - f_FORMATn, nrargs, nrargs == 1 ? "" : "s" - ); - f_FORMAT = 0; - } - OutDef.od_nrargs = nrargs; } @@ -465,10 +496,24 @@ fill_arg(e) arg->ar_class = ArgConst; arg->CAA_VALUE = e->VL_VALUE; } - else if (e->ex_class == String) { - arg->ar_class = ArgString; - arg->CAS_VALUE = e->SG_VALUE; - arg->CAS_LEN = e->SG_LEN - 1; /* SG_LEN includes the \0 */ + else if (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; + + while (sc) { + if (sc->sc_dlb == e->VL_LBL) + break; + sc = sc->next; + } + if (sc) { + /* it was a string */ + arg->ar_class = ArgString; + arg->CAS_VALUE = sc->sc_value; + arg->CAS_LEN = sc->sc_len - 1; /* included the \0 */ + } + else { + arg->ar_class = ArgExpr; + } } else { arg->ar_class = ArgExpr; diff --git a/lang/cem/cemcom/l_states.c b/lang/cem/cemcom/l_states.c index b4d97ab91..0c6df5147 100644 --- a/lang/cem/cemcom/l_states.c +++ b/lang/cem/cemcom/l_states.c @@ -48,6 +48,13 @@ struct brace *top_br = &brace_bottom; static print_autos(); +lint_init_stack() +{ +/* Allocate some memory for the global stack_bottom + */ + stack_bottom.ls_current = new_state(); +} + lint_start_local() { register struct brace *br = new_brace(); @@ -332,7 +339,6 @@ check_args_used() register struct def *def = se->se_idf->id_def; if ( (def && !def->df_used) - && !loptions['v'] && !(f_ARGSUSED || LINTLIB) ) { def_warning(def, "argument %s not used in function %s", diff --git a/lang/cem/cemcom/main.c b/lang/cem/cemcom/main.c index b8104bf1b..607a74182 100644 --- a/lang/cem/cemcom/main.c +++ b/lang/cem/cemcom/main.c @@ -96,9 +96,6 @@ 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 @@ -116,6 +113,9 @@ main(argc, argv) do_option(par); argc--, argv++; } +#ifdef LINT + lint_init(); +#endif LINT compile(argc - 1, &argv[1]); #ifdef DEBUG diff --git a/lang/cem/cemcom/options.c b/lang/cem/cemcom/options.c index e873061e1..2d627f94b 100644 --- a/lang/cem/cemcom/options.c +++ b/lang/cem/cemcom/options.c @@ -80,6 +80,7 @@ next_option: /* to allow combined one-char options */ 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 */ + case 'L': /* lintlibrary */ loptions[opt] = 1; goto next_option; #endif LINT