many improvements

This commit is contained in:
dick 1988-08-07 22:55:20 +00:00
parent 5581bdad15
commit 56fff3d6cd
8 changed files with 535 additions and 429 deletions

View file

@ -1,3 +1,21 @@
7-Aug-88 Dick Grune (dick) at dick
About the class of an inpdef, often set-like questions are asked.
To speed up answering these questions, a mapping has been created
of the values of `class' onto answers to these questions. See
class.[ch].
5-Aug-88 Dick Grune (dick) at dick
Streamlined the program by rearranging the input sequence:
- library
- external defs
- external decls
- external usage
- static defs
- static usage
This change to a much more natural order has been possible by the
introduction of the static file number. Many pieces of code could
now be taken together and the program is much cleaner now.
8-Jul-88 Dick Grune (dick) at dick
Added a special meta-type (also in lpaas1) for non-negative
constant actual arguments, because these may match both the signed

View file

@ -1,26 +1,26 @@
# M A K E F I L E F O R L P A S S 2
# Machine and environ dependent definitions
EMHOME = /usr/em
LPASS1 = ../lpass1
EMHOME = /usr/em
LPASS1 = ../lpass1
# Libraries and EM interface definitions
SYSLIB = $(EMHOME)/modules/lib/libsystem.a
STRLIB = $(EMHOME)/modules/lib/libstring.a
PRTLIB = $(EMHOME)/modules/lib/libprint.a
INPLIB = $(EMHOME)/modules/lib/libinput.a
ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a
MALLOC = $(EMHOME)/modules/lib/malloc.o
LLIBS = $(INPLIB) $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
SYSLIB = $(EMHOME)/modules/lib/libsystem.a
STRLIB = $(EMHOME)/modules/lib/libstring.a
PRTLIB = $(EMHOME)/modules/lib/libprint.a
INPLIB = $(EMHOME)/modules/lib/libinput.a
ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a
MALLOC = $(EMHOME)/modules/lib/malloc.o
LLIBS = $(INPLIB) $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
CFLAGS = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg -I/usr/include
CFLAGS = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg -I/usr/include
.SUFFIXES: .str .h
.str.h:
$(LPASS1)/make.allocd <$*.str >$*.h
SRC = lpass2.c read.c
OBJ = lpass2.o read.o
SRC = lpass2.c read.c report.c class.c
OBJ = lpass2.o read.o report.o class.o
test: lpass2
make lint
@ -32,7 +32,7 @@ lpass2: $(OBJ) Makefile next.o
lint:
../lint $(CFLAGS) $(SRC) next.c #???
next.c: inpdef.str
next.c: $(LPASS1)/make.next inpdef.str
$(LPASS1)/make.next inpdef.str > next.c
tags: $(SRC)
@ -42,4 +42,7 @@ clean:
rm -f a.out core next.c inpdef.h $(OBJ) next.o
#----------------------------------------------------------------
lpass2.o: ../lpass1/errout.h ../lpass1/lint.h ../lpass1/l_class.h inpdef.h
class.o: class.h
lpass2.o: ../lpass1/l_class.h ../lpass1/l_lint.h class.h inpdef.h
read.o: ../lpass1/l_class.h class.h inpdef.h
report.o: inpdef.h

View file

@ -0,0 +1,47 @@
#include "../lpass1/l_class.h"
#include "class.h"
int class[] = {
/* mapping of class values onto bit patterns */
/* LFDF */ CL_LIB|CL_FUNC|CL_DEF,
/* LVDF */ CL_LIB|CL_VAR|CL_DEF,
/* EFDF */ CL_EXT|CL_FUNC|CL_DEF,
/* EVDF */ CL_EXT|CL_VAR|CL_DEF,
/* EFDC */ CL_EXT|CL_FUNC|CL_DECL,
/* EVDC */ CL_EXT|CL_VAR|CL_DECL,
/* IFDC */ CL_IMPL|CL_FUNC|CL_DECL,
/* SFDF */ CL_STAT|CL_FUNC|CL_DEF,
/* SVDF */ CL_STAT|CL_VAR|CL_DEF,
/* FC */ CL_FUNC|CL_USAGE,
/* VU */ CL_VAR|CL_USAGE
};
static int val[] = {
LFDF,
LVDF,
EFDF,
EVDF,
EFDC,
EVDC,
IFDC,
SFDF,
SVDF,
FC,
VU
};
init_class()
{
/* The initialization of class[] has been taken care of above.
For it to work, we have to test that the class values are
in the right order. This is also necessary for the scanning
sequence in lpass2.c to work properly.
*/
int i;
for (i = 0; i+1 < sizeof(val)/sizeof(val[0]); i++) {
if (val[i] >= val[i+1])
panic("class values out of sequence");
}
}

View file

@ -0,0 +1,16 @@
#define CL_DEF (1<<0)
#define CL_DECL (1<<1)
#define CL_USAGE (1<<2)
#define CL_FUNC (1<<3)
#define CL_VAR (1<<4)
#define CL_LIB (1<<5)
#define CL_EXT (1<<6)
#define CL_IMPL (1<<7)
#define CL_STAT (1<<8)
extern int class[];
#define is_class(id,cl) ((class[(id)->id_class-'a'] & (cl)) == (cl))

View file

@ -5,14 +5,22 @@
struct inpdef {
struct inpdef *next;
int id_class;
/* filled by get_id() */
int id_class; /* see ../lpass1/l_class.h */
char id_name[NAMESIZE];
int id_statnr;
char id_file[FNAMESIZE];
int id_line;
int id_nrargs;
char id_argtps[ARGTPSSIZE];
int id_returns;
char id_type[TYPESIZE];
int id_args; /* set if arguments given */
int id_nrargs; /* number of args, neg. for varargs */
char id_argtps[ARGTPSSIZE]; /* argument types, colon separated */
int id_valreturned; /* for def/decl, set if val returned */
int id_valused; /* for FC, see ../lpass1/l_lint.h */
/* not filled by get_id() */
int id_called;
int id_used;
int id_ignored;

View file

@ -1,46 +1,55 @@
#include <varargs.h>
#include <alloc.h>
#include "../lpass1/l_lint.h"
#include "../lpass1/l_class.h"
#include "class.h"
#include "inpdef.h"
#include <alloc.h>
#include <system.h>
#define MSGOUT STDERR /* filedes on which to write the messages */
#define ERROUT STDERR /* filedes on which to write the panics */
#define streq(s1,s2) (strcmp(s1, s2) == 0)
#define min(a,b) ((a) <= (b) ? (a) : (b))
#define type_equal(s1,s2) (streq(s1, s2))
char cur_name[NAMESIZE];
struct inpdef *dot, *lib, *ext, *sta;
char *cur_name;
struct inpdef *dot_id,
*ext_def,
*static_def;
struct inpdef *id_read();
#define same_name() (dot && streq(cur_name, dot->id_name))
#define same_obj(stnr) (same_name() && dot->id_statnr == stnr)
#define same_name() streq(cur_name, dot_id->id_name)
#define defdec(id) (is_class(id, CL_DEF) ? "defined" : "declared")
/******** M A I N ********/
main(argc, argv)
char *argv[];
{
struct inpdef *id;
init(argc, argv);
get_dot_id();
while (dot_id) {
cur_name = dot_id->id_name;
read_defs();
while (dot_id && same_name()) {
id = id_read();
check(id);
free_inpdef(id);
dot = new_inpdef();
get_dot();
while (dot) {
if (lib) {
free_inpdef(lib);
lib = 0;
}
if (ext) {
free_inpdef(ext);
ext = 0;
}
strcpy(cur_name, dot->id_name);
lib_def();
ext_def();
ext_decls();
usage(0);
if (ext)
check_def(ext);
statics();
/* inpdefs of class ERRCL are never generated */
if (same_name()) {
/* there are more lines for this name that have
not been absorbed
*/
panic("sequence error in intermediate file");
}
check_usage();
free_defs();
}
}
@ -50,13 +59,14 @@ static char *table[] = {0};
init(argc, argv)
char *argv[];
{
/* Prepare standard input for reading using the input-package
* Read first inpdef into dot_id
/*
* Parse options
* Prepare standard input for reading using the input-package
*/
char *result;
init_class();
while (argc > 1 && *argv[1] == '-') {
switch (argv[1][1]) {
case 'u':
@ -67,7 +77,7 @@ init(argc, argv)
options[argv[1][1]] = 1;
break;
default:
/* ready to extend */
/* ready to be extended */
break;
}
argc--, argv++;
@ -77,248 +87,295 @@ init(argc, argv)
panic("InsertFile() fails");
}
read_defs()
get_dot()
{
struct inpdef *id;
if (ext_def || static_def)
panic("read_defs: slate not clean");/*???*/
while (dot_id && same_name() && is_def(dot_id)) {
id = id_read();
switch (id->id_class) {
case EFDF:
case EVDF:
if (ext_def) {
report("%L: %s also defined at %L",
id, id->id_name, ext_def);
free_inpdef(id);
}
else {
ext_def = id;
}
break;
case SFDF:
case SVDF:
if (ext_def) {
report("%L: %s also defined at %L",
id, id->id_name, ext_def);
free_inpdef(id);
}
else {
static_in_list(id);
}
break;
case LFDF:
case LVDF:
if (ext_def) {
/* Some libraries contain more than one
* definition
*/
if (is_lib_class(ext_def->id_class)) {
report("%L: %s redefined in library %L",
id, id->id_name, ext_def);
}
free_inpdef(id);
}
else {
ext_def = id;
}
break;
default:
panic("invalid class (%c) in read_defs", id->id_class);
}
if (!get_id(dot)) {
free_inpdef(dot);
dot = 0;
cur_name[0] = '\0';
}
}
struct inpdef *
id_read()
{
/* Returns the value of dot_id if present, 0 otherwise.
* Reads a new inpdef ahead, to which dot_id will be pointing.
* Cur_name will be pointing to id_name of the returned inpdef.
*/
struct inpdef *old_id;
if (!dot_id)
return (0);
old_id = dot_id;
cur_name = old_id->id_name;
get_dot_id();
return (old_id);
}
/******** L I B R A R Y ********/
get_dot_id()
lib_def()
{
/* Allocates a new inpdef, calls it dot_id and fills it */
dot_id = new_inpdef();
if (!get_id(dot_id)) {
free_inpdef(dot_id);
cur_name = "";
dot_id = 0;
if (same_obj(0) && is_class(dot, CL_LIB)) {
lib = dot;
dot = new_inpdef();
get_dot();
}
while (same_obj(0) && is_class(dot, CL_LIB)) {
report("%L: multiple definition of %s in library",
dot, dot->id_name);
get_dot();
}
}
struct inpdef *definition();
check(id)
struct inpdef *id;
/******** E X T E R N ********/
ext_def()
{
/* Checks a declaration, function call or variable usage, described by id,
* against the definitions.
*/
struct inpdef *idef;
if (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) {
if (lib) {
report("%L: %s also defined in library %L",
dot, dot->id_name, lib);
}
ext = dot;
dot = new_inpdef();
get_dot();
}
idef = definition(id);
switch (id->id_class) {
case EFDC:
if (!idef) {
if (!options['u']) {
report("%L: %s declared but never defined",
id, id->id_name);
}
discard_defs();
break;
while (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) {
report("%L: %s also defined at %L",
dot, dot->id_name, ext);
get_dot();
}
}
ext_decls()
{
while (same_obj(0) && dot->id_class == EFDC) {
one_ext_decl("function", "variable", CL_VAR);
}
while (same_obj(0) && dot->id_class == EVDC) {
one_ext_decl("variable", "function", CL_FUNC);
}
while (same_obj(0) && dot->id_class == IFDC) {
one_ext_decl("function", "variable", CL_VAR);
}
}
one_ext_decl(kind, other_kind, other_class)
char *kind;
char *other_kind;
int other_class;
{
struct inpdef *def = ext ? ext : lib ? lib : 0;
if (!def) {
/* the declaration will have to serve */
if (!is_class(dot, CL_IMPL) && !options['u']) {
report("%L: %s %s declared but never defined",
dot, dot->id_name, kind);
}
if (idef->id_class == EVDF || idef->id_class == LVDF) {
report("%L: function %s declared as variable at %L",
id, id->id_name, idef);
break;
ext = dot;
dot = new_inpdef();
get_dot();
return;
}
if (is_class(def, other_class)) {
/* e.g.: function FFF declared as variable at ... */
report("%L: %s %s %s as %s at %L",
dot, kind, dot->id_name, defdec(def), other_kind, def);
/* no further testing possible */
return;
}
if (!type_equal(dot->id_type, def->id_type)) {
/* e.g.: type of variable VVV defined differently at ... */
report("%L: type of %s %s %s differently at %L",
dot, kind, dot->id_name, defdec(def), def);
}
get_dot();
}
/******** U S A G E ********/
usage(stnr)
int stnr;
{
struct inpdef *def = stnr ? sta : ext ? ext : lib ? lib : 0;
while (same_obj(stnr) && dot->id_class == FC) {
one_func_call(def);
}
while (same_obj(stnr) && dot->id_class == VU) {
one_var_usage(def);
}
}
one_func_call(def)
struct inpdef *def;
{
if (!def) {
if (!options['u']) {
report("%L: function %s used but not defined",
dot, dot->id_name);
}
if (!type_equal(id->id_type, idef->id_type)) {
report("%L: value of function %s declared differently at %L",
id, id->id_name, idef);
}
break;
case EVDC:
if (!idef) {
if (!options['u']) {
report("%L: %s declared but never defined",
id, id->id_name);
}
discard_defs();
break;
}
if (idef->id_class == EFDF || idef->id_class == LFDF) {
report("%L: variable %s declared as function at %L",
id, id->id_name, idef);
break;
}
if (!type_equal(id->id_type, idef->id_type)) {
report("%L: variable %s declared differently at %L",
id, id->id_name, idef);
}
break;
case IFDC:
if (!idef)
break; /* used but not defined */
if (idef->id_class == EVDF || idef->id_class == LVDF) {
report("%L: function %s declared as variable at %L",
id, id->id_name, idef);
break;
}
if (!type_equal(id->id_type, idef->id_type)) {
report("%L: function value of %s declared differently at %L",
id, id->id_name, idef);
}
break;
case FC:
if (!idef) {
if (!options['u']) {
report("%L: function %s used but not defined",
id, id->id_name);
}
discard_defs();
break;
}
idef->id_called = 1;
check_args(id, idef);
if (id->id_returns == USED && !idef->id_returns) {
get_dot();
return;
}
def->id_called = 1;
if (def->id_args) {
check_args(dot, def);
if (dot->id_valused == USED && !def->id_valreturned) {
report("%L: value of %s is used, but none is returned at %L",
id, id->id_name, idef);
}
switch (id->id_returns) {
case USED:
idef->id_used = 1;
break;
case IGNORED:
idef->id_ignored = 1;
break;
case VOIDED:
idef->id_voided = 1;
break;
default:
panic("invalid id->id_returns in check");
dot, dot->id_name, def);
}
}
switch (dot->id_valused) {
case USED:
def->id_used = 1;
break;
case VU:
if (!idef) {
if (!options['u']) {
report("%L: variable %s used but not defined",
id, id->id_name);
}
discard_defs();
break;
}
idef->id_called = 1;
case IGNORED:
def->id_ignored = 1;
break;
case EFDF:
case SFDF:
case EVDF:
case SVDF:
case LFDF:
case LVDF:
panic("check() called for a definition");
case VOIDED:
def->id_voided = 1;
break;
default:
panic("invalid class (%c) in check", id->id_class);
panic("invalid dot->id_valused in check");
break;
}
get_dot();
}
discard_defs()
one_var_usage(def)
struct inpdef *def;
{
/* Read until a definition having another name */
if (!def) {
if (!options['u']) {
report("%L: variable %s used but not defined",
dot, dot->id_name);
}
get_dot();
return;
}
struct inpdef *id;
def->id_called = 1;
while (dot_id && same_name()) {
id = id_read();
free_inpdef(id);
get_dot();
}
/******** S T A T I C ********/
statics()
{
while (same_name() && dot->id_statnr != 0) {
one_static(dot->id_statnr);
}
}
check_args(id, idef)
struct inpdef *id, *idef;
one_static(stnr)
int stnr;
{
while (same_obj(stnr)) {
if (sta) {
free_inpdef(sta);
sta = 0;
}
stat_def(stnr);
usage(stnr);
if (sta)
check_def(sta);
get_dot();
}
}
stat_def(stnr)
int stnr;
{
if (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) {
if (lib) {
report("%L: %s also defined in library %L",
dot, dot->id_name, lib);
}
if (ext) {
report("%L: %s also %s at %L",
dot, dot->id_name, defdec(ext), ext);
}
sta = dot;
dot = new_inpdef();
get_dot();
}
while (same_obj(stnr) && is_class(dot, CL_STAT|CL_DEF)) {
report("%L: %s also defined at %L",
dot, dot->id_name, sta);
get_dot();
}
}
check_def(def)
struct inpdef *def;
{
if (!def)
return;
if (!def->id_called) {
if (streq(def->id_name, "main")) {
/* silent */
}
else if (ext && is_class(ext, CL_LIB)) {
/* silent */
}
else {
if (!options['u']) {
report("%L: %s %s but never used",
def, def->id_name, defdec(def));
}
}
}
if (is_class(def, CL_DEF|CL_FUNC)) {
if (def->id_valreturned && def->id_called && def->id_ignored) {
report("%L: %s returns value which is %s ignored",
def, def->id_name,
(def->id_used || def->id_voided) ?
"sometimes" : "always");
}
}
}
/******** T Y P E C H E C K I N G ********/
check_args(id, def)
struct inpdef *id, *def;
{
register char *act_tp = id->id_argtps;
register char *def_tp = idef->id_argtps;
register char *def_tp = def->id_argtps;
register int i;
register int nrargs; /* # of args to be type-checked */
register int varargs;
/* determine nrargs */
if (idef->id_nrargs < 0) {
if (def->id_nrargs < 0) {
varargs = 1;
nrargs = -idef->id_nrargs - 1;
nrargs = -def->id_nrargs - 1;
}
else {
varargs = 0;
nrargs = idef->id_nrargs;
nrargs = def->id_nrargs;
}
/* adjust nrargs, if necessary */
if (varargs) {
if (nrargs > id->id_nrargs) {
report("%L: number of args to %s differs from %L",
id, id->id_name, idef);
id, id->id_name, def);
nrargs = id->id_nrargs;
}
}
else {
if (nrargs != id->id_nrargs) {
report("%L: number of args to %s differs from %L",
id, id->id_name, idef);
id, id->id_name, def);
nrargs = min(nrargs, id->id_nrargs);
}
}
@ -346,19 +403,27 @@ check_args(id, idef)
if (!type_match(act, def)) {
report("%L: arg %d of %s differs from that at %L",
id, i, id->id_name, idef);
id, i, id->id_name, def);
}
*act_tp++ = ':';
*def_tp++ = ':';
}
}
int
type_equal(act, def)
char *act, *def;
{
return streq(act, def);
}
int
type_match(act, def)
char *act, *def;
{
if (type_equal(act, def))
return 1;
if (act[0] == '+') {
/* a non-negative constant */
/* might be signed or unsigned */
@ -373,181 +438,22 @@ type_match(act, def)
return 0;
}
check_usage()
{
/* Checks if the defined function or variable is used.
* There can be several static definitions.
*/
struct inpdef *sd = static_def;
/******** D E B U G G I N G ********/
if (ext_def)
check_def(ext_def);
while (sd) {
check_def(sd);
sd = sd->next;
}
}
check_def(id)
struct inpdef *id;
{
if (!id->id_called) {
if (streq(id->id_name, "main")) {
/* silent */
}
else if (ext_def && is_lib_class(ext_def->id_class)) {
/* silent */
}
else {
if (!options['u']) {
report("%L: %s defined but never used",
id, id->id_name);
}
}
}
if (is_fundef_class(id->id_class)) {
if (id->id_returns && id->id_called && id->id_ignored) {
report("%L: %s returns value which is %s ignored",
id, id->id_name,
(id->id_used || id->id_voided) ?
"sometimes" : "always");
}
}
}
static_in_list(id)
struct inpdef *id;
{
/* Put id in the list of static definitions.
* static_def points to the first element.
*/
id->next = static_def;
static_def = id;
}
struct inpdef *
definition(id)
struct inpdef *id;
{
/* If there is a static definition that comes from the same file, a pointer
* to this definition will be returned.
* Otherwise a pointer to the ext_def is returned (which may be null).
*/
struct inpdef *sd = static_def;
while (sd) {
if (id->id_statnr == sd->id_statnr)
return (sd);
sd = sd->next;
}
return (ext_def);
}
free_defs()
{
/* Dispose the external definition and the static definitions. */
struct inpdef *sd;
if (ext_def) {
free_inpdef(ext_def);
ext_def = 0;
}
while (static_def) {
sd = static_def;
static_def = static_def->next;
free_inpdef(sd);
}
}
/* VARARGS */
report(va_alist)
va_dcl
{
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char*);
register char *f = fmt;
register char fc;
/* First see if the first arg is an inpdef with
a global file name; if so, skip this message.
*/
if (f[0] == '%' && f[1] == 'L') {
/* it is an inpdef */
register struct inpdef *id =
va_arg(ap, struct inpdef *);
f += 2;
/* is the file name global? */
if (id->id_file[0] == '/')
return;
/* if no, we have used up the argument,
so print it here
*/
fprint(MSGOUT, "\"%s\", line %d",
id->id_file, id->id_line);
}
while ((fc = *f++)) {
if (fc == '%') {
switch (*f++) {
register struct inpdef *id;
register char *s;
register int i;
case 'L': /* a location item */
id = va_arg(ap, struct inpdef *);
fprint(MSGOUT, "\"%s\", line %d",
id->id_file, id->id_line);
break;
case 's': /* a string item */
s = va_arg(ap, char *);
fprint(MSGOUT, "%s", s);
break;
case 'd': /* an int item */
i = va_arg(ap, int);
fprint(MSGOUT, "%d", i);
break;
default:
panic("bad format %s", fmt);
break;
}
}
else {
fprint(MSGOUT, "%c", fc);
}
}
fprint(MSGOUT, "\n");
}
va_end(ap);
}
/* VARARGS1 */
panic(fmt, args)
char *fmt;
{
fprint(ERROUT, "PANIC, lint, pass2: ");
doprnt(ERROUT, fmt, &args);
fprint(ERROUT, "\n");
exit(1);
}
/* for DEBUGGING */
print_id(id)
struct inpdef *id;
{
print("inpdef: %s, %s, %04d, \"%s\", %d, %d, %s, %d, %s\n",
id->id_class == EFDF ? "EFDF" :
id->id_class == SFDF ? "SFDF" :
id->id_class == EVDF ? "EVDF" :
id->id_class == SVDF ? "SVDF" :
print("inpdef: %s, %s, %04d, \"%s\", %d, %s",
id->id_class == LFDF ? "LFDF" :
id->id_class == LVDF ? "LVDF" :
id->id_class == EFDF ? "EFDF" :
id->id_class == EVDF ? "EVDF" :
id->id_class == EFDC ? "EFDC" :
id->id_class == EVDC ? "EVDC" :
id->id_class == IFDC ? "IFDC" :
id->id_class == SFDF ? "SFDF" :
id->id_class == SVDF ? "SVDF" :
id->id_class == FC ? "FC" :
id->id_class == VU ? "VU" :
id->id_class == ERRCL ? "ERRCL" : "<BADCLASS>",
@ -555,9 +461,21 @@ print_id(id)
id->id_statnr,
id->id_file,
id->id_line,
id->id_nrargs,
((id->id_nrargs == 0) ? "" : id->id_argtps),
id->id_returns,
id->id_type);
id->id_type
);
if (is_class(id, CL_FUNC|CL_DEF) || is_class(id, CL_FUNC|CL_USAGE)) {
print(", %d, %s, %s",
id->id_nrargs,
id->id_nrargs == 0 ? "" : id->id_argtps,
id->id_class == FC ?
(id->id_valused == USED ? "USED" :
id->id_valused == IGNORED ? "IGNORED" :
id->id_valused == VOIDED ? "VOIDED" :
"<BAD VALUSED>")
: (id->id_valreturned ? "VALRETURNED" :
"NOVALRETURNED")
);
}
print("\n");
}

View file

@ -1,12 +1,13 @@
#include "../lpass1/l_class.h"
#include "inpdef.h"
#include "../lpass1/l_class.h"
#include "class.h"
#include "inpdef.h"
#include <ctype.h>
#include <ctype.h>
#define INP_NPUSHBACK 2
#include <inp_pkg.spec>
#include <inp_pkg.body>
#include <inp_pkg.spec>
#include <inp_pkg.body>
PRIVATE int LineNr = 1;
@ -25,37 +26,49 @@ int
get_id(id)
struct inpdef *id;
{
/* A low-level function which just reads a definition */
/* A low-level function which just reads a definition */
if (!ReadString(id->id_name, ':', NAMESIZE))
return 0;
if (!ReadInt(&id->id_statnr))
return 0;
SkipChar(':');
loadchar(id->id_class);
if (id->id_class == EOI)
return 0;
SkipChar(':');
switch (id->id_class) {
case EFDF:
case SFDF:
case LFDF:
case FC:
if (is_class(id, CL_FUNC|CL_DEF) || is_class(id, CL_FUNC|CL_USAGE)) {
/* read the argument information */
id->id_args = 1;
if (!ReadInt(&id->id_nrargs))
return 0;
SkipChar(':');
if (!ReadArgs(id->id_nrargs, id->id_argtps))
return 0;
if (!ReadInt(&id->id_returns))
return 0;
if (id->id_class == FC) {
/* function call */
if (!ReadInt(&id->id_valused))
return 0;
}
else {
/* function definition */
if (!ReadInt(&id->id_valreturned))
return 0;
}
SkipChar(':');
break;
}
else {
id->id_args = 0;
}
if (!ReadString(id->id_type, ':', TYPESIZE))
return 0;
if (!ReadInt(&id->id_line))
return 0;
SkipChar(':');
if (!ReadString(id->id_file, '\n', FNAMESIZE))
return 0;
{ extern char options[];
@ -69,14 +82,16 @@ PRIVATE int
ReadString(buf, delim, maxsize)
char *buf;
{
/* Reads a string until 'delim' is encountered.
* Delim is discarded.
* If 'maxsize-1' is exceeded, "string too long" is written by panic().
* A '\0' is appended to the string.
* At EOI 0 is returned, else the length of the string (including
* the appended '\0') is returned.
*/
int ch;
/* Reads a string until 'delim' is encountered.
Delim is discarded.
If 'maxsize-1' is exceeded, "string too long" is written
by panic().
A '\0' is appended to the string.
At EOI 0 is returned, else the length of the string (including
the appended '\0') is returned.
*/
int ch = 0;
int nread = 0;
while (nread < maxsize - 1) {
@ -87,11 +102,11 @@ ReadString(buf, delim, maxsize)
break;
buf[nread++] = (char)ch;
}
buf[nread++] = '\0';
if (ch != delim) {
panic("line %d: string too long: %s", LineNr, buf);
/*NOTREACHED*/
}
buf[nread++] = '\0';
return (nread);
}

View file

@ -0,0 +1,81 @@
#include <varargs.h>
#include <system.h>
#include "inpdef.h"
#define MSGOUT STDERR /* filedes on which to write the messages */
#define ERROUT STDERR /* filedes on which to write the panics */
/* VARARGS */
report(va_alist)
va_dcl
{
va_list ap;
va_start(ap);
{
char *fmt = va_arg(ap, char*);
register char *f = fmt;
register char fc;
/* First see if the first arg is an inpdef with
a global file name; if so, skip this message.
*/
if (f[0] == '%' && f[1] == 'L') {
/* it is an inpdef */
register struct inpdef *id =
va_arg(ap, struct inpdef *);
f += 2;
/* is the file name global? */
if (id->id_file[0] == '/')
return;
/* if no, we have used up the argument,
so print it here
*/
fprint(MSGOUT, "\"%s\", line %d",
id->id_file, id->id_line);
}
while ((fc = *f++)) {
if (fc == '%') {
switch (*f++) {
register struct inpdef *id;
register char *s;
register int i;
case 'L': /* a location item */
id = va_arg(ap, struct inpdef *);
fprint(MSGOUT, "\"%s\", line %d",
id->id_file, id->id_line);
break;
case 's': /* a string item */
s = va_arg(ap, char *);
fprint(MSGOUT, "%s", s);
break;
case 'd': /* an int item */
i = va_arg(ap, int);
fprint(MSGOUT, "%d", i);
break;
default:
panic("bad format %s", fmt);
break;
}
}
else {
fprint(MSGOUT, "%c", fc);
}
}
fprint(MSGOUT, "\n");
}
va_end(ap);
}
/* VARARGS1 */
panic(fmt, args)
char *fmt;
{
fprint(ERROUT, "PANIC, lint, pass2: ");
doprnt(ERROUT, fmt, &args);
fprint(ERROUT, "\n");
exit(1);
}