formats introduced in lint
This commit is contained in:
parent
ac21f8d98a
commit
e66f3adc06
13 changed files with 325 additions and 166 deletions
|
@ -74,7 +74,7 @@ LLlex()
|
||||||
}
|
}
|
||||||
else { /* read ahead and return the old one */
|
else { /* read ahead and return the old one */
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
move_NOT2s();
|
lint_comment_ahead();
|
||||||
#endif LINT
|
#endif LINT
|
||||||
dot = ahead;
|
dot = ahead;
|
||||||
/* the following test is performed due to the dual
|
/* the following test is performed due to the dual
|
||||||
|
@ -477,8 +477,8 @@ skipcomment()
|
||||||
NoUnstack++;
|
NoUnstack++;
|
||||||
LoadChar(c);
|
LoadChar(c);
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
lint_comment(-2);
|
lint_start_comment();
|
||||||
lint_comment(c);
|
lint_comment_char(c);
|
||||||
#endif LINT
|
#endif LINT
|
||||||
do {
|
do {
|
||||||
while (c != '*') {
|
while (c != '*') {
|
||||||
|
@ -487,18 +487,24 @@ skipcomment()
|
||||||
else
|
else
|
||||||
if (c == EOI) {
|
if (c == EOI) {
|
||||||
NoUnstack--;
|
NoUnstack--;
|
||||||
|
#ifdef LINT
|
||||||
|
lint_end_comment();
|
||||||
|
#endif LINT
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LoadChar(c);
|
LoadChar(c);
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
lint_comment(c);
|
lint_comment_char(c);
|
||||||
#endif LINT
|
#endif LINT
|
||||||
} /* last Character seen was '*' */
|
} /* last Character seen was '*' */
|
||||||
LoadChar(c);
|
LoadChar(c);
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
lint_comment(c);
|
lint_comment_char(c);
|
||||||
#endif LINT
|
#endif LINT
|
||||||
} while (c != '/');
|
} while (c != '/');
|
||||||
|
#ifdef LINT
|
||||||
|
lint_end_comment();
|
||||||
|
#endif LINT
|
||||||
NoUnstack--;
|
NoUnstack--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -448,6 +448,7 @@ arith.o: expr.h
|
||||||
arith.o: field.h
|
arith.o: field.h
|
||||||
arith.o: idf.h
|
arith.o: idf.h
|
||||||
arith.o: label.h
|
arith.o: label.h
|
||||||
|
arith.o: lint.h
|
||||||
arith.o: mes.h
|
arith.o: mes.h
|
||||||
arith.o: noRoption.h
|
arith.o: noRoption.h
|
||||||
arith.o: nobitfield.h
|
arith.o: nobitfield.h
|
||||||
|
@ -821,6 +822,7 @@ l_states.o: expr.h
|
||||||
l_states.o: file_info.h
|
l_states.o: file_info.h
|
||||||
l_states.o: idf.h
|
l_states.o: idf.h
|
||||||
l_states.o: l_brace.h
|
l_states.o: l_brace.h
|
||||||
|
l_states.o: l_comment.h
|
||||||
l_states.o: l_lint.h
|
l_states.o: l_lint.h
|
||||||
l_states.o: l_outdef.h
|
l_states.o: l_outdef.h
|
||||||
l_states.o: l_state.h
|
l_states.o: l_state.h
|
||||||
|
@ -883,6 +885,7 @@ l_outdef.o: field.h
|
||||||
l_outdef.o: file_info.h
|
l_outdef.o: file_info.h
|
||||||
l_outdef.o: idf.h
|
l_outdef.o: idf.h
|
||||||
l_outdef.o: l_class.h
|
l_outdef.o: l_class.h
|
||||||
|
l_outdef.o: l_comment.h
|
||||||
l_outdef.o: l_lint.h
|
l_outdef.o: l_lint.h
|
||||||
l_outdef.o: l_outdef.h
|
l_outdef.o: l_outdef.h
|
||||||
l_outdef.o: label.h
|
l_outdef.o: label.h
|
||||||
|
|
|
@ -339,6 +339,7 @@ function2pointer(exp)
|
||||||
string2pointer(ex)
|
string2pointer(ex)
|
||||||
register struct expr *ex;
|
register struct expr *ex;
|
||||||
{
|
{
|
||||||
|
#ifndef LINT
|
||||||
/* The expression, which must be a string constant, is converted
|
/* The expression, which must be a string constant, is converted
|
||||||
to a pointer to the string-containing area.
|
to a pointer to the string-containing area.
|
||||||
*/
|
*/
|
||||||
|
@ -349,6 +350,7 @@ string2pointer(ex)
|
||||||
ex->VL_CLASS = Label;
|
ex->VL_CLASS = Label;
|
||||||
ex->VL_LBL = lbl;
|
ex->VL_LBL = lbl;
|
||||||
ex->VL_VALUE = (arith)0;
|
ex->VL_VALUE = (arith)0;
|
||||||
|
#endif LINT
|
||||||
}
|
}
|
||||||
|
|
||||||
opnd2integral(expp, oper)
|
opnd2integral(expp, oper)
|
||||||
|
|
|
@ -74,6 +74,7 @@ init_code(dst_file)
|
||||||
|
|
||||||
static struct string_cst *str_list = 0;
|
static struct string_cst *str_list = 0;
|
||||||
|
|
||||||
|
#ifndef LINT
|
||||||
code_string(val, len, dlb)
|
code_string(val, len, dlb)
|
||||||
char *val;
|
char *val;
|
||||||
int len;
|
int len;
|
||||||
|
@ -88,6 +89,7 @@ code_string(val, len, dlb)
|
||||||
sc->sc_len = len;
|
sc->sc_len = len;
|
||||||
sc->sc_dlb = dlb;
|
sc->sc_dlb = dlb;
|
||||||
}
|
}
|
||||||
|
#endif LINT
|
||||||
|
|
||||||
def_strings(sc)
|
def_strings(sc)
|
||||||
register struct string_cst *sc;
|
register struct string_cst *sc;
|
||||||
|
|
|
@ -365,8 +365,9 @@ p1_expr(lvl, expr)
|
||||||
char *bts2str();
|
char *bts2str();
|
||||||
|
|
||||||
print(
|
print(
|
||||||
"%s\n",
|
"\"%s\"\n",
|
||||||
bts2str(expr->SG_VALUE, expr->SG_LEN, next_transient())
|
bts2str(expr->SG_VALUE, expr->SG_LEN-1,
|
||||||
|
next_transient())
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -462,6 +462,10 @@ is_ld_cst(expr)
|
||||||
/* An expression is a `load-time constant' if it is of the form
|
/* An expression is a `load-time constant' if it is of the form
|
||||||
<idf> +/- <integral> or <integral>.
|
<idf> +/- <integral> or <integral>.
|
||||||
*/
|
*/
|
||||||
|
#ifdef LINT
|
||||||
|
if (expr->ex_class == String)
|
||||||
|
return 1;
|
||||||
|
#endif LINT
|
||||||
return expr->ex_lvalue == 0 && expr->ex_class == Value;
|
return expr->ex_lvalue == 0 && expr->ex_class == Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,6 @@ gen_idf()
|
||||||
*/
|
*/
|
||||||
static int name_cnt;
|
static int name_cnt;
|
||||||
char buff[100];
|
char buff[100];
|
||||||
char *sprint();
|
|
||||||
|
|
||||||
sprint(buff, "#%d in %s, line %u",
|
sprint(buff, "#%d in %s, line %u",
|
||||||
++name_cnt, dot.tk_file, dot.tk_line);
|
++name_cnt, dot.tk_file, dot.tk_line);
|
||||||
|
|
|
@ -489,10 +489,12 @@ check_ival(expp, tp)
|
||||||
else /* e.g., int a; int *p = &a; */
|
else /* e.g., int a; int *p = &a; */
|
||||||
C_con_dnam(idf->id_text, expr->VL_VALUE);
|
C_con_dnam(idf->id_text, expr->VL_VALUE);
|
||||||
}
|
}
|
||||||
|
#ifndef LINT
|
||||||
else {
|
else {
|
||||||
ASSERT(expr->VL_CLASS == Label);
|
ASSERT(expr->VL_CLASS == Label);
|
||||||
C_con_dlb(expr->VL_LBL, expr->VL_VALUE);
|
C_con_dlb(expr->VL_LBL, expr->VL_VALUE);
|
||||||
}
|
}
|
||||||
|
#endif LINT
|
||||||
break;
|
break;
|
||||||
#ifndef NOFLOAT
|
#ifndef NOFLOAT
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
|
|
|
@ -5,10 +5,13 @@
|
||||||
/* $Header$ */
|
/* $Header$ */
|
||||||
/* Lint-specific comment handling */
|
/* Lint-specific comment handling */
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "lint.h"
|
#include "lint.h"
|
||||||
|
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
|
|
||||||
|
#include <alloc.h>
|
||||||
#include "arith.h"
|
#include "arith.h"
|
||||||
#include "l_state.h"
|
#include "l_state.h"
|
||||||
|
|
||||||
|
@ -21,124 +24,162 @@
|
||||||
static int notreached;
|
static int notreached;
|
||||||
static int varargsN = -1;
|
static int varargsN = -1;
|
||||||
static int argsused;
|
static int argsused;
|
||||||
static check_pseudo();
|
static int formatN;
|
||||||
|
static char *format;
|
||||||
|
static char *prev_format;
|
||||||
|
|
||||||
int LINTLIB; /* file is lint library */
|
int LINTLIB; /* file is lint library */
|
||||||
int s_NOTREACHED; /* statement not reached */
|
int s_NOTREACHED; /* statement not reached */
|
||||||
int f_VARARGSn; /* function with variable # of args */
|
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 */
|
||||||
|
char *f_FORMAT;
|
||||||
|
|
||||||
set_not_reached()
|
lint_comment_ahead()
|
||||||
{
|
|
||||||
notreached = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
move_NOT2s()
|
|
||||||
{
|
{
|
||||||
s_NOTREACHED = notreached;
|
s_NOTREACHED = notreached;
|
||||||
notreached = 0;
|
notreached = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_varargs(n)
|
lint_comment_function()
|
||||||
{
|
|
||||||
varargsN = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
move_VAR2f()
|
|
||||||
{
|
|
||||||
f_VARARGSn = varargsN;
|
|
||||||
varargsN = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_argsused(n)
|
|
||||||
{
|
|
||||||
argsused = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
move_ARG2f()
|
|
||||||
{
|
{
|
||||||
f_ARGSUSED = argsused;
|
f_ARGSUSED = argsused;
|
||||||
argsused = 0;
|
argsused = 0;
|
||||||
|
|
||||||
|
f_VARARGSn = varargsN;
|
||||||
|
varargsN = -1;
|
||||||
|
|
||||||
|
f_FORMATn = formatN;
|
||||||
|
formatN = 0;
|
||||||
|
f_FORMAT = format;
|
||||||
|
if (format)
|
||||||
|
prev_format = format;
|
||||||
|
format = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_lintlib()
|
static char buf[1000];
|
||||||
|
static char *bufpos; /* next free position in buf */
|
||||||
|
|
||||||
|
lint_start_comment()
|
||||||
{
|
{
|
||||||
LINTLIB = 1;
|
bufpos = &buf[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IN_SPACE 0
|
lint_comment_char(c)
|
||||||
#define IN_WORD 1
|
|
||||||
#define IN_COMMENT 2
|
|
||||||
|
|
||||||
lint_comment(c)
|
|
||||||
int c;
|
int c;
|
||||||
{
|
{
|
||||||
/* This function is called with every character between /_* and *_/ (the
|
/* This function is called with every character between /_* and *_/ */
|
||||||
* _underscores are used because comment in C doesn't nest).
|
if (bufpos - &buf[0] < sizeof(buf)-1)
|
||||||
* It looks for pseudocomments.
|
*bufpos++ = (char)c;
|
||||||
* In this version it is allowed that 'keyword' is followed by rubbish.
|
|
||||||
* At the start of each comment the function should be initialized by
|
|
||||||
* calling it with c = -2.
|
|
||||||
* I am not sure if this way of information hiding is a good solution.
|
|
||||||
*/
|
|
||||||
static int position; /* IN_SPACE, IN_WORD, IN_COMMENT */
|
|
||||||
static char buf[12];
|
|
||||||
static int i; /* next free position in buf */
|
|
||||||
|
|
||||||
if (c == -2) {
|
|
||||||
position = IN_SPACE;
|
|
||||||
i = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position == IN_COMMENT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (position == IN_SPACE) {
|
|
||||||
if (c == ' ' || c == '\t')
|
|
||||||
return;
|
|
||||||
position = IN_WORD;
|
|
||||||
}
|
|
||||||
/* position == IN_WORD */
|
|
||||||
if (c == ' ' || c == '\t' || c == '*') {
|
|
||||||
position = IN_COMMENT;
|
|
||||||
check_pseudo(buf, i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (i < 12)
|
|
||||||
buf[i++] = (char)c;
|
|
||||||
else
|
|
||||||
position = IN_COMMENT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <ctype.h>
|
lint_end_comment()
|
||||||
|
|
||||||
static
|
|
||||||
check_pseudo(buf, i)
|
|
||||||
char *buf;
|
|
||||||
{
|
{
|
||||||
/* Look if the i characters in buf are aequivalent with one of the
|
*bufpos++ = '\0';
|
||||||
* strings N_OTREACHED, V_ARARGS[n], A_RGSUSED, L_INTLIBRARY
|
bufpos = &buf[0];
|
||||||
* (the u_nderscores are there to not confuse (UNIX) lint)
|
|
||||||
*/
|
/* skip initial blanks */
|
||||||
buf[i++] = '\0';
|
while (*bufpos && isspace(*bufpos)) {
|
||||||
if (strcmp(buf, "NOTREACHED") == 0) {
|
bufpos++;
|
||||||
set_not_reached();
|
|
||||||
}
|
}
|
||||||
else if (strcmp(buf, "ARGSUSED") == 0) {
|
|
||||||
set_argsused(1);
|
/* now test for one of the pseudo-comments */
|
||||||
|
if (strncmp(bufpos, "NOTREACHED", 10) == 0) {
|
||||||
|
notreached = 1;
|
||||||
}
|
}
|
||||||
else if (strcmp(buf, "LINTLIBRARY") == 0) {
|
else
|
||||||
set_lintlib();
|
if (strncmp(bufpos, "ARGSUSED", 8) == 0) {
|
||||||
|
argsused = 1;
|
||||||
}
|
}
|
||||||
else if (strncmp(buf, "VARARGS", 7) == 0) {
|
else
|
||||||
if (i == 8) {
|
if (strncmp(bufpos, "LINTLIBRARY", 11) == 0) {
|
||||||
set_varargs(0);
|
LINTLIB = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (strncmp(bufpos, "VARARGS", 7) == 0) {
|
||||||
|
varargsN = isdigit(bufpos[7]) ? atoi(&bufpos[7]) : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (strncmp(bufpos, "FORMAT", 6) == 0 && isdigit(bufpos[6])) {
|
||||||
|
int argn = bufpos[6] - '0';
|
||||||
|
|
||||||
|
varargsN = argn + 1;
|
||||||
|
make_format(argn, &bufpos[7]);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We use a small FSA to skip layout inside formats, but to preserve
|
||||||
|
a space between letters and digits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define NONE 0
|
||||||
|
#define LETGIT 1
|
||||||
|
#define LETGITSPACE 2
|
||||||
|
|
||||||
|
make_format(argn, oldf)
|
||||||
|
int argn;
|
||||||
|
char *oldf;
|
||||||
|
{
|
||||||
|
register char *newf;
|
||||||
|
register int last_stat;
|
||||||
|
|
||||||
|
while (*oldf && *oldf != '$') {
|
||||||
|
oldf++;
|
||||||
|
}
|
||||||
|
if (!*oldf) {
|
||||||
|
/* no format given, repeat previous format */
|
||||||
|
if (!prev_format) {
|
||||||
|
warning("format missing and no previous format");
|
||||||
}
|
}
|
||||||
else if (i == 9 && isdigit(buf[7])) {
|
formatN = argn;
|
||||||
set_varargs(atoi(&buf[7]));
|
format = prev_format;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (*oldf++ != '$') {
|
||||||
|
warning("no format in FORMAT pseudo-comment");
|
||||||
|
format = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* there is a new format to be composed */
|
||||||
|
newf = Malloc(strlen(oldf));
|
||||||
|
/* certainly enough and probably not overly too much */
|
||||||
|
formatN = argn;
|
||||||
|
format = newf;
|
||||||
|
|
||||||
|
last_stat = NONE;
|
||||||
|
while (*oldf && *oldf != '$') {
|
||||||
|
register char ch = *oldf++;
|
||||||
|
|
||||||
|
if (isspace(ch)) {
|
||||||
|
if (last_stat == LETGIT)
|
||||||
|
last_stat = LETGITSPACE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (isalnum(ch)) {
|
||||||
|
switch (last_stat) {
|
||||||
|
case NONE:
|
||||||
|
last_stat = LETGIT;
|
||||||
|
break;
|
||||||
|
case LETGITSPACE:
|
||||||
|
*newf++ = ' ';
|
||||||
|
last_stat = LETGIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*newf++ = ch;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last_stat = NONE;
|
||||||
|
*newf++ = ch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (*oldf != '$') {
|
||||||
|
warning("no end of format in FORMAT pseudo-comment");
|
||||||
|
format = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*newf++ = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif LINT
|
#endif LINT
|
||||||
|
|
13
lang/cem/cemcom/l_comment.h
Normal file
13
lang/cem/cemcom/l_comment.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||||
|
*/
|
||||||
|
/* $Header$ */
|
||||||
|
|
||||||
|
extern int LINTLIB; /* file is lint library */
|
||||||
|
extern int s_NOTREACHED; /* statement not reached */
|
||||||
|
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;
|
||||||
|
|
|
@ -24,12 +24,13 @@
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "l_lint.h"
|
#include "l_lint.h"
|
||||||
|
#include "l_comment.h"
|
||||||
#include "l_outdef.h"
|
#include "l_outdef.h"
|
||||||
#include "l_class.h"
|
#include "l_class.h"
|
||||||
|
|
||||||
|
extern char *bts2str();
|
||||||
extern char *symbol2str();
|
extern char *symbol2str();
|
||||||
|
|
||||||
extern int f_VARARGSn, LINTLIB;
|
|
||||||
int stat_number = 9999; /* static scope number */
|
int stat_number = 9999; /* static scope number */
|
||||||
struct outdef OutDef, OutCall;
|
struct outdef OutDef, OutCall;
|
||||||
|
|
||||||
|
@ -127,17 +128,16 @@ local_EFDC(idf)
|
||||||
lint_formals()
|
lint_formals()
|
||||||
{
|
{
|
||||||
/* Make a list of tp_entries containing the types of the formal
|
/* Make a list of tp_entries containing the types of the formal
|
||||||
* parameters of the function definition currently parsed.
|
* parameters of the function definition just parsed.
|
||||||
*/
|
*/
|
||||||
register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
|
register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
|
||||||
register struct tp_entry **hook = &OutDef.od_entry;
|
register struct argument **hook = &OutDef.od_arg;
|
||||||
|
register int nrargs = 0;
|
||||||
|
|
||||||
OutDef.od_nrargs = 0;
|
|
||||||
while (se) {
|
while (se) {
|
||||||
register struct type *type = se->se_idf->id_def->df_type;
|
register struct type *type = se->se_idf->id_def->df_type;
|
||||||
register struct tp_entry *te = new_tp_entry();
|
register struct argument *arg = new_argument();
|
||||||
|
|
||||||
switch (type->tp_fund) {
|
|
||||||
/* Do the conversions on the formals that could not be
|
/* Do the conversions on the formals that could not be
|
||||||
done in declare_idf().
|
done in declare_idf().
|
||||||
It is, unfortunately, impossible not to do them,
|
It is, unfortunately, impossible not to do them,
|
||||||
|
@ -146,6 +146,7 @@ lint_formals()
|
||||||
want to duplicate the whole of expression handling
|
want to duplicate the whole of expression handling
|
||||||
for lint.
|
for lint.
|
||||||
*/
|
*/
|
||||||
|
switch (type->tp_fund) {
|
||||||
case CHAR:
|
case CHAR:
|
||||||
case SHORT:
|
case SHORT:
|
||||||
type = int_type;
|
type = int_type;
|
||||||
|
@ -154,19 +155,45 @@ lint_formals()
|
||||||
type = double_type;
|
type = double_type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
te->te_type = type;
|
|
||||||
te->te_class = !Const;
|
|
||||||
*hook = te;
|
|
||||||
hook = &te->next;
|
|
||||||
|
|
||||||
OutDef.od_nrargs++;
|
if (f_FORMAT && nrargs == f_FORMATn) {
|
||||||
|
if ( type->tp_fund != POINTER
|
||||||
|
|| type->tp_up->tp_fund != CHAR
|
||||||
|
) {
|
||||||
|
warning("format parameter %d is not pointer to char",
|
||||||
|
nrargs);
|
||||||
|
}
|
||||||
|
arg->ar_type = string_type;
|
||||||
|
arg->ar_class = ArgString;
|
||||||
|
arg->CAS_VALUE = f_FORMAT;
|
||||||
|
arg->CAS_LEN = strlen(f_FORMAT);
|
||||||
|
f_FORMAT = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
arg->ar_type = type;
|
||||||
|
arg->ar_class = ArgFormal;
|
||||||
|
}
|
||||||
|
*hook = arg;
|
||||||
|
hook = &arg->next;
|
||||||
|
|
||||||
|
nrargs++;
|
||||||
se = se->next;
|
se = se->next;
|
||||||
}
|
}
|
||||||
if (f_VARARGSn > OutDef.od_nrargs) {
|
|
||||||
warning("VARARGS%d function has only %d arguments",
|
if (f_VARARGSn > nrargs) {
|
||||||
f_VARARGSn, OutDef.od_nrargs);
|
warning("VARARGS%d function has only %d argument%s",
|
||||||
f_VARARGSn = OutDef.od_nrargs;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
output_use(idf)
|
output_use(idf)
|
||||||
|
@ -212,10 +239,10 @@ output_def(od)
|
||||||
break;
|
break;
|
||||||
case SFDF:
|
case SFDF:
|
||||||
/* remove tp_entries */
|
/* remove tp_entries */
|
||||||
while (od->od_entry) {
|
while (od->od_arg) {
|
||||||
register struct tp_entry *tmp = od->od_entry;
|
register struct argument *tmp = od->od_arg;
|
||||||
od->od_entry = od->od_entry->next;
|
od->od_arg = od->od_arg->next;
|
||||||
free_tp_entry(tmp);
|
free_argument(tmp);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
@ -229,19 +256,19 @@ output_def(od)
|
||||||
case LFDF:
|
case LFDF:
|
||||||
if (f_VARARGSn != -1) {
|
if (f_VARARGSn != -1) {
|
||||||
printf(":%d", -1 - f_VARARGSn);
|
printf(":%d", -1 - f_VARARGSn);
|
||||||
outtypes(od->od_entry, f_VARARGSn);
|
outargs(od->od_arg, f_VARARGSn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printf(":%d", od->od_nrargs);
|
printf(":%d", od->od_nrargs);
|
||||||
outtypes(od->od_entry, od->od_nrargs);
|
outargs(od->od_arg, od->od_nrargs);
|
||||||
}
|
}
|
||||||
od->od_entry = 0;
|
od->od_arg = 0;
|
||||||
printf(":%d", od->od_valreturned);
|
printf(":%d", od->od_valreturned);
|
||||||
break;
|
break;
|
||||||
case FC:
|
case FC:
|
||||||
printf(":%d", od->od_nrargs);
|
printf(":%d", od->od_nrargs);
|
||||||
outtypes(od->od_entry, od->od_nrargs);
|
outargs(od->od_arg, od->od_nrargs);
|
||||||
od->od_entry = 0;
|
od->od_arg = 0;
|
||||||
printf(":%d", od->od_valused);
|
printf(":%d", od->od_valused);
|
||||||
break;
|
break;
|
||||||
case EVDF:
|
case EVDF:
|
||||||
|
@ -257,26 +284,53 @@ output_def(od)
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
printf(":");
|
printf(":");
|
||||||
outtype(od->od_type);
|
outargtype(od->od_type);
|
||||||
printf(":%u:%s\n", od->od_line, od->od_file);
|
printf(":%u:%s\n", od->od_line, od->od_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
outtypes(te, n)
|
outargs(arg, n)
|
||||||
struct tp_entry *te;
|
struct argument *arg;
|
||||||
{
|
{
|
||||||
/* Output n types in the tp_entry-list and remove all the entries */
|
/* Output the n arguments in the argument list and remove them */
|
||||||
|
|
||||||
register struct tp_entry *tmp;
|
register struct argument *tmp;
|
||||||
|
|
||||||
while (n--) {
|
while (n--) {
|
||||||
ASSERT(te);
|
ASSERT(arg);
|
||||||
printf(":");
|
outarg(arg);
|
||||||
if (te->te_class == Const && te->te_value >= 0) {
|
tmp = arg;
|
||||||
|
arg = arg->next;
|
||||||
|
free_argument(tmp);
|
||||||
|
}
|
||||||
|
/* remove the remaining entries */
|
||||||
|
while (arg) {
|
||||||
|
tmp = arg;
|
||||||
|
arg = arg->next;
|
||||||
|
free_argument(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outarg(arg)
|
||||||
|
struct argument *arg;
|
||||||
|
{
|
||||||
|
printf(":");
|
||||||
|
switch (arg->ar_class) {
|
||||||
|
case ArgConst:
|
||||||
|
if (arg->CAA_VALUE >= 0) {
|
||||||
/* constant non-negative actual parameter */
|
/* constant non-negative actual parameter */
|
||||||
printf("+");
|
printf("+");
|
||||||
}
|
}
|
||||||
outtype(te->te_type);
|
outargtype(arg->ar_type);
|
||||||
if (te->te_type->tp_fund == FUNCTION) {
|
break;
|
||||||
|
|
||||||
|
case ArgString:
|
||||||
|
outargstring(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ArgFormal:
|
||||||
|
case ArgExpr:
|
||||||
|
outargtype(arg->ar_type);
|
||||||
|
if (arg->ar_type->tp_fund == FUNCTION) {
|
||||||
/* UGLY PATCH !!! ??? */
|
/* UGLY PATCH !!! ??? */
|
||||||
/* function names as operands are sometimes
|
/* function names as operands are sometimes
|
||||||
FUNCTION and sometimes POINTER to FUNCTION,
|
FUNCTION and sometimes POINTER to FUNCTION,
|
||||||
|
@ -286,34 +340,44 @@ outtypes(te, n)
|
||||||
*/
|
*/
|
||||||
printf("*");
|
printf("*");
|
||||||
}
|
}
|
||||||
tmp = te;
|
break;
|
||||||
te = te->next;
|
|
||||||
free_tp_entry(tmp);
|
default:
|
||||||
}
|
NOTREACHED();
|
||||||
/* remove the remaining entries */
|
/*NOTREACHED*/
|
||||||
while (te) {
|
|
||||||
tmp = te;
|
|
||||||
te = te->next;
|
|
||||||
free_tp_entry(tmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
outtype(tp)
|
outargstring(arg)
|
||||||
|
struct argument *arg;
|
||||||
|
{
|
||||||
|
char buff[1000];
|
||||||
|
register char *p;
|
||||||
|
|
||||||
|
bts2str(arg->CAS_VALUE, arg->CAS_LEN, buff);
|
||||||
|
for (p = &buff[0]; *p; p++) {
|
||||||
|
if (*p == '"' || *p == ':')
|
||||||
|
*p = ' ';
|
||||||
|
}
|
||||||
|
printf("\"%s\"", buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
outargtype(tp)
|
||||||
struct type *tp;
|
struct type *tp;
|
||||||
{
|
{
|
||||||
switch (tp->tp_fund) {
|
switch (tp->tp_fund) {
|
||||||
case POINTER:
|
case POINTER:
|
||||||
outtype(tp->tp_up);
|
outargtype(tp->tp_up);
|
||||||
printf("*");
|
printf("*");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARRAY:
|
case ARRAY:
|
||||||
outtype(tp->tp_up);
|
outargtype(tp->tp_up);
|
||||||
printf("*"); /* compatible with [] */
|
printf("*"); /* compatible with [] */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FUNCTION:
|
case FUNCTION:
|
||||||
outtype(tp->tp_up);
|
outargtype(tp->tp_up);
|
||||||
printf("()");
|
printf("()");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -365,7 +429,8 @@ fill_outcall(ex, used)
|
||||||
register struct idf *idf = ex->OP_LEFT->VL_IDF;
|
register struct idf *idf = ex->OP_LEFT->VL_IDF;
|
||||||
register struct def *def = idf->id_def;
|
register struct def *def = idf->id_def;
|
||||||
|
|
||||||
if (def->df_sc == IMPLICIT) {
|
if (def->df_sc == IMPLICIT && !idf->id_def->df_used) {
|
||||||
|
/* IFDC, first time */
|
||||||
implicit_func_decl(idf, ex->ex_file, ex->ex_line);
|
implicit_func_decl(idf, ex->ex_file, ex->ex_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,7 +440,7 @@ fill_outcall(ex, used)
|
||||||
OutCall.od_name = idf->id_text;
|
OutCall.od_name = idf->id_text;
|
||||||
OutCall.od_file = ex->ex_file;
|
OutCall.od_file = ex->ex_file;
|
||||||
OutCall.od_line = ex->ex_line;
|
OutCall.od_line = ex->ex_line;
|
||||||
OutCall.od_entry = (struct tp_entry *)0;
|
OutCall.od_arg = (struct argument *)0;
|
||||||
OutCall.od_nrargs = 0;
|
OutCall.od_nrargs = 0;
|
||||||
|
|
||||||
if ((ex = ex->OP_RIGHT) != 0) { /* function call with arguments */
|
if ((ex = ex->OP_RIGHT) != 0) { /* function call with arguments */
|
||||||
|
@ -392,20 +457,24 @@ fill_outcall(ex, used)
|
||||||
fill_arg(e)
|
fill_arg(e)
|
||||||
struct expr *e;
|
struct expr *e;
|
||||||
{
|
{
|
||||||
register struct tp_entry *te;
|
register struct argument *arg;
|
||||||
|
|
||||||
te = new_tp_entry();
|
arg = new_argument();
|
||||||
te->te_type = e->ex_type;
|
arg->ar_type = e->ex_type;
|
||||||
if (is_cp_cst(e)) {
|
if (is_cp_cst(e)) {
|
||||||
te->te_class = Const;
|
arg->ar_class = ArgConst;
|
||||||
te->te_value = e->VL_VALUE;
|
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 {
|
else {
|
||||||
te->te_class = !Const;
|
arg->ar_class = ArgExpr;
|
||||||
te->te_value = (arith) 0;
|
|
||||||
}
|
}
|
||||||
te->next = OutCall.od_entry;
|
arg->next = OutCall.od_arg;
|
||||||
OutCall.od_entry = te;
|
OutCall.od_arg = arg;
|
||||||
OutCall.od_nrargs++;
|
OutCall.od_nrargs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,14 +5,30 @@
|
||||||
/* $Header$ */
|
/* $Header$ */
|
||||||
/* Lint output definition */
|
/* Lint output definition */
|
||||||
|
|
||||||
struct tp_entry {
|
/* Values for ar_class */
|
||||||
struct tp_entry *next;
|
#define ArgFormal 0
|
||||||
struct type *te_type;
|
#define ArgExpr 1 /* actual */
|
||||||
int te_class; /* for constant parameters */
|
#define ArgConst 2 /* integer constant */
|
||||||
arith te_value;
|
#define ArgString 3 /* string */
|
||||||
|
|
||||||
|
struct argument {
|
||||||
|
struct argument *next;
|
||||||
|
struct type *ar_type;
|
||||||
|
int ar_class; /* for constant parameters */
|
||||||
|
union const_arg {
|
||||||
|
arith ca_value;
|
||||||
|
struct {
|
||||||
|
char *cas_value;
|
||||||
|
int cas_len;
|
||||||
|
} ca_string;
|
||||||
|
} ar_object;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ALLOCDEF "tp_entry" 10 */
|
#define CAA_VALUE ar_object.ca_value
|
||||||
|
#define CAS_VALUE ar_object.ca_string.cas_value
|
||||||
|
#define CAS_LEN ar_object.ca_string.cas_len
|
||||||
|
|
||||||
|
/* ALLOCDEF "argument" 10 */
|
||||||
|
|
||||||
struct outdef {
|
struct outdef {
|
||||||
char od_class;
|
char od_class;
|
||||||
|
@ -21,7 +37,7 @@ struct outdef {
|
||||||
char *od_file;
|
char *od_file;
|
||||||
unsigned int od_line;
|
unsigned int od_line;
|
||||||
int od_nrargs;
|
int od_nrargs;
|
||||||
struct tp_entry *od_entry; /* a list of the types of the
|
struct argument *od_arg; /* a list of the types of the
|
||||||
* formal parameters */
|
* formal parameters */
|
||||||
int od_valreturned;
|
int od_valreturned;
|
||||||
/* NOVALRETURNED, VALRETURNED, NORETURN; see l_lint.h */
|
/* NOVALRETURNED, VALRETURNED, NORETURN; see l_lint.h */
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "l_lint.h"
|
#include "l_lint.h"
|
||||||
#include "l_brace.h"
|
#include "l_brace.h"
|
||||||
#include "l_state.h"
|
#include "l_state.h"
|
||||||
|
#include "l_comment.h"
|
||||||
#include "l_outdef.h"
|
#include "l_outdef.h"
|
||||||
|
|
||||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
@ -35,7 +36,6 @@ extern char *func_name;
|
||||||
extern struct type *func_type;
|
extern struct type *func_type;
|
||||||
extern int func_notypegiven;
|
extern int func_notypegiven;
|
||||||
extern char loptions[];
|
extern char loptions[];
|
||||||
extern int s_NOTREACHED;
|
|
||||||
|
|
||||||
/* global variables for the lint_stack */
|
/* global variables for the lint_stack */
|
||||||
struct lint_stack_entry stack_bottom;
|
struct lint_stack_entry stack_bottom;
|
||||||
|
@ -326,13 +326,15 @@ check_autos()
|
||||||
check_args_used()
|
check_args_used()
|
||||||
{
|
{
|
||||||
register struct stack_entry *se = local_level->sl_entry;
|
register struct stack_entry *se = local_level->sl_entry;
|
||||||
extern int f_ARGSUSED;
|
|
||||||
|
|
||||||
ASSERT(level == L_FORMAL1);
|
ASSERT(level == L_FORMAL1);
|
||||||
while (se) {
|
while (se) {
|
||||||
register struct def *def = se->se_idf->id_def;
|
register struct def *def = se->se_idf->id_def;
|
||||||
|
|
||||||
if (def && !def->df_used && !loptions['v'] && !f_ARGSUSED) {
|
if ( (def && !def->df_used)
|
||||||
|
&& !loptions['v']
|
||||||
|
&& !(f_ARGSUSED || LINTLIB)
|
||||||
|
) {
|
||||||
def_warning(def, "argument %s not used in function %s",
|
def_warning(def, "argument %s not used in function %s",
|
||||||
se->se_idf->id_text, func_name);
|
se->se_idf->id_text, func_name);
|
||||||
}
|
}
|
||||||
|
@ -861,8 +863,7 @@ lint_break_stmt()
|
||||||
lint_start_function()
|
lint_start_function()
|
||||||
{
|
{
|
||||||
lint_return_stmt(-1); /* initialization */
|
lint_return_stmt(-1); /* initialization */
|
||||||
move_ARG2f();
|
lint_comment_function();
|
||||||
move_VAR2f();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lint_end_function()
|
lint_end_function()
|
||||||
|
|
Loading…
Add table
Reference in a new issue