lint: printf testing and FORMATs

This commit is contained in:
dick 1988-11-03 15:18:46 +00:00
parent 7267917050
commit 4ed20925c6
9 changed files with 107 additions and 32 deletions

View file

@ -125,7 +125,7 @@ SRC = $(CSRC) $(LCSRC) $(GCSRC)
LINT = /usr/bin/lint LINT = /usr/bin/lint
LINTFLAGS = LINTFLAGS =
MYLINT = ../lint MYLINT = ../lpass2/lint
MYLINTFLAGS = #-xh MYLINTFLAGS = #-xh
#EXCLEXCLEXCLEXCL #EXCLEXCLEXCLEXCL

View file

@ -274,9 +274,13 @@ declare_idf(ds, dc, lvl)
#ifdef LINT #ifdef LINT
if ( def && def->df_level < lvl 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 on a more global level
*/ */
warning("%s is already defined as a %s", warning("%s is already defined as a %s",

View file

@ -14,6 +14,9 @@
#include <alloc.h> #include <alloc.h>
#include "arith.h" #include "arith.h"
#include "l_state.h" #include "l_state.h"
#include "l_comment.h"
extern char loptions[];
/* Since the lexical analyser does a one-token look-ahead, pseudo- /* Since the lexical analyser does a one-token look-ahead, pseudo-
comments are read too soon. This is remedied by first storing them 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 varargsN = -1;
static int argsused; static int argsused;
static int formatN; static int formatN;
static int formatVAR;
static char *format; static char *format;
static char *prev_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_ARGSUSED; /* function does not use all args */
int f_FORMATn; /* argument f_FORMATn is f_FORMAT */ int f_FORMATn; /* argument f_FORMATn is f_FORMAT */
char *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() lint_comment_ahead()
{ {
@ -43,7 +54,7 @@ lint_comment_ahead()
lint_comment_function() lint_comment_function()
{ {
f_ARGSUSED = argsused; f_ARGSUSED = argsused | loptions['v'];
argsused = 0; argsused = 0;
f_VARARGSn = varargsN; f_VARARGSn = varargsN;
@ -55,6 +66,9 @@ lint_comment_function()
if (format) if (format)
prev_format = format; prev_format = format;
format = 0; format = 0;
f_FORMATvar = formatVAR;
formatVAR = 0;
} }
static char buf[1000]; static char buf[1000];
@ -97,14 +111,22 @@ lint_end_comment()
} }
else else
if (strncmp(bufpos, "VARARGS", 7) == 0) { if (strncmp(bufpos, "VARARGS", 7) == 0) {
varargsN = isdigit(bufpos[7]) ? atoi(&bufpos[7]) : 0; bufpos += 7;
varargsN = isdigit(*bufpos) ? atoi(bufpos) : 0;
} }
else else
if (strncmp(bufpos, "FORMAT", 6) == 0 && isdigit(bufpos[6])) { 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; varargsN = argn + 1;
make_format(argn, &bufpos[7]); if (*bufpos == 'v') {
/* something like FORMAT3v */
formatVAR = 1;
bufpos++;
}
make_format(argn, bufpos);
} }
} }

View file

@ -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_ARGSUSED; /* function does not use all args */
extern int f_FORMATn; /* argument f_FORMATn is f_FORMAT */ extern int f_FORMATn; /* argument f_FORMATn is f_FORMAT */
extern char *f_FORMAT; extern char *f_FORMAT;
extern int f_FORMATvar; /* but the formal argument may be
absent because of varargs.h */

View file

@ -36,13 +36,8 @@ static struct expr_state *lint_oper();
lint_init() lint_init()
{ {
/* Allocate some memory for the global stack_bottom lint_init_comment();
* and some other initializations lint_init_stack();
*/
extern struct lint_stack_entry stack_bottom;
stack_bottom.ls_current = new_state();
} }
pre_lint_expr(expr, val, used) pre_lint_expr(expr, val, used)
@ -357,7 +352,7 @@ expr_ignored(expr)
break; break;
case Value: case Value:
hwarning("identifier as statement"); hwarning("value as statement");
break; break;
default: /* String Float */ default: /* String Float */

View file

@ -22,6 +22,7 @@
#include "idf.h" #include "idf.h"
#include "level.h" #include "level.h"
#include "label.h" #include "label.h"
#include "code.h"
#include "expr.h" #include "expr.h"
#include "l_lint.h" #include "l_lint.h"
#include "l_comment.h" #include "l_comment.h"
@ -157,8 +158,10 @@ lint_formals()
} }
if (f_FORMAT && nrargs == f_FORMATn) { if (f_FORMAT && nrargs == f_FORMATn) {
if ( type->tp_fund != POINTER if ( !f_FORMATvar
|| type->tp_up->tp_fund != CHAR && ( type->tp_fund != POINTER
|| type->tp_up->tp_fund != CHAR
)
) { ) {
warning("format parameter %d is not pointer to char", warning("format parameter %d is not pointer to char",
nrargs); nrargs);
@ -180,19 +183,47 @@ lint_formals()
se = se->next; 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) { if (f_VARARGSn > nrargs) {
warning("VARARGS%d function has only %d argument%s", warning("VARARGS%d function has only %d argument%s",
f_VARARGSn, nrargs, nrargs == 1 ? "" : "s" f_VARARGSn, nrargs, nrargs == 1 ? "" : "s"
); );
f_VARARGSn = nrargs; 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; OutDef.od_nrargs = nrargs;
} }
@ -465,10 +496,24 @@ fill_arg(e)
arg->ar_class = ArgConst; arg->ar_class = ArgConst;
arg->CAA_VALUE = e->VL_VALUE; arg->CAA_VALUE = e->VL_VALUE;
} }
else if (e->ex_class == String) { else if (e->ex_class == Value && e->VL_CLASS == Label) {
arg->ar_class = ArgString; /* it may be a string; let's look it up */
arg->CAS_VALUE = e->SG_VALUE; register struct string_cst *sc = str_list;
arg->CAS_LEN = e->SG_LEN - 1; /* SG_LEN includes the \0 */
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 { else {
arg->ar_class = ArgExpr; arg->ar_class = ArgExpr;

View file

@ -48,6 +48,13 @@ struct brace *top_br = &brace_bottom;
static print_autos(); static print_autos();
lint_init_stack()
{
/* Allocate some memory for the global stack_bottom
*/
stack_bottom.ls_current = new_state();
}
lint_start_local() lint_start_local()
{ {
register struct brace *br = new_brace(); register struct brace *br = new_brace();
@ -332,7 +339,6 @@ check_args_used()
register struct def *def = se->se_idf->id_def; register struct def *def = se->se_idf->id_def;
if ( (def && !def->df_used) if ( (def && !def->df_used)
&& !loptions['v']
&& !(f_ARGSUSED || LINTLIB) && !(f_ARGSUSED || LINTLIB)
) { ) {
def_warning(def, "argument %s not used in function %s", def_warning(def, "argument %s not used in function %s",

View file

@ -96,9 +96,6 @@ main(argc, argv)
inc_max = 10; inc_max = 10;
init_pp(); /* initialise the preprocessor macros */ init_pp(); /* initialise the preprocessor macros */
#ifdef LINT
lint_init();
#endif LINT
#endif NOPP #endif NOPP
/* Note: source file "-" indicates that the source is supplied /* Note: source file "-" indicates that the source is supplied
@ -116,6 +113,9 @@ main(argc, argv)
do_option(par); do_option(par);
argc--, argv++; argc--, argv++;
} }
#ifdef LINT
lint_init();
#endif LINT
compile(argc - 1, &argv[1]); compile(argc - 1, &argv[1]);
#ifdef DEBUG #ifdef DEBUG

View file

@ -80,6 +80,7 @@ next_option: /* to allow combined one-char options */
case 'b': /* don't report unreachable break-statements */ case 'b': /* don't report unreachable break-statements */
case 'x': /* complain about unused extern declared variables */ case 'x': /* complain about unused extern declared variables */
case 'u': /* no "used but not defined"; for pass 2 */ case 'u': /* no "used but not defined"; for pass 2 */
case 'L': /* lintlibrary */
loptions[opt] = 1; loptions[opt] = 1;
goto next_option; goto next_option;
#endif LINT #endif LINT