formats introduced
This commit is contained in:
		
							parent
							
								
									bcb3b108a5
								
							
						
					
					
						commit
						ac21f8d98a
					
				
					 7 changed files with 355 additions and 141 deletions
				
			
		|  | @ -7,7 +7,7 @@ | |||
| 
 | ||||
| # Machine and environ dependent definitions
 | ||||
| EMHOME =	/usr/em | ||||
| LPASS1 =	../lpass1 | ||||
| LPASS1 =	$(EMHOME)/lang/cem/cemcom | ||||
| 
 | ||||
| # Libraries and EM interface definitions
 | ||||
| SYSLIB =	$(EMHOME)/modules/lib/libsystem.a | ||||
|  | @ -24,12 +24,13 @@ CFLAGS =	-I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg -I/usr/include | |||
| .str.h: | ||||
| 	$(LPASS1)/make.allocd <$*.str >$*.h | ||||
| 
 | ||||
| SRC =	lpass2.c read.c report.c class.c | ||||
| OBJ =	lpass2.o read.o report.o class.o | ||||
| SRC =	lpass2.c checkargs.c read.c report.c class.c l_print3ack.c | ||||
| OBJ =	lpass2.o checkargs.o read.o report.o class.o l_print3ack.o | ||||
| 
 | ||||
| test:	lpass2 | ||||
| 	make lint | ||||
| #	lpass2 -xh <.i
 | ||||
| 	lpass2 -xh <.i | ||||
| #	make lint
 | ||||
| 
 | ||||
| 
 | ||||
| lpass2:	$(OBJ) Makefile next.o | ||||
| 	$(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) next.o $(LLIBS) -o lpass2 | ||||
|  |  | |||
							
								
								
									
										248
									
								
								lang/cem/lint/lpass2/checkargs.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								lang/cem/lint/lpass2/checkargs.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,248 @@ | |||
| /*
 | ||||
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||
|  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||
|  */ | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| /******** A R G U M E N T   T Y P E   C H E C K I N G ********/ | ||||
| 
 | ||||
| #include	"private.h" | ||||
| #include	"inpdef.h" | ||||
| 
 | ||||
| extern char *strcpy(); | ||||
| 
 | ||||
| #define	streq(s1,s2)	(strcmp(s1, s2) == 0) | ||||
| 
 | ||||
| /* a format is developed into a normal parameter definition */ | ||||
| PRIVATE int is_formatargs;		/* present or not */ | ||||
| PRIVATE char formatargs[1000];		/* the definitions */ | ||||
| 
 | ||||
| PRIVATE chk_argtps(); | ||||
| PRIVATE char *next_atype(); | ||||
| PRIVATE int type_match(); | ||||
| 
 | ||||
| int | ||||
| type_equal(act, form) | ||||
| 	char *act, *form; | ||||
| { | ||||
| 	return	streq(act, form) | ||||
| 	||	streq(act, "erroneous") | ||||
| 	||	streq(form, "erroneous"); | ||||
| } | ||||
| 
 | ||||
| chk_args(id, def) | ||||
| 	struct inpdef *id, *def; | ||||
| { | ||||
| 	char *act_tp = id->id_argtps; | ||||
| 	int nrargs = 0;			/* number of args */ | ||||
| 
 | ||||
| 	/* clear format */ | ||||
| 	is_formatargs = 0; | ||||
| 
 | ||||
| 	/* check normal arguments */ | ||||
| 	chk_argtps(id, def, &nrargs, act_tp, def->id_argtps); | ||||
| 
 | ||||
| 	if (is_formatargs) { | ||||
| 		/* there was a format */ | ||||
| 		register int i; | ||||
| 
 | ||||
| 		/* skip over the actuals already covered */ | ||||
| 		for (i = 0; i < nrargs; i++) { | ||||
| 			act_tp = next_atype(act_tp); | ||||
| 		} | ||||
| 
 | ||||
| 		/* and check the format arguments */ | ||||
| 		chk_argtps(id, (struct inpdef *)0, &nrargs, | ||||
| 						act_tp, &formatargs[0]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| PRIVATE chk_argtps(id, def, nrargs, act_tp, form_tp) | ||||
| 	struct inpdef *id;		/* the actual call */ | ||||
| 	struct inpdef *def;		/* 0 for format-derived definition */ | ||||
| 	int *nrargs;			/* in-out parameter, counting */ | ||||
| 	char *act_tp;			/* actual types */ | ||||
| 	char *form_tp;			/* formal type definitions */ | ||||
| { | ||||
| 	while (*act_tp && *form_tp) { | ||||
| 		register char *act_start = act_tp; | ||||
| 		register char *form_start = form_tp; | ||||
| 
 | ||||
| 		/* isolate actual argument type */ | ||||
| 		act_tp = next_atype(act_tp); | ||||
| 		act_tp[-1] = '\0'; | ||||
| 
 | ||||
| 		/* isolate formal argument type */ | ||||
| 		form_tp = next_atype(form_tp); | ||||
| 		form_tp[-1] = '\0'; | ||||
| 
 | ||||
| 		(*nrargs)++; | ||||
| 		if (!type_match(id, act_start, form_start)) { | ||||
| 			report("%L: arg %d of %s differs from that in %L", | ||||
| 				id, *nrargs, id->id_name, def); | ||||
| 		} | ||||
| 		act_tp[-1] = ':'; | ||||
| 		form_tp[-1] = ':'; | ||||
| 	} | ||||
| 
 | ||||
| 	if (*form_tp) { | ||||
| 		/* formal type definitions not exhausted */ | ||||
| 		report("%L: %s has fewer arguments than in %L", | ||||
| 			id, id->id_name, def); | ||||
| 	} | ||||
| 	if (*act_tp) { | ||||
| 		/* actual types not exhausted */ | ||||
| 		if (def && def->id_nrargs < 0) { | ||||
| 			/* the function had VARARGS */ | ||||
| 		} | ||||
| 		else { | ||||
| 			report("%L: %s has more arguments than in %L", | ||||
| 				id, id->id_name, def); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| PRIVATE char * | ||||
| next_atype(tp) | ||||
| 	char *tp; | ||||
| { | ||||
| 	while (*tp && *tp != ':') { | ||||
| 		tp++; | ||||
| 	} | ||||
| 	if (*tp == ':') { | ||||
| 		tp++; | ||||
| 	} | ||||
| 	return tp; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| PRIVATE type_match(id, act, form) | ||||
| 	struct inpdef *id; | ||||
| 	char *act, *form; | ||||
| { | ||||
| 	if (form[0] == '"' && act[0] == '"') { | ||||
| 		conv_format(id, act, form); | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (	(form[0] == '"' && streq(act, "char*")) | ||||
| 	||	(act[0] == '"' && streq(form, "char*")) | ||||
| 	) { | ||||
| 		return 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (type_equal(act, form)) | ||||
| 		return 1; | ||||
| 
 | ||||
| 	if (act[0] == '+') { | ||||
| 		/* a non-negative constant */ | ||||
| 		/* might be signed or unsigned */ | ||||
| 		if (type_equal(&act[1], form)) | ||||
| 			return 1; | ||||
| 		if (	strncmp(form, "unsigned ", strlen("unsigned ")) == 0 | ||||
| 		&&	type_equal(&act[1], &form[strlen("unsigned ")]) | ||||
| 		) { | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| PRIVATE conv_format(id, act, form) | ||||
| 	struct inpdef *id; | ||||
| 	char *act, *form; | ||||
| { | ||||
| 	/*	convert the actual format into a def-list, using the
 | ||||
| 		formal format (form) as a map to convert from %X to type | ||||
| 	*/ | ||||
| 	register char *fmt = &formatargs[0]; | ||||
| 
 | ||||
| 	is_formatargs = 1; | ||||
| 	while (*act) { | ||||
| 		register char *map; | ||||
| 
 | ||||
| 		/* find next conversion specification */ | ||||
| 		while (*act && *act != '%') { | ||||
| 			act++; | ||||
| 		} | ||||
| 		if (*act++ != '%') | ||||
| 			break; | ||||
| 		if (*act == '%') { | ||||
| 			/* %% */ | ||||
| 			act++; | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		/* process options */ | ||||
| 		if (*act && *act == '-') { | ||||
| 			act++; | ||||
| 		} | ||||
| 		while (*act && ('0' <= *act && *act <= '9')) { | ||||
| 			act++; | ||||
| 		} | ||||
| 		if (*act == '*') { | ||||
| 			act++; | ||||
| 			strcpy(fmt, "int:"); | ||||
| 			fmt += 4; | ||||
| 		} | ||||
| 		if (*act && *act == '.') { | ||||
| 			act++; | ||||
| 		} | ||||
| 		while (*act && ('0' <= *act && *act <= '9')) { | ||||
| 			act++; | ||||
| 		} | ||||
| 		if (*act == '*') { | ||||
| 			act++; | ||||
| 			strcpy(fmt, "int:"); | ||||
| 			fmt += 4; | ||||
| 		} | ||||
| 
 | ||||
| 		map = form; | ||||
| 		while (*map) { | ||||
| 			register char *cs = act; | ||||
| 
 | ||||
| 			/* find next conversion mapping */ | ||||
| 			while (*map && *map != '%') { | ||||
| 				map++; | ||||
| 			} | ||||
| 			if (*map++ != '%') { | ||||
| 				/* we ran off the map */ | ||||
| 				report("%L: unknown conversion specification in format", | ||||
| 					id); | ||||
| 				break; | ||||
| 			} | ||||
| 
 | ||||
| 			while (*map && *map != '=') { | ||||
| 				register int match = 0; | ||||
| 
 | ||||
| 				if (*map == '[') { | ||||
| 					while (*map && *map != ']') { | ||||
| 						if (*map == *cs) { | ||||
| 							match = 1; | ||||
| 						} | ||||
| 						map++; | ||||
| 					} | ||||
| 				} | ||||
| 				else { | ||||
| 					match = (*map == *cs); | ||||
| 				} | ||||
| 
 | ||||
| 				if (match) { | ||||
| 					map++, cs++; | ||||
| 				} | ||||
| 				else	break; | ||||
| 			} | ||||
| 			if (*map++ == '=') { | ||||
| 				/* found the type belonging to %*cs */ | ||||
| 				while (*map && *map != '%' && *map != '"') { | ||||
| 					*fmt++ = *map++; | ||||
| 				} | ||||
| 				*fmt++ = ':'; | ||||
| 				act = cs; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	*fmt++ = '\0'; | ||||
| } | ||||
| 
 | ||||
|  | @ -9,7 +9,7 @@ | |||
| 	class[] contains a bit pattern for each letter, with those bits set | ||||
| 	that correspond to the lint class meaning of the letter. | ||||
| 
 | ||||
| 	This facility is used through the macro  is_class(inpdef_var, CL_???) | ||||
| 	This facility is used through the macro  is_class(inpdef_var, CL_XXX) | ||||
| */ | ||||
| 
 | ||||
| #define	CL_DEF		(1<<0) | ||||
|  |  | |||
							
								
								
									
										30
									
								
								lang/cem/lint/lpass2/l_print3ack.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								lang/cem/lint/lpass2/l_print3ack.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| /*
 | ||||
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||
|  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||
|  */ | ||||
| /* $Header$ */ | ||||
| 
 | ||||
| /*	A C K   P R I N T   M O D U L E   D E F I N T I O N S   */ | ||||
| 
 | ||||
| #ifdef	lint | ||||
| 
 | ||||
| #include	<system.h> | ||||
| 
 | ||||
| /* LINTLIBRARY */ | ||||
| 
 | ||||
| /* FORMAT0 $
 | ||||
| 	%[bdox] = int		%l[bdox] = long | ||||
| 	%c = int		%s = char * | ||||
| 	%u = unsigned int | ||||
| $ */ | ||||
| print(format) char *format; { ; } | ||||
| 
 | ||||
| /* FORMAT1 */ | ||||
| fprint(filep, format) File *filep; char *format; { ; } | ||||
| /* FORMAT1 */ | ||||
| sprint(s, format) char *s; char *format; { ; } | ||||
| /* FORMAT1 */ | ||||
| doprnt(filep, format) File *filep; char *format; { ; } | ||||
| 
 | ||||
| #endif	lint | ||||
| 
 | ||||
|  | @ -15,13 +15,11 @@ | |||
| extern char *strcpy(); | ||||
| 
 | ||||
| #define	streq(s1,s2)	(strcmp(s1, s2) == 0) | ||||
| #define	min(a,b)	((a) <= (b) ? (a) : (b)) | ||||
| 
 | ||||
| PRIVATE char cur_name[NAMESIZE]; | ||||
| PRIVATE struct inpdef *dot, *lib, *ext, *sta; | ||||
| 
 | ||||
| PRIVATE check_args(); | ||||
| PRIVATE check_def(); | ||||
| PRIVATE chk_def(); | ||||
| PRIVATE ext_decls(); | ||||
| PRIVATE ext_def(); | ||||
| PRIVATE get_dot(); | ||||
|  | @ -32,8 +30,6 @@ PRIVATE one_func_call(); | |||
| PRIVATE one_var_usage(); | ||||
| PRIVATE stat_def(); | ||||
| PRIVATE statics(); | ||||
| PRIVATE int type_equal(); | ||||
| PRIVATE int type_match(); | ||||
| PRIVATE usage(); | ||||
| 
 | ||||
| #define	same_name()	(dot && streq(cur_name, dot->id_name)) | ||||
|  | @ -67,7 +63,7 @@ main(argc, argv) | |||
| 		ext_decls(); | ||||
| 		usage(0); | ||||
| 		if (ext) | ||||
| 			check_def(ext); | ||||
| 			chk_def(ext); | ||||
| 		statics(); | ||||
| 		if (same_name()) { | ||||
| 			/*	there are more lines for this name that have
 | ||||
|  | @ -199,6 +195,7 @@ PRIVATE one_ext_decl(kind, other_kind, other_class) | |||
| 		report("%L: %s %s %s as %s at %L", | ||||
| 			dot, kind, dot->id_name, defdec(def), other_kind, def); | ||||
| 		/* no further testing possible */ | ||||
| 		get_dot(); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -264,7 +261,7 @@ PRIVATE one_func_call(def) | |||
| 	def->id_called = 1; | ||||
| 
 | ||||
| 	if (def->id_args) { | ||||
| 		check_args(dot, def); | ||||
| 		chk_args(dot, def); | ||||
| 		if (	dot->id_valused == USED | ||||
| 		&&	def->id_valreturned == NOVALRETURNED | ||||
| 		) { | ||||
|  | @ -284,7 +281,7 @@ PRIVATE one_func_call(def) | |||
| 		def->id_voided = 1; | ||||
| 		break; | ||||
| 	default: | ||||
| 		panic("invalid dot->id_valused in check"); | ||||
| 		panic("invalid dot->id_valused in one_func_call()"); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -326,7 +323,7 @@ PRIVATE statics() | |||
| 		stat_def(stnr); | ||||
| 		usage(stnr); | ||||
| 		if (sta) | ||||
| 			check_def(sta); | ||||
| 			chk_def(sta); | ||||
| 
 | ||||
| 		if (same_obj(stnr)) | ||||
| 			panic("sequence error in input"); | ||||
|  | @ -360,7 +357,7 @@ PRIVATE stat_def(stnr) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| PRIVATE check_def(def) | ||||
| PRIVATE chk_def(def) | ||||
| 	struct inpdef *def; | ||||
| { | ||||
| 	if (!def) | ||||
|  | @ -396,104 +393,6 @@ PRIVATE check_def(def) | |||
| } | ||||
| 
 | ||||
| 
 | ||||
| /******** T Y P E   C H E C K I N G ********/ | ||||
| 
 | ||||
| PRIVATE check_args(id, def) | ||||
| 	struct inpdef *id, *def; | ||||
| { | ||||
| 	register char *act_tp = id->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 (def->id_nrargs < 0) { | ||||
| 		varargs = 1; | ||||
| 		nrargs = -def->id_nrargs - 1; | ||||
| 	} | ||||
| 	else { | ||||
| 		varargs = 0; | ||||
| 		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, 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, def); | ||||
| 			nrargs = min(nrargs, id->id_nrargs); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 1; i <= nrargs; i++) { | ||||
| 		register char *act_par = act_tp; | ||||
| 		register char *def_par = def_tp; | ||||
| 
 | ||||
| 		/* isolate actual argument type */ | ||||
| 		while (*act_tp) { | ||||
| 			if (*act_tp == ':') { | ||||
| 				*act_tp = '\0'; | ||||
| 				break; | ||||
| 			} | ||||
| 			act_tp++; | ||||
| 		} | ||||
| 		/* isolate formal argument type */ | ||||
| 		while (*def_tp) { | ||||
| 			if (*def_tp == ':') { | ||||
| 				*def_tp = '\0'; | ||||
| 				break; | ||||
| 			} | ||||
| 			def_tp++; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!type_match(act_par, def_par)) { | ||||
| 			report("%L: arg %d of %s differs from that at %L", | ||||
| 				id, i, id->id_name, def); | ||||
| 		} | ||||
| 		*act_tp++ = ':'; | ||||
| 		*def_tp++ = ':'; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int | ||||
| PRIVATE type_equal(act, def) | ||||
| 	char *act, *def; | ||||
| { | ||||
| 	return	streq(act, def) | ||||
| 	||	streq(act, "erroneous") | ||||
| 	||	streq(def, "erroneous"); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| PRIVATE 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 */ | ||||
| 		if (type_equal(&act[1], def)) | ||||
| 			return 1; | ||||
| 		if (	strncmp(def, "unsigned ", strlen("unsigned ")) == 0 | ||||
| 		&&	type_equal(&act[1], &def[strlen("unsigned ")]) | ||||
| 		) { | ||||
| 			return 1; | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /******** D E B U G G I N G ********/ | ||||
| 
 | ||||
| print_id(name, id) | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ | |||
| 
 | ||||
| #include	"private.h" | ||||
| 
 | ||||
| PRIVATE int LineNr = 1; | ||||
| int LineNr = 1; | ||||
| 
 | ||||
| /* Two dangerous macro's. They replace a single statement by
 | ||||
|  * two statements | ||||
|  | @ -25,10 +25,13 @@ PRIVATE int LineNr = 1; | |||
| #define	loadchar(ch) LoadChar(ch); if (ch=='\n') LineNr++ | ||||
| #define	pushback(ch) PushBack(); if (ch=='\n') LineNr-- | ||||
| 
 | ||||
| /* all the ReadX() functions return 0 upon EOI */ | ||||
| PRIVATE int ReadString(); | ||||
| PRIVATE int ReadInt(); | ||||
| PRIVATE SkipChar(); | ||||
| PRIVATE int ReadArgs(); | ||||
| PRIVATE int ReadArg(); | ||||
| 
 | ||||
| PRIVATE SkipChar(); | ||||
| 
 | ||||
| int | ||||
| get_id(id) | ||||
|  | @ -79,20 +82,18 @@ get_id(id) | |||
| 
 | ||||
| 	if (!ReadString(id->id_file, '\n', FNAMESIZE)) | ||||
| 		return 0; | ||||
| 	return (1); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| 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(). | ||||
| 	/*	Reads a string until 'delim' is encountered; delim is
 | ||||
| 		discarded. | ||||
| 		If 'maxsize-1' is exceeded or the string contains a newline | ||||
| 		(which is not delim), panic() is called. | ||||
| 		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; | ||||
|  | @ -104,14 +105,18 @@ ReadString(buf, delim, maxsize) | |||
| 			return 0; | ||||
| 		if (ch == delim) | ||||
| 			break; | ||||
| 		if (ch == '\n') { | ||||
| 			panic("newline in string"); | ||||
| 			/*NOTREACHED*/ | ||||
| 		} | ||||
| 		buf[nread++] = (char)ch; | ||||
| 	} | ||||
| 	buf[nread++] = '\0'; | ||||
| 	if (ch != delim) { | ||||
| 		panic("line %d: string too long: %s", LineNr, buf); | ||||
| 		panic("string too long"); | ||||
| 		/*NOTREACHED*/ | ||||
| 	} | ||||
| 	return (nread); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| PRIVATE int | ||||
|  | @ -123,7 +128,6 @@ ReadInt(ip) | |||
|  * Non-digits except minus-sign in front of the number are discarded. | ||||
|  * Doesn't check on overflow. | ||||
|  * Just a minus-sign is interpreted as 0. (To prevent a look-ahead.) | ||||
|  * At EOI 0 is returned, else 1. | ||||
|  */ | ||||
| 	int ch; | ||||
| 	int negative = 0; | ||||
|  | @ -148,24 +152,12 @@ ReadInt(ip) | |||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| PRIVATE SkipChar(ch) | ||||
| { | ||||
| 	int c; | ||||
| 
 | ||||
| 	loadchar(c); | ||||
| 	if (c != ch) { | ||||
| 		panic("line %d: bad format, '%c' expected; '%c' read", | ||||
| 				LineNr, ch, c); | ||||
| 		/*NOTREACHED*/ | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| PRIVATE int | ||||
| ReadArgs(nrargs, buf) | ||||
| 	char *buf; | ||||
| { | ||||
| 	/*	Reads a string into buf with format
 | ||||
| 			<type1>:<type2>: ... :<typeN>: | ||||
| 			<type1>:<type2>: ... :<typeN>:\0 | ||||
| 		Note: format must include the final colon. | ||||
| 	*/ | ||||
| 	int i; | ||||
|  | @ -179,7 +171,7 @@ ReadArgs(nrargs, buf) | |||
| 	for (i = 0; i < nrargs; i++) { | ||||
| 		int n; | ||||
| 
 | ||||
| 		if (!ReadString(buf, ':', ARGTPSSIZE-charcount-1)) | ||||
| 		if (!ReadArg(buf, ARGTPSSIZE-charcount-1)) | ||||
| 			return 0; | ||||
| 		n = strlen(buf) + 1; | ||||
| 		charcount += n; | ||||
|  | @ -190,3 +182,40 @@ ReadArgs(nrargs, buf) | |||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| PRIVATE int | ||||
| ReadArg(buf, size) | ||||
| 	char *buf; | ||||
| 	int size; | ||||
| { | ||||
| 	int ch; | ||||
| 
 | ||||
| 	loadchar(ch); | ||||
| 	switch (ch) { | ||||
| 	case '"':	/* formal format or actual string */ | ||||
| 		*buf++ = ch; | ||||
| 		if (!ReadString(buf, ch, size-1)) | ||||
| 			return 0; | ||||
| 		buf += strlen(buf); | ||||
| 		*buf++ = ch; | ||||
| 		*buf++ = '\0'; | ||||
| 		SkipChar(':'); | ||||
| 		return 1; | ||||
| 	default:	/* normal type */ | ||||
| 		pushback(ch); | ||||
| 		return ReadString(buf, ':', size); | ||||
| 	case EOI: | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| PRIVATE SkipChar(ch) | ||||
| { | ||||
| 	int c; | ||||
| 
 | ||||
| 	loadchar(c); | ||||
| 	if (c != ch) { | ||||
| 		panic("bad format, '%c' expected; '%c' read", ch, c); | ||||
| 		/*NOTREACHED*/ | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,8 @@ | |||
| #define	MSGOUT		STDERR	/* filedes on which to write the messages */ | ||||
| #define	ERROUT		STDERR	/* filedes on which to write the panics */ | ||||
| 
 | ||||
| extern int LineNr; | ||||
| 
 | ||||
| PRIVATE rep_loc(); | ||||
| 
 | ||||
| /* VARARGS */ | ||||
|  | @ -90,6 +92,11 @@ PRIVATE | |||
| rep_loc(id) | ||||
| 	struct inpdef *id; | ||||
| { | ||||
| 	/* a definition can come from a number of places */ | ||||
| 	if (!id) { | ||||
| 		fprint(MSGOUT, "format"); | ||||
| 	} | ||||
| 	else | ||||
| 	if (is_class(id, CL_LIB)) { | ||||
| 		fprint(MSGOUT, "library file %s", id->id_file); | ||||
| 	} | ||||
|  | @ -103,7 +110,7 @@ rep_loc(id) | |||
| panic(fmt, args) | ||||
| 	char *fmt; | ||||
| { | ||||
| 	fprint(ERROUT, "PANIC, lint, pass2: "); | ||||
| 	fprint(ERROUT, "PANIC, lint, pass2: line %d: ", LineNr); | ||||
| 	doprnt(ERROUT, fmt, &args); | ||||
| 	fprint(ERROUT, "\n"); | ||||
| 	exit(1); | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue