errorsubr.c revision 7940:e871be8c1471
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 */
38void
39arrayify(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*/
62static void
63error(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
77void *
78Calloc(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
88char *
89strsave(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 */
100int
101position(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 */
114char *
115substitute(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
130char
131lastchar(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
144char
145firstchar(char *string)
146{
147	if (string)
148		return (string[0]);
149	else
150		return ('\0');
151}
152
153char
154next_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
167void
168clob_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 */
181boolean
182persperdexplode(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
206static	char	cincomment[] = CINCOMMENT;
207static	char	coutcomment[] = COUTCOMMENT;
208static	char	fincomment[] = FINCOMMENT;
209static	char	foutcomment[] = FOUTCOMMENT;
210static	char	newline[] = NEWLINE;
211static	char	piincomment[] = PIINCOMMENT;
212static	char	pioutcomment[] = PIOUTCOMMENT;
213static	char	lispincomment[] = LISPINCOMMENT;
214static	char	riincomment[] = RIINCOMMENT;
215static	char	rioutcomment[] = RIOUTCOMMENT;
216static	char	troffincomment[] = TROFFINCOMMENT;
217static	char	troffoutcomment[] = TROFFOUTCOMMENT;
218static	char	mod2incomment[] = MOD2INCOMMENT;
219static	char	mod2outcomment[] = MOD2OUTCOMMENT;
220
221struct 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
246void
247printerrors(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
266void
267wordvprint(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 */
283void
284wordvbuild(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 */
328int
329wordvcmp(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 */
348char **
349wordvsplice(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 */
367static	char	*S = "s";
368static	char	*N = "";
369
370char *
371plural(int n)
372{
373	return (n > 1 ? S : N);
374}
375
376char *
377verbform(int n)
378{
379	return (n > 1 ? N : S);
380}
381