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
|
LINT = /usr/bin/lint
|
||||||
LINTFLAGS =
|
LINTFLAGS =
|
||||||
|
|
||||||
MYLINT = ../lint
|
MYLINT = ../lpass2/lint
|
||||||
MYLINTFLAGS = #-xh
|
MYLINTFLAGS = #-xh
|
||||||
|
|
||||||
#EXCLEXCLEXCLEXCL
|
#EXCLEXCLEXCLEXCL
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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_fund != POINTER
|
||||||
|| type->tp_up->tp_fund != CHAR
|
|| 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) {
|
||||||
|
/* 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->ar_class = ArgString;
|
||||||
arg->CAS_VALUE = e->SG_VALUE;
|
arg->CAS_VALUE = sc->sc_value;
|
||||||
arg->CAS_LEN = e->SG_LEN - 1; /* SG_LEN includes the \0 */
|
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;
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue