lint: printf testing and FORMATs
This commit is contained in:
parent
7267917050
commit
4ed20925c6
|
@ -125,7 +125,7 @@ SRC = $(CSRC) $(LCSRC) $(GCSRC)
|
|||
LINT = /usr/bin/lint
|
||||
LINTFLAGS =
|
||||
|
||||
MYLINT = ../lint
|
||||
MYLINT = ../lpass2/lint
|
||||
MYLINTFLAGS = #-xh
|
||||
|
||||
#EXCLEXCLEXCLEXCL
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include <alloc.h>
|
||||
#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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue