many improvements
This commit is contained in:
		
							parent
							
								
									5581bdad15
								
							
						
					
					
						commit
						56fff3d6cd
					
				
					 8 changed files with 535 additions and 429 deletions
				
			
		| 
						 | 
					@ -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
 | 
					 8-Jul-88  Dick Grune (dick) at dick
 | 
				
			||||||
	Added a special meta-type (also in lpaas1) for non-negative
 | 
						Added a special meta-type (also in lpaas1) for non-negative
 | 
				
			||||||
	constant actual arguments, because these may match both the signed
 | 
						constant actual arguments, because these may match both the signed
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,26 +1,26 @@
 | 
				
			||||||
#	M A K E F I L E   F O R   L P A S S 2
 | 
					#	M A K E F I L E   F O R   L P A S S 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Machine and environ dependent definitions
 | 
					# Machine and environ dependent definitions
 | 
				
			||||||
EMHOME = /usr/em
 | 
					EMHOME =	/usr/em
 | 
				
			||||||
LPASS1 = ../lpass1
 | 
					LPASS1 =	../lpass1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Libraries and EM interface definitions
 | 
					# Libraries and EM interface definitions
 | 
				
			||||||
SYSLIB = $(EMHOME)/modules/lib/libsystem.a
 | 
					SYSLIB =	$(EMHOME)/modules/lib/libsystem.a
 | 
				
			||||||
STRLIB = $(EMHOME)/modules/lib/libstring.a
 | 
					STRLIB =	$(EMHOME)/modules/lib/libstring.a
 | 
				
			||||||
PRTLIB = $(EMHOME)/modules/lib/libprint.a
 | 
					PRTLIB =	$(EMHOME)/modules/lib/libprint.a
 | 
				
			||||||
INPLIB = $(EMHOME)/modules/lib/libinput.a
 | 
					INPLIB =	$(EMHOME)/modules/lib/libinput.a
 | 
				
			||||||
ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a
 | 
					ALLOCLIB =	$(EMHOME)/modules/lib/liballoc.a
 | 
				
			||||||
MALLOC = $(EMHOME)/modules/lib/malloc.o
 | 
					MALLOC =	$(EMHOME)/modules/lib/malloc.o
 | 
				
			||||||
LLIBS = $(INPLIB) $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
 | 
					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
 | 
					.SUFFIXES: .str .h
 | 
				
			||||||
.str.h:
 | 
					.str.h:
 | 
				
			||||||
	$(LPASS1)/make.allocd <$*.str >$*.h
 | 
						$(LPASS1)/make.allocd <$*.str >$*.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SRC =	lpass2.c read.c
 | 
					SRC =	lpass2.c read.c report.c class.c
 | 
				
			||||||
OBJ =	lpass2.o read.o
 | 
					OBJ =	lpass2.o read.o report.o class.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test:	lpass2
 | 
					test:	lpass2
 | 
				
			||||||
	make lint
 | 
						make lint
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ lpass2:	$(OBJ) Makefile next.o
 | 
				
			||||||
lint:
 | 
					lint:
 | 
				
			||||||
	../lint $(CFLAGS) $(SRC) next.c #???
 | 
						../lint $(CFLAGS) $(SRC) next.c #???
 | 
				
			||||||
 | 
					
 | 
				
			||||||
next.c:	inpdef.str
 | 
					next.c:	$(LPASS1)/make.next inpdef.str
 | 
				
			||||||
	$(LPASS1)/make.next inpdef.str > next.c
 | 
						$(LPASS1)/make.next inpdef.str > next.c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
tags:	$(SRC)
 | 
					tags:	$(SRC)
 | 
				
			||||||
| 
						 | 
					@ -42,4 +42,7 @@ clean:
 | 
				
			||||||
	rm -f a.out core next.c inpdef.h $(OBJ) next.o
 | 
						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
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										47
									
								
								lang/cem/lint/lpass2/class.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								lang/cem/lint/lpass2/class.c
									
										
									
									
									
										Normal 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");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								lang/cem/lint/lpass2/class.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								lang/cem/lint/lpass2/class.h
									
										
									
									
									
										Normal 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))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,14 +5,22 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct inpdef {
 | 
					struct inpdef {
 | 
				
			||||||
	struct inpdef *next;
 | 
						struct inpdef *next;
 | 
				
			||||||
	int id_class;
 | 
					
 | 
				
			||||||
 | 
						/* filled by get_id() */
 | 
				
			||||||
 | 
						int id_class;			/* see ../lpass1/l_class.h */
 | 
				
			||||||
	char id_name[NAMESIZE];
 | 
						char id_name[NAMESIZE];
 | 
				
			||||||
 | 
						int id_statnr;
 | 
				
			||||||
	char id_file[FNAMESIZE];
 | 
						char id_file[FNAMESIZE];
 | 
				
			||||||
	int id_line;
 | 
						int id_line;
 | 
				
			||||||
	int id_nrargs;
 | 
					 | 
				
			||||||
	char id_argtps[ARGTPSSIZE];
 | 
					 | 
				
			||||||
	int id_returns;
 | 
					 | 
				
			||||||
	char id_type[TYPESIZE];
 | 
						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_called;
 | 
				
			||||||
	int id_used;
 | 
						int id_used;
 | 
				
			||||||
	int id_ignored;
 | 
						int id_ignored;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,46 +1,55 @@
 | 
				
			||||||
#include	<varargs.h>
 | 
					#include	<alloc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include	"../lpass1/l_lint.h"
 | 
					#include	"../lpass1/l_lint.h"
 | 
				
			||||||
#include	"../lpass1/l_class.h"
 | 
					#include	"../lpass1/l_class.h"
 | 
				
			||||||
 | 
					#include	"class.h"
 | 
				
			||||||
#include	"inpdef.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	streq(s1,s2)	(strcmp(s1, s2) == 0)
 | 
				
			||||||
#define	min(a,b)	((a) <= (b) ? (a) : (b))
 | 
					#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;
 | 
					#define	same_name()	(dot && streq(cur_name, dot->id_name))
 | 
				
			||||||
struct inpdef *dot_id,
 | 
					#define	same_obj(stnr)	(same_name() && dot->id_statnr == stnr)
 | 
				
			||||||
	*ext_def,
 | 
					 | 
				
			||||||
	*static_def;
 | 
					 | 
				
			||||||
struct inpdef *id_read();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#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)
 | 
					main(argc, argv)
 | 
				
			||||||
	char *argv[];
 | 
						char *argv[];
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inpdef *id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	init(argc, argv);
 | 
						init(argc, argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	get_dot_id();
 | 
						dot = new_inpdef();
 | 
				
			||||||
	while (dot_id) {
 | 
						get_dot();
 | 
				
			||||||
		cur_name = dot_id->id_name;
 | 
						while (dot) {
 | 
				
			||||||
		read_defs();
 | 
							if (lib) {
 | 
				
			||||||
		while (dot_id && same_name()) {
 | 
								free_inpdef(lib);
 | 
				
			||||||
			id = id_read();
 | 
								lib = 0;
 | 
				
			||||||
			check(id);
 | 
							}
 | 
				
			||||||
			free_inpdef(id);
 | 
							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)
 | 
					init(argc, argv)
 | 
				
			||||||
	char *argv[];
 | 
						char *argv[];
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
/* Prepare standard input for reading using the input-package
 | 
					/*
 | 
				
			||||||
 * Read first inpdef into dot_id
 | 
					 | 
				
			||||||
 * Parse options
 | 
					 * Parse options
 | 
				
			||||||
 | 
					 * Prepare standard input for reading using the input-package
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					 | 
				
			||||||
	char *result;
 | 
						char *result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init_class();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (argc > 1 && *argv[1] == '-') {
 | 
						while (argc > 1 && *argv[1] == '-') {
 | 
				
			||||||
		switch (argv[1][1]) {
 | 
							switch (argv[1][1]) {
 | 
				
			||||||
		case 'u':
 | 
							case 'u':
 | 
				
			||||||
| 
						 | 
					@ -67,7 +77,7 @@ init(argc, argv)
 | 
				
			||||||
			options[argv[1][1]] = 1;
 | 
								options[argv[1][1]] = 1;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			/* ready to extend */
 | 
								/* ready to be extended */
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		argc--, argv++;
 | 
							argc--, argv++;
 | 
				
			||||||
| 
						 | 
					@ -77,248 +87,295 @@ init(argc, argv)
 | 
				
			||||||
		panic("InsertFile() fails");
 | 
							panic("InsertFile() fails");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
read_defs()
 | 
					get_dot()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct inpdef *id;
 | 
						if (!get_id(dot)) {
 | 
				
			||||||
 | 
							free_inpdef(dot);
 | 
				
			||||||
	if (ext_def || static_def)
 | 
							dot = 0;
 | 
				
			||||||
		panic("read_defs: slate not clean");/*???*/
 | 
							cur_name[0] = '\0';
 | 
				
			||||||
 | 
					 | 
				
			||||||
	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);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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)
 | 
					/******** L I B R A R Y ********/
 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	old_id = dot_id;
 | 
					 | 
				
			||||||
	cur_name = old_id->id_name;
 | 
					 | 
				
			||||||
	get_dot_id();
 | 
					 | 
				
			||||||
	return (old_id);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
get_dot_id()
 | 
					lib_def()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
/* Allocates a new inpdef, calls it dot_id and fills it */
 | 
						if (same_obj(0) && is_class(dot, CL_LIB)) {
 | 
				
			||||||
	dot_id = new_inpdef();
 | 
							lib = dot;
 | 
				
			||||||
	if (!get_id(dot_id)) {
 | 
							dot = new_inpdef();
 | 
				
			||||||
		free_inpdef(dot_id);
 | 
							get_dot();
 | 
				
			||||||
		cur_name = "";
 | 
						}
 | 
				
			||||||
		dot_id = 0;
 | 
					
 | 
				
			||||||
 | 
						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)
 | 
					/******** E X T E R N ********/
 | 
				
			||||||
	struct inpdef *id;
 | 
					
 | 
				
			||||||
 | 
					ext_def()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
/* Checks a declaration, function call or variable usage, described by id,
 | 
						if (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) {
 | 
				
			||||||
 * against the definitions.
 | 
							if (lib) {
 | 
				
			||||||
 */
 | 
								report("%L: %s also defined in library %L",
 | 
				
			||||||
	struct inpdef *idef;
 | 
									dot, dot->id_name, lib);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ext = dot;
 | 
				
			||||||
 | 
							dot = new_inpdef();
 | 
				
			||||||
 | 
							get_dot();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idef = definition(id);
 | 
						while (same_obj(0) && is_class(dot, CL_EXT|CL_DEF)) {
 | 
				
			||||||
	switch (id->id_class) {
 | 
							report("%L: %s also defined at %L",
 | 
				
			||||||
	case EFDC:
 | 
								dot, dot->id_name, ext);
 | 
				
			||||||
		if (!idef) {
 | 
							get_dot();
 | 
				
			||||||
			if (!options['u']) {
 | 
						}
 | 
				
			||||||
				report("%L: %s declared but never defined",
 | 
					}
 | 
				
			||||||
					id, id->id_name);
 | 
					
 | 
				
			||||||
			}
 | 
					ext_decls()
 | 
				
			||||||
			discard_defs();
 | 
					{
 | 
				
			||||||
			break;
 | 
						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) {
 | 
							ext = dot;
 | 
				
			||||||
			report("%L: function %s declared as variable at %L",
 | 
							dot = new_inpdef();
 | 
				
			||||||
				id, id->id_name, idef);
 | 
							get_dot();
 | 
				
			||||||
			break;
 | 
							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)) {
 | 
							get_dot();
 | 
				
			||||||
			report("%L: value of function %s declared differently at %L",
 | 
							return;
 | 
				
			||||||
				id, id->id_name, idef);
 | 
						}
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		break;
 | 
						def->id_called = 1;
 | 
				
			||||||
	case EVDC:
 | 
					
 | 
				
			||||||
		if (!idef) {
 | 
						if (def->id_args) {
 | 
				
			||||||
			if (!options['u']) {
 | 
							check_args(dot, def);
 | 
				
			||||||
				report("%L: %s declared but never defined",
 | 
							if (dot->id_valused == USED && !def->id_valreturned) {
 | 
				
			||||||
					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) {
 | 
					 | 
				
			||||||
			report("%L: value of %s is used, but none is returned at %L",
 | 
								report("%L: value of %s is used, but none is returned at %L",
 | 
				
			||||||
				id, id->id_name, idef);
 | 
									dot, dot->id_name, def);
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		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");
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (dot->id_valused) {
 | 
				
			||||||
 | 
						case USED:
 | 
				
			||||||
 | 
							def->id_used = 1;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case VU:
 | 
						case IGNORED:
 | 
				
			||||||
		if (!idef) {
 | 
							def->id_ignored = 1;
 | 
				
			||||||
			if (!options['u']) {
 | 
					 | 
				
			||||||
				report("%L: variable %s used but not defined",
 | 
					 | 
				
			||||||
					id, id->id_name);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			discard_defs();
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		idef->id_called = 1;
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case EFDF:
 | 
						case VOIDED:
 | 
				
			||||||
	case SFDF:
 | 
							def->id_voided = 1;
 | 
				
			||||||
	case EVDF:
 | 
					 | 
				
			||||||
	case SVDF:
 | 
					 | 
				
			||||||
	case LFDF:
 | 
					 | 
				
			||||||
	case LVDF:
 | 
					 | 
				
			||||||
		panic("check() called for a definition");
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("invalid class (%c) in check", id->id_class);
 | 
							panic("invalid dot->id_valused in check");
 | 
				
			||||||
		break;
 | 
							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()) {
 | 
						get_dot();
 | 
				
			||||||
		id = id_read();
 | 
					}
 | 
				
			||||||
		free_inpdef(id);
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/******** S T A T I C ********/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					statics()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (same_name() && dot->id_statnr != 0) {
 | 
				
			||||||
 | 
							one_static(dot->id_statnr);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
check_args(id, idef)
 | 
					one_static(stnr)
 | 
				
			||||||
	struct inpdef *id, *idef;
 | 
						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 *act_tp = id->id_argtps;
 | 
				
			||||||
	register char *def_tp = idef->id_argtps;
 | 
						register char *def_tp = def->id_argtps;
 | 
				
			||||||
	register int i;
 | 
						register int i;
 | 
				
			||||||
	register int nrargs;		/* # of args to be type-checked */
 | 
						register int nrargs;		/* # of args to be type-checked */
 | 
				
			||||||
	register int varargs;
 | 
						register int varargs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* determine nrargs */
 | 
						/* determine nrargs */
 | 
				
			||||||
	if (idef->id_nrargs < 0) {
 | 
						if (def->id_nrargs < 0) {
 | 
				
			||||||
		varargs = 1;
 | 
							varargs = 1;
 | 
				
			||||||
		nrargs = -idef->id_nrargs - 1;
 | 
							nrargs = -def->id_nrargs - 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		varargs = 0;
 | 
							varargs = 0;
 | 
				
			||||||
		nrargs = idef->id_nrargs;
 | 
							nrargs = def->id_nrargs;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* adjust nrargs, if necessary */
 | 
						/* adjust nrargs, if necessary */
 | 
				
			||||||
	if (varargs) {
 | 
						if (varargs) {
 | 
				
			||||||
		if (nrargs > id->id_nrargs) {
 | 
							if (nrargs > id->id_nrargs) {
 | 
				
			||||||
			report("%L: number of args to %s differs from %L",
 | 
								report("%L: number of args to %s differs from %L",
 | 
				
			||||||
				id, id->id_name, idef);
 | 
									id, id->id_name, def);
 | 
				
			||||||
			nrargs = id->id_nrargs;
 | 
								nrargs = id->id_nrargs;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		if (nrargs != id->id_nrargs) {
 | 
							if (nrargs != id->id_nrargs) {
 | 
				
			||||||
			report("%L: number of args to %s differs from %L",
 | 
								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);
 | 
								nrargs = min(nrargs, id->id_nrargs);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -346,19 +403,27 @@ check_args(id, idef)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!type_match(act, def)) {
 | 
							if (!type_match(act, def)) {
 | 
				
			||||||
			report("%L: arg %d of %s differs from that at %L",
 | 
								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++ = ':';
 | 
							*act_tp++ = ':';
 | 
				
			||||||
		*def_tp++ = ':';
 | 
							*def_tp++ = ':';
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int
 | 
				
			||||||
 | 
					type_equal(act, def)
 | 
				
			||||||
 | 
						char *act, *def;
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return streq(act, def);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
type_match(act, def)
 | 
					type_match(act, def)
 | 
				
			||||||
	char *act, *def;
 | 
						char *act, *def;
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (type_equal(act, def))
 | 
						if (type_equal(act, def))
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (act[0] == '+') {
 | 
						if (act[0] == '+') {
 | 
				
			||||||
		/* a non-negative constant */
 | 
							/* a non-negative constant */
 | 
				
			||||||
		/* might be signed or unsigned */
 | 
							/* might be signed or unsigned */
 | 
				
			||||||
| 
						 | 
					@ -373,181 +438,22 @@ type_match(act, def)
 | 
				
			||||||
	return 0;
 | 
						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)
 | 
					print_id(id)
 | 
				
			||||||
	struct inpdef *id;
 | 
						struct inpdef *id;
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	print("inpdef: %s, %s, %04d, \"%s\", %d, %d, %s, %d, %s\n",
 | 
						print("inpdef: %s, %s, %04d, \"%s\", %d, %s",
 | 
				
			||||||
		id->id_class == EFDF ? "EFDF" :
 | 
					 | 
				
			||||||
		id->id_class == SFDF ? "SFDF" :
 | 
					 | 
				
			||||||
		id->id_class == EVDF ? "EVDF" :
 | 
					 | 
				
			||||||
		id->id_class == SVDF ? "SVDF" :
 | 
					 | 
				
			||||||
		id->id_class == LFDF ? "LFDF" :
 | 
							id->id_class == LFDF ? "LFDF" :
 | 
				
			||||||
		id->id_class == LVDF ? "LVDF" :
 | 
							id->id_class == LVDF ? "LVDF" :
 | 
				
			||||||
 | 
							id->id_class == EFDF ? "EFDF" :
 | 
				
			||||||
 | 
							id->id_class == EVDF ? "EVDF" :
 | 
				
			||||||
		id->id_class == EFDC ? "EFDC" :
 | 
							id->id_class == EFDC ? "EFDC" :
 | 
				
			||||||
		id->id_class == EVDC ? "EVDC" :
 | 
							id->id_class == EVDC ? "EVDC" :
 | 
				
			||||||
		id->id_class == IFDC ? "IFDC" :
 | 
							id->id_class == IFDC ? "IFDC" :
 | 
				
			||||||
 | 
							id->id_class == SFDF ? "SFDF" :
 | 
				
			||||||
 | 
							id->id_class == SVDF ? "SVDF" :
 | 
				
			||||||
		id->id_class == FC ? "FC" :
 | 
							id->id_class == FC ? "FC" :
 | 
				
			||||||
		id->id_class == VU ? "VU" :
 | 
							id->id_class == VU ? "VU" :
 | 
				
			||||||
		id->id_class == ERRCL ? "ERRCL" : "<BADCLASS>",
 | 
							id->id_class == ERRCL ? "ERRCL" : "<BADCLASS>",
 | 
				
			||||||
| 
						 | 
					@ -555,9 +461,21 @@ print_id(id)
 | 
				
			||||||
		id->id_statnr,
 | 
							id->id_statnr,
 | 
				
			||||||
		id->id_file,
 | 
							id->id_file,
 | 
				
			||||||
		id->id_line,
 | 
							id->id_line,
 | 
				
			||||||
		id->id_nrargs,
 | 
							id->id_type
 | 
				
			||||||
		((id->id_nrargs == 0) ? "" : id->id_argtps),
 | 
						);
 | 
				
			||||||
		id->id_returns,
 | 
						if (is_class(id, CL_FUNC|CL_DEF) || is_class(id, CL_FUNC|CL_USAGE)) {
 | 
				
			||||||
		id->id_type);
 | 
							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");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,13 @@
 | 
				
			||||||
#include "../lpass1/l_class.h"
 | 
					#include	"../lpass1/l_class.h"
 | 
				
			||||||
#include "inpdef.h"
 | 
					#include	"class.h"
 | 
				
			||||||
 | 
					#include	"inpdef.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <ctype.h>
 | 
					#include	<ctype.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define	INP_NPUSHBACK 2
 | 
					#define	INP_NPUSHBACK 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <inp_pkg.spec>
 | 
					#include	<inp_pkg.spec>
 | 
				
			||||||
#include <inp_pkg.body>
 | 
					#include	<inp_pkg.body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PRIVATE int LineNr = 1;
 | 
					PRIVATE int LineNr = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,37 +26,49 @@ int
 | 
				
			||||||
get_id(id)
 | 
					get_id(id)
 | 
				
			||||||
	struct inpdef *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))
 | 
						if (!ReadString(id->id_name, ':', NAMESIZE))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	if (!ReadInt(&id->id_statnr))
 | 
						if (!ReadInt(&id->id_statnr))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	SkipChar(':');
 | 
						SkipChar(':');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loadchar(id->id_class);
 | 
						loadchar(id->id_class);
 | 
				
			||||||
	if (id->id_class == EOI)
 | 
						if (id->id_class == EOI)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	SkipChar(':');
 | 
						SkipChar(':');
 | 
				
			||||||
	switch (id->id_class) {
 | 
					
 | 
				
			||||||
	case EFDF:
 | 
						if (is_class(id, CL_FUNC|CL_DEF) || is_class(id, CL_FUNC|CL_USAGE)) {
 | 
				
			||||||
	case SFDF:
 | 
							/* read the argument information */
 | 
				
			||||||
	case LFDF:
 | 
							id->id_args = 1;
 | 
				
			||||||
	case FC:
 | 
					 | 
				
			||||||
		if (!ReadInt(&id->id_nrargs))
 | 
							if (!ReadInt(&id->id_nrargs))
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		SkipChar(':');
 | 
							SkipChar(':');
 | 
				
			||||||
		if (!ReadArgs(id->id_nrargs, id->id_argtps))
 | 
							if (!ReadArgs(id->id_nrargs, id->id_argtps))
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		if (!ReadInt(&id->id_returns))
 | 
							if (id->id_class == FC) {
 | 
				
			||||||
			return 0;
 | 
								/* function call */
 | 
				
			||||||
 | 
								if (!ReadInt(&id->id_valused))
 | 
				
			||||||
 | 
									return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								/* function definition */
 | 
				
			||||||
 | 
								if (!ReadInt(&id->id_valreturned))
 | 
				
			||||||
 | 
									return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		SkipChar(':');
 | 
							SkipChar(':');
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						else {
 | 
				
			||||||
 | 
							id->id_args = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ReadString(id->id_type, ':', TYPESIZE))
 | 
						if (!ReadString(id->id_type, ':', TYPESIZE))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	if (!ReadInt(&id->id_line))
 | 
						if (!ReadInt(&id->id_line))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	SkipChar(':');
 | 
						SkipChar(':');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ReadString(id->id_file, '\n', FNAMESIZE))
 | 
						if (!ReadString(id->id_file, '\n', FNAMESIZE))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	{	extern char options[];
 | 
						{	extern char options[];
 | 
				
			||||||
| 
						 | 
					@ -69,14 +82,16 @@ PRIVATE int
 | 
				
			||||||
ReadString(buf, delim, maxsize)
 | 
					ReadString(buf, delim, maxsize)
 | 
				
			||||||
	char *buf;
 | 
						char *buf;
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
/* Reads a string until 'delim' is encountered.
 | 
						/*	Reads a string until 'delim' is encountered.
 | 
				
			||||||
 * Delim is discarded.
 | 
							Delim is discarded.
 | 
				
			||||||
 * If 'maxsize-1' is exceeded, "string too long" is written by panic().
 | 
							If 'maxsize-1' is exceeded, "string too long" is written
 | 
				
			||||||
 * A '\0' is appended to the string.
 | 
							by panic().
 | 
				
			||||||
 * At EOI 0 is returned, else the length of the string (including
 | 
							A '\0' is appended to the string.
 | 
				
			||||||
 * the appended '\0') is returned.
 | 
							At EOI 0 is returned, else the length of the string (including
 | 
				
			||||||
 */
 | 
							the appended '\0') is returned.
 | 
				
			||||||
	int ch;
 | 
						*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int ch = 0;
 | 
				
			||||||
	int nread = 0;
 | 
						int nread = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (nread < maxsize - 1) {
 | 
						while (nread < maxsize - 1) {
 | 
				
			||||||
| 
						 | 
					@ -87,11 +102,11 @@ ReadString(buf, delim, maxsize)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		buf[nread++] = (char)ch;
 | 
							buf[nread++] = (char)ch;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						buf[nread++] = '\0';
 | 
				
			||||||
	if (ch != delim) {
 | 
						if (ch != delim) {
 | 
				
			||||||
		panic("line %d: string too long: %s", LineNr, buf);
 | 
							panic("line %d: string too long: %s", LineNr, buf);
 | 
				
			||||||
		/*NOTREACHED*/
 | 
							/*NOTREACHED*/
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	buf[nread++] = '\0';
 | 
					 | 
				
			||||||
	return (nread);
 | 
						return (nread);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										81
									
								
								lang/cem/lint/lpass2/report.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								lang/cem/lint/lpass2/report.c
									
										
									
									
									
										Normal 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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue