xref: /netbsd-src/usr.bin/error/subr.c (revision 81b108b45f75f89f1e3ffad9fb6f074e771c0935)
1 /*	$NetBSD: subr.c,v 1.4 1995/09/10 15:55:15 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1980, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)subr.c	8.1 (Berkeley) 6/6/93";
39 #endif
40 static char rcsid[] = "$NetBSD: subr.c,v 1.4 1995/09/10 15:55:15 christos Exp $";
41 #endif /* not lint */
42 
43 #include <stdio.h>
44 #include <ctype.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include "error.h"
48 /*
49  *	Arrayify a list of rules
50  */
51 arrayify(e_length, e_array, header)
52 	int	*e_length;
53 	Eptr	**e_array;
54 	Eptr	header;
55 {
56 	reg	Eptr	errorp;
57 	reg	Eptr	*array;
58 	reg	int	listlength;
59 	reg	int	listindex;
60 
61 	for (errorp = header, listlength = 0;
62 	     errorp; errorp = errorp->error_next, listlength++)
63 		continue;
64 	array = (Eptr*)Calloc(listlength+1, sizeof (Eptr));
65 	for(listindex = 0, errorp = header;
66 	    listindex < listlength;
67 	    listindex++, errorp = errorp->error_next){
68 		array[listindex] = errorp;
69 		errorp->error_position = listindex;
70 	}
71 	array[listindex] = (Eptr)0;
72 	*e_length = listlength;
73 	*e_array = array;
74 }
75 
76 /*VARARGS1*/
77 error(msg, a1, a2, a3)
78 	char	*msg;
79 {
80 	fprintf(stderr, "Error: ");
81 	fprintf(stderr, msg, a1, a2, a3);
82 	fprintf(stderr, "\n");
83 	fflush(stdout);
84 	fflush(stderr);
85 	exit(6);
86 }
87 /*ARGSUSED*/
88 char *Calloc(nelements, size)
89 	int	nelements;
90 	int	size;
91 {
92 	char	*back;
93 	if ( (back = (char *)calloc(nelements, size)) == (char *)NULL){
94 		error("Ran out of memory.\n");
95 		exit(1);
96 	}
97 	return(back);
98 }
99 
100 char *strsave(instring)
101 	char	*instring;
102 {
103 	char	*outstring;
104 	(void)strcpy(outstring = (char *)Calloc(1, strlen(instring) + 1),
105 		instring);
106 	return(outstring);
107 }
108 /*
109  *	find the position of a given character in a string
110  *		(one based)
111  */
112 int position(string, ch)
113 	reg	char	*string;
114 	reg	char	ch;
115 {
116 	reg	int	i;
117 	if (string)
118 	for (i=1; *string; string++, i++){
119 		if (*string == ch)
120 			return(i);
121 	}
122 	return(-1);
123 }
124 /*
125  *	clobber the first occurance of ch in string by the new character
126  */
127 char *substitute(string, chold, chnew)
128 	char	*string;
129 	char	chold, chnew;
130 {
131 	reg	char	*cp = string;
132 
133 	if (cp)
134 	while (*cp){
135 		if (*cp == chold){
136 			*cp = chnew;
137 			break;
138 		}
139 		cp++;
140 	}
141 	return(string);
142 }
143 
144 char lastchar(string)
145 	char	*string;
146 {
147 	int	length;
148 	if (string == 0) return('\0');
149 	length = strlen(string);
150 	if (length >= 1)
151 		return(string[length-1]);
152 	else
153 		return('\0');
154 }
155 
156 char firstchar(string)
157 	char	*string;
158 {
159 	if (string)
160 		return(string[0]);
161 	else
162 		return('\0');
163 }
164 
165 char	next_lastchar(string)
166 	char	*string;
167 {
168 	int	length;
169 	if (string == 0) return('\0');
170 	length = strlen(string);
171 	if (length >= 2)
172 		return(string[length - 2]);
173 	else
174 		return('\0');
175 }
176 
177 clob_last(string, newstuff)
178 	char	*string, newstuff;
179 {
180 	int	length = 0;
181 	if (string)
182 		length = strlen(string);
183 	if (length >= 1)
184 		string[length - 1] = newstuff;
185 }
186 
187 /*
188  *	parse a string that is the result of a format %s(%d)
189  *	return TRUE if this is of the proper format
190  */
191 boolean persperdexplode(string, r_perd, r_pers)
192 	char	*string;
193 	char	**r_perd, **r_pers;
194 {
195 	reg	char	*cp;
196 		int	length = 0;
197 
198 	if (string)
199 		length = strlen(string);
200 	if (   (length >= 4)
201 	    && (string[length - 1] == ')' ) ){
202 		for (cp = &string[length - 2];
203 		     (isdigit(*cp)) && (*cp != '(');
204 		     --cp)
205 			continue;
206 		if (*cp == '('){
207 			string[length - 1] = '\0';	/* clobber the ) */
208 			*r_perd = strsave(cp+1);
209 			string[length - 1] = ')';
210 			*cp = '\0';			/* clobber the ( */
211 			*r_pers = strsave(string);
212 			*cp = '(';
213 			return(TRUE);
214 		}
215 	}
216 	return(FALSE);
217 }
218 /*
219  *	parse a quoted string that is the result of a format \"%s\"(%d)
220  *	return TRUE if this is of the proper format
221  */
222 boolean qpersperdexplode(string, r_perd, r_pers)
223 	char	*string;
224 	char	**r_perd, **r_pers;
225 {
226 	reg	char	*cp;
227 		int	length = 0;
228 
229 	if (string)
230 		length = strlen(string);
231 	if (   (length >= 4)
232 	    && (string[length - 1] == ')' ) ){
233 		for (cp = &string[length - 2];
234 		     (isdigit(*cp)) && (*cp != '(');
235 		     --cp)
236 			continue;
237 		if (*cp == '(' && *(cp - 1) == '"'){
238 			string[length - 1] = '\0';
239 			*r_perd = strsave(cp+1);
240 			string[length - 1] = ')';
241 			*(cp - 1) = '\0';		/* clobber the " */
242 			*r_pers = strsave(string + 1);
243 			*(cp - 1) = '"';
244 			return(TRUE);
245 		}
246 	}
247 	return(FALSE);
248 }
249 
250 static	char	cincomment[] = CINCOMMENT;
251 static	char	coutcomment[] = COUTCOMMENT;
252 static	char	fincomment[] = FINCOMMENT;
253 static	char	foutcomment[] = FOUTCOMMENT;
254 static	char	newline[] = NEWLINE;
255 static	char	piincomment[] = PIINCOMMENT;
256 static	char	pioutcomment[] = PIOUTCOMMENT;
257 static	char	lispincomment[] = LISPINCOMMENT;
258 static	char	riincomment[] = RIINCOMMENT;
259 static	char	rioutcomment[] = RIOUTCOMMENT;
260 static	char	troffincomment[] = TROFFINCOMMENT;
261 static	char	troffoutcomment[] = TROFFOUTCOMMENT;
262 static	char	mod2incomment[] = MOD2INCOMMENT;
263 static	char	mod2outcomment[] = MOD2OUTCOMMENT;
264 
265 struct	lang_desc lang_table[] = {
266 	/*INUNKNOWN	0*/	"unknown", cincomment,	coutcomment,
267 	/*INCPP		1*/	"cpp",	cincomment,    coutcomment,
268 	/*INCC		2*/	"cc",	cincomment,    coutcomment,
269 	/*INAS		3*/	"as",	ASINCOMMENT,   newline,
270 	/*INLD		4*/	"ld",	cincomment,    coutcomment,
271 	/*INLINT	5*/	"lint",	cincomment,    coutcomment,
272 	/*INF77		6*/	"f77",	fincomment,    foutcomment,
273 	/*INPI		7*/	"pi",	piincomment,   pioutcomment,
274 	/*INPC		8*/	"pc",	piincomment,   pioutcomment,
275 	/*INFRANZ	9*/	"franz",lispincomment, newline,
276 	/*INLISP	10*/	"lisp",	lispincomment, newline,
277 	/*INVAXIMA	11*/	"vaxima",lispincomment,newline,
278 	/*INRATFOR	12*/	"ratfor",fincomment,   foutcomment,
279 	/*INLEX		13*/	"lex",	cincomment,    coutcomment,
280 	/*INYACC	14*/	"yacc",	cincomment,    coutcomment,
281 	/*INAPL		15*/	"apl",	".lm",	       newline,
282 	/*INMAKE	16*/	"make",	ASINCOMMENT,   newline,
283 	/*INRI		17*/	"ri",	riincomment,   rioutcomment,
284 	/*INTROFF	18*/	"troff",troffincomment,troffoutcomment,
285 	/*INMOD2	19*/	"mod2",	mod2incomment, mod2outcomment,
286 				0,	0,	     0
287 };
288 
289 printerrors(look_at_subclass, errorc, errorv)
290 	boolean	look_at_subclass;
291 	int	errorc;
292 	Eptr	errorv[];
293 {
294 	reg	int	i;
295 	reg	Eptr	errorp;
296 
297 	for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]){
298 		if (errorp->error_e_class == C_IGNORE)
299 			continue;
300 		if (look_at_subclass && errorp->error_s_class == C_DUPL)
301 			continue;
302 		printf("Error %d, (%s error) [%s], text = \"",
303 			i,
304 			class_table[errorp->error_e_class],
305 			lang_table[errorp->error_language].lang_name);
306 		wordvprint(stdout,errorp->error_lgtext,errorp->error_text);
307 		printf("\"\n");
308 	}
309 }
310 
311 wordvprint(fyle, wordc, wordv)
312 	FILE	*fyle;
313 	int	wordc;
314 	char	*wordv[];
315 {
316 	int	i;
317 	char *sep = "";
318 
319 	for(i = 0; i < wordc; i++)
320 		if (wordv[i]) {
321 			fprintf(fyle, "%s%s",sep,wordv[i]);
322 			sep = " ";
323 		}
324 }
325 
326 /*
327  *	Given a string, parse it into a number of words, and build
328  *	a wordc wordv combination pointing into it.
329  */
330 wordvbuild(string, r_wordc, r_wordv)
331 	char	*string;
332 	int	*r_wordc;
333 	char	***r_wordv;
334 {
335 	reg	char 	*cp;
336 		char	**wordv;
337 		int	wordcount;
338 		int	wordindex;
339 
340 	for (wordcount = 0, cp = string; *cp; wordcount++){
341 		while (*cp  && isspace(*cp))
342 			cp++;
343 		if (*cp == 0)
344 			break;
345 		while (!isspace(*cp))
346 			cp++;
347 	}
348 	wordv = (char **)Calloc(wordcount + 1, sizeof (char *));
349 	for (cp=string,wordindex=0; wordcount; wordindex++,--wordcount){
350 		while (*cp && isspace(*cp))
351 			cp++;
352 		if (*cp == 0)
353 			break;
354 		wordv[wordindex] = cp;
355 		while(!isspace(*cp))
356 			cp++;
357 		*cp++ = '\0';
358 	}
359 	if (wordcount != 0)
360 		error("Initial miscount of the number of words in a line\n");
361 	wordv[wordindex] = (char *)0;
362 #ifdef FULLDEBUG
363 	for (wordcount = 0; wordcount < wordindex; wordcount++)
364 		printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]);
365 	printf("\n");
366 #endif
367 	*r_wordc = wordindex;
368 	*r_wordv = wordv;
369 }
370 /*
371  *	Compare two 0 based wordvectors
372  */
373 int wordvcmp(wordv1, wordc, wordv2)
374 	char	**wordv1;
375 	int	wordc;
376 	char	**wordv2;
377 {
378 	reg	int i;
379 		int	back;
380 	for (i = 0; i < wordc; i++){
381 		if (wordv1[i] == 0 || wordv2[i] == 0)
382 				return(-1);
383 		if (back = strcmp(wordv1[i], wordv2[i])){
384 			return(back);
385 		}
386 	}
387 	return(0);	/* they are equal */
388 }
389 
390 /*
391  *	splice a 0 basedword vector onto the tail of a
392  *	new wordv, allowing the first emptyhead slots to be empty
393  */
394 char	**wordvsplice(emptyhead, wordc, wordv)
395 	int	emptyhead;
396 	int	wordc;
397 	char	**wordv;
398 {
399 	reg	char	**nwordv;
400 		int	nwordc = emptyhead + wordc;
401 	reg	int	i;
402 
403 	nwordv = (char **)Calloc(nwordc, sizeof (char *));
404 	for (i = 0; i < emptyhead; i++)
405 		nwordv[i] = 0;
406 	for(i = emptyhead; i < nwordc; i++){
407 		nwordv[i] = wordv[i-emptyhead];
408 	}
409 	return(nwordv);
410 }
411 /*
412  *	plural'ize and verb forms
413  */
414 static	char	*S = "s";
415 static	char	*N = "";
416 char *plural(n)
417 	int	n;
418 {
419 	return( n > 1 ? S : N);
420 }
421 char *verbform(n)
422 	int	n;
423 {
424 	return( n > 1 ? N : S);
425 }
426 
427