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