xref: /illumos-gate/usr/src/cmd/sgs/error/common/errorsubr.c (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <stdarg.h>
35 #include <string.h>
36 #include "error.h"
37 
38 /*
39  *	Arrayify a list of rules
40  */
41 void
42 arrayify(int *e_length, Eptr **e_array, Eptr header)
43 {
44 	Eptr	errorp;
45 	Eptr	*array;
46 	int	listlength;
47 	int	listindex;
48 
49 	for (errorp = header, listlength = 0;
50 	    errorp; errorp = errorp->error_next, listlength++)
51 		continue;
52 	array = Calloc(listlength+1, sizeof (Eptr));
53 	for (listindex = 0, errorp = header;
54 	    listindex < listlength;
55 	    listindex++, errorp = errorp->error_next) {
56 		array[listindex] = errorp;
57 		errorp->error_position = listindex;
58 	}
59 	array[listindex] = (Eptr)0;
60 	*e_length = listlength;
61 	*e_array = array;
62 }
63 
64 /*PRINTFLIKE1*/
65 static void
66 error(char *format, ...)
67 {
68 	va_list	args;
69 
70 	va_start(args, format);
71 	(void) fprintf(stderr, "Error: ");
72 	(void) vfprintf(stderr, format, args);
73 	(void) fprintf(stderr, "\n");
74 	(void) fflush(stdout);
75 	(void) fflush(stderr);
76 	va_end(args);
77 	exit(6);
78 }
79 
80 void *
81 Calloc(int nelements, int size)
82 {
83 	void	*back;
84 	if ((back = calloc(nelements, size)) == NULL) {
85 		error("Ran out of memory.\n");
86 		exit(1);
87 	}
88 	return (back);
89 }
90 
91 char *
92 strsave(char *instring)
93 {
94 	char	*outstring;
95 	(void) strcpy(outstring = Calloc(1, strlen(instring) + 1),
96 		instring);
97 	return (outstring);
98 }
99 /*
100  *	find the position of a given character in a string
101  *		(one based)
102  */
103 int
104 position(char *string, char ch)
105 {
106 	int	i;
107 	if (string)
108 	for (i = 1; *string; string++, i++) {
109 		if (*string == ch)
110 			return (i);
111 	}
112 	return (-1);
113 }
114 /*
115  *	clobber the first occurance of ch in string by the new character
116  */
117 char *
118 substitute(char *string, char chold, char chnew)
119 {
120 	char	*cp = string;
121 
122 	if (cp)
123 	while (*cp) {
124 		if (*cp == chold) {
125 			*cp = chnew;
126 			break;
127 		}
128 		cp++;
129 	}
130 	return (string);
131 }
132 
133 char
134 lastchar(char *string)
135 {
136 	int	length;
137 
138 	if (string == NULL)
139 		return ('\0');
140 	length = strlen(string);
141 	if (length >= 1)
142 		return (string[length-1]);
143 	else
144 		return ('\0');
145 }
146 
147 char
148 firstchar(char *string)
149 {
150 	if (string)
151 		return (string[0]);
152 	else
153 		return ('\0');
154 }
155 
156 char
157 next_lastchar(char *string)
158 {
159 	int	length;
160 
161 	if (string == NULL)
162 		return ('\0');
163 	length = strlen(string);
164 	if (length >= 2)
165 		return (string[length - 2]);
166 	else
167 		return ('\0');
168 }
169 
170 void
171 clob_last(char *string, char newstuff)
172 {
173 	int	length = 0;
174 	if (string)
175 		length = strlen(string);
176 	if (length >= 1)
177 		string[length - 1] = newstuff;
178 }
179 
180 /*
181  *	parse a string that is the result of a format %s(%d)
182  *	return TRUE if this is of the proper format
183  */
184 boolean
185 persperdexplode(char *string, char **r_perd, char **r_pers)
186 {
187 	char	*cp;
188 	int	length = 0;
189 
190 	if (string)
191 		length = strlen(string);
192 	if ((length >= 4) && (string[length - 1] == ')')) {
193 		for (cp = &string[length - 2];
194 		    (isdigit(*cp)) && (*cp != '('); --cp)
195 			continue;
196 		if (*cp == '(') {
197 			string[length - 1] = '\0';	/* clobber the ) */
198 			*r_perd = strsave(cp+1);
199 			string[length - 1] = ')';
200 			*cp = '\0';			/* clobber the ( */
201 			*r_pers = strsave(string);
202 			*cp = '(';
203 			return (TRUE);
204 		}
205 	}
206 	return (FALSE);
207 }
208 
209 static	char	cincomment[] = CINCOMMENT;
210 static	char	coutcomment[] = COUTCOMMENT;
211 static	char	fincomment[] = FINCOMMENT;
212 static	char	foutcomment[] = FOUTCOMMENT;
213 static	char	newline[] = NEWLINE;
214 static	char	piincomment[] = PIINCOMMENT;
215 static	char	pioutcomment[] = PIOUTCOMMENT;
216 static	char	lispincomment[] = LISPINCOMMENT;
217 static	char	riincomment[] = RIINCOMMENT;
218 static	char	rioutcomment[] = RIOUTCOMMENT;
219 static	char	troffincomment[] = TROFFINCOMMENT;
220 static	char	troffoutcomment[] = TROFFOUTCOMMENT;
221 static	char	mod2incomment[] = MOD2INCOMMENT;
222 static	char	mod2outcomment[] = MOD2OUTCOMMENT;
223 
224 struct lang_desc lang_table[] = {
225 	/* INUNKNOWN	0 */	"unknown", cincomment,	coutcomment,
226 	/* INCPP	1 */	"cpp",	cincomment,    coutcomment,
227 	/* INCC		2 */	"cc",	cincomment,    coutcomment,
228 	/* INAS		3 */	"as",	ASINCOMMENT,   newline,
229 	/* INLD		4 */	"ld",	cincomment,    coutcomment,
230 	/* INLINT	5 */	"lint",	cincomment,    coutcomment,
231 	/* INF77	6 */	"f77",	fincomment,    foutcomment,
232 	/* INPI		7 */	"pi",	piincomment,   pioutcomment,
233 	/* INPC		8 */	"pc",	piincomment,   pioutcomment,
234 	/* INFRANZ	9 */	"franz", lispincomment, newline,
235 	/* INLISP	10 */	"lisp",	lispincomment, newline,
236 	/* INVAXIMA	11 */	"vaxima", lispincomment, newline,
237 	/* INRATFOR	12 */	"ratfor", fincomment,   foutcomment,
238 	/* INLEX	13 */	"lex",	cincomment,    coutcomment,
239 	/* INYACC	14 */	"yacc",	cincomment,    coutcomment,
240 	/* INAPL	15 */	"apl",	".lm", newline,
241 	/* INMAKE	16 */	"make",	ASINCOMMENT,   newline,
242 	/* INRI		17 */	"ri",	riincomment,   rioutcomment,
243 	/* INTROFF	18 */	"troff", troffincomment, troffoutcomment,
244 	/* INMOD2	19 */	"mod2",	mod2incomment, mod2outcomment,
245 	/* INSUNF77	20 */	"Sunf77", fincomment,   foutcomment,
246 	0,	0,	0
247 };
248 
249 void
250 printerrors(boolean look_at_subclass, int errorc, Eptr errorv[])
251 {
252 	int	i;
253 	Eptr	errorp;
254 
255 	for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) {
256 		if (errorp->error_e_class == C_IGNORE)
257 			continue;
258 		if (look_at_subclass && errorp->error_s_class == C_DUPL)
259 			continue;
260 		(void) printf("Error %d, (%s error) [%s], text = \"",
261 			i,
262 			class_table[errorp->error_e_class],
263 			lang_table[errorp->error_language].lang_name);
264 		wordvprint(stdout, errorp->error_lgtext, errorp->error_text);
265 		(void) printf("\"\n");
266 	}
267 }
268 
269 void
270 wordvprint(FILE *fyle, int wordc, char *wordv[])
271 {
272 	int	i;
273 	char *sep = "";
274 
275 	for (i = 0; i < wordc; i++)
276 		if (wordv[i]) {
277 			(void) fprintf(fyle, "%s%s", sep, wordv[i]);
278 			sep = " ";
279 		}
280 }
281 
282 /*
283  *	Given a string, parse it into a number of words, and build
284  *	a wordc wordv combination pointing into it.
285  */
286 void
287 wordvbuild(char *string, int *r_wordc, char ***r_wordv)
288 {
289 	char 	*cp;
290 		char	*saltedbuffer;
291 		char	**wordv;
292 		int	wordcount;
293 		int	wordindex;
294 
295 	saltedbuffer = strsave(string);
296 	for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++) {
297 		while (*cp && isspace(*cp))
298 			cp++;
299 		if (*cp == 0)
300 			break;
301 		while (!isspace(*cp))
302 			cp++;
303 	}
304 	wordv = Calloc(wordcount + 1, sizeof (char *));
305 	for (cp = saltedbuffer, wordindex = 0; wordcount;
306 	    wordindex++, --wordcount) {
307 		while (*cp && isspace(*cp))
308 			cp++;
309 		if (*cp == 0)
310 			break;
311 		wordv[wordindex] = cp;
312 		while (!isspace(*cp))
313 			cp++;
314 		*cp++ = '\0';
315 	}
316 	if (wordcount != 0)
317 		error("Initial miscount of the number of words in a line\n");
318 	wordv[wordindex] = NULL;
319 #ifdef FULLDEBUG
320 	for (wordcount = 0; wordcount < wordindex; wordcount++)
321 		(void) printf("Word %d = \"%s\"\n", wordcount,
322 		    wordv[wordcount]);
323 	(void) printf("\n");
324 #endif
325 	*r_wordc = wordindex;
326 	*r_wordv = wordv;
327 }
328 /*
329  *	Compare two 0 based wordvectors
330  */
331 int
332 wordvcmp(char **wordv1, int wordc, char **wordv2)
333 {
334 	int i;
335 	int	back;
336 
337 	for (i = 0; i < wordc; i++) {
338 		if (wordv1[i] == 0 || wordv2[i] == 0)
339 				return (-1);
340 		if (back = strcmp(wordv1[i], wordv2[i])) {
341 			return (back);
342 		}
343 	}
344 	return (0);	/* they are equal */
345 }
346 
347 /*
348  *	splice a 0 basedword vector onto the tail of a
349  *	new wordv, allowing the first emptyhead slots to be empty
350  */
351 char **
352 wordvsplice(int emptyhead, int wordc, char **wordv)
353 {
354 	char	**nwordv;
355 	int	nwordc = emptyhead + wordc;
356 	int	i;
357 
358 	nwordv = Calloc(nwordc, sizeof (char *));
359 	for (i = 0; i < emptyhead; i++)
360 		nwordv[i] = 0;
361 	for (i = emptyhead; i < nwordc; i++) {
362 		nwordv[i] = wordv[i-emptyhead];
363 	}
364 	return (nwordv);
365 }
366 
367 /*
368  *	plural'ize and verb forms
369  */
370 static	char	*S = "s";
371 static	char	*N = "";
372 
373 char *
374 plural(int n)
375 {
376 	return (n > 1 ? S : N);
377 }
378 
379 char *
380 verbform(int n)
381 {
382 	return (n > 1 ? N : S);
383 }
384