errorsubr.c revision 5846:466857e6771b
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#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <stdio.h>
30#include <ctype.h>
31#include <stdlib.h>
32#include <unistd.h>
33#include <stdarg.h>
34#include <string.h>
35#include "error.h"
36
37/*
38 *	Arrayify a list of rules
39 */
40void
41arrayify(int *e_length, Eptr **e_array, Eptr header)
42{
43	Eptr	errorp;
44	Eptr	*array;
45	int	listlength;
46	int	listindex;
47
48	for (errorp = header, listlength = 0;
49	    errorp; errorp = errorp->error_next, listlength++)
50		continue;
51	array = Calloc(listlength+1, sizeof (Eptr));
52	for (listindex = 0, errorp = header;
53	    listindex < listlength;
54	    listindex++, errorp = errorp->error_next) {
55		array[listindex] = errorp;
56		errorp->error_position = listindex;
57	}
58	array[listindex] = (Eptr)0;
59	*e_length = listlength;
60	*e_array = array;
61}
62
63/*PRINTFLIKE1*/
64static void
65error(char *format, ...)
66{
67	va_list	args;
68
69	va_start(args, format);
70	(void) fprintf(stderr, "Error: ");
71	(void) vfprintf(stderr, format, args);
72	(void) fprintf(stderr, "\n");
73	(void) fflush(stdout);
74	(void) fflush(stderr);
75	va_end(args);
76	exit(6);
77}
78
79void *
80Calloc(int nelements, int size)
81{
82	void	*back;
83	if ((back = calloc(nelements, size)) == NULL) {
84		error("Ran out of memory.\n");
85		exit(1);
86	}
87	return (back);
88}
89
90char *
91strsave(char *instring)
92{
93	char	*outstring;
94	(void) strcpy(outstring = Calloc(1, strlen(instring) + 1),
95	    instring);
96	return (outstring);
97}
98/*
99 *	find the position of a given character in a string
100 *		(one based)
101 */
102int
103position(char *string, char ch)
104{
105	int	i;
106	if (string)
107	for (i = 1; *string; string++, i++) {
108		if (*string == ch)
109			return (i);
110	}
111	return (-1);
112}
113/*
114 *	clobber the first occurance of ch in string by the new character
115 */
116char *
117substitute(char *string, char chold, char chnew)
118{
119	char	*cp = string;
120
121	if (cp)
122	while (*cp) {
123		if (*cp == chold) {
124			*cp = chnew;
125			break;
126		}
127		cp++;
128	}
129	return (string);
130}
131
132char
133lastchar(char *string)
134{
135	int	length;
136
137	if (string == NULL)
138		return ('\0');
139	length = strlen(string);
140	if (length >= 1)
141		return (string[length-1]);
142	else
143		return ('\0');
144}
145
146char
147firstchar(char *string)
148{
149	if (string)
150		return (string[0]);
151	else
152		return ('\0');
153}
154
155char
156next_lastchar(char *string)
157{
158	int	length;
159
160	if (string == NULL)
161		return ('\0');
162	length = strlen(string);
163	if (length >= 2)
164		return (string[length - 2]);
165	else
166		return ('\0');
167}
168
169void
170clob_last(char *string, char newstuff)
171{
172	int	length = 0;
173	if (string)
174		length = strlen(string);
175	if (length >= 1)
176		string[length - 1] = newstuff;
177}
178
179/*
180 *	parse a string that is the result of a format %s(%d)
181 *	return TRUE if this is of the proper format
182 */
183boolean
184persperdexplode(char *string, char **r_perd, char **r_pers)
185{
186	char	*cp;
187	int	length = 0;
188
189	if (string)
190		length = strlen(string);
191	if ((length >= 4) && (string[length - 1] == ')')) {
192		for (cp = &string[length - 2];
193		    (isdigit(*cp)) && (*cp != '('); --cp)
194			continue;
195		if (*cp == '(') {
196			string[length - 1] = '\0';	/* clobber the ) */
197			*r_perd = strsave(cp+1);
198			string[length - 1] = ')';
199			*cp = '\0';			/* clobber the ( */
200			*r_pers = strsave(string);
201			*cp = '(';
202			return (TRUE);
203		}
204	}
205	return (FALSE);
206}
207
208static	char	cincomment[] = CINCOMMENT;
209static	char	coutcomment[] = COUTCOMMENT;
210static	char	fincomment[] = FINCOMMENT;
211static	char	foutcomment[] = FOUTCOMMENT;
212static	char	newline[] = NEWLINE;
213static	char	piincomment[] = PIINCOMMENT;
214static	char	pioutcomment[] = PIOUTCOMMENT;
215static	char	lispincomment[] = LISPINCOMMENT;
216static	char	riincomment[] = RIINCOMMENT;
217static	char	rioutcomment[] = RIOUTCOMMENT;
218static	char	troffincomment[] = TROFFINCOMMENT;
219static	char	troffoutcomment[] = TROFFOUTCOMMENT;
220static	char	mod2incomment[] = MOD2INCOMMENT;
221static	char	mod2outcomment[] = MOD2OUTCOMMENT;
222
223struct lang_desc lang_table[] = {
224	/* INUNKNOWN	0 */	"unknown", cincomment,	coutcomment,
225	/* INCPP	1 */	"cpp",	cincomment,    coutcomment,
226	/* INCC		2 */	"cc",	cincomment,    coutcomment,
227	/* INAS		3 */	"as",	ASINCOMMENT,   newline,
228	/* INLD		4 */	"ld",	cincomment,    coutcomment,
229	/* INLINT	5 */	"lint",	cincomment,    coutcomment,
230	/* INF77	6 */	"f77",	fincomment,    foutcomment,
231	/* INPI		7 */	"pi",	piincomment,   pioutcomment,
232	/* INPC		8 */	"pc",	piincomment,   pioutcomment,
233	/* INFRANZ	9 */	"franz", lispincomment, newline,
234	/* INLISP	10 */	"lisp",	lispincomment, newline,
235	/* INVAXIMA	11 */	"vaxima", lispincomment, newline,
236	/* INRATFOR	12 */	"ratfor", fincomment,   foutcomment,
237	/* INLEX	13 */	"lex",	cincomment,    coutcomment,
238	/* INYACC	14 */	"yacc",	cincomment,    coutcomment,
239	/* INAPL	15 */	"apl",	".lm", newline,
240	/* INMAKE	16 */	"make",	ASINCOMMENT,   newline,
241	/* INRI		17 */	"ri",	riincomment,   rioutcomment,
242	/* INTROFF	18 */	"troff", troffincomment, troffoutcomment,
243	/* INMOD2	19 */	"mod2",	mod2incomment, mod2outcomment,
244	/* INSUNF77	20 */	"Sunf77", fincomment,   foutcomment,
245	0,	0,	0
246};
247
248void
249printerrors(boolean look_at_subclass, int errorc, Eptr errorv[])
250{
251	int	i;
252	Eptr	errorp;
253
254	for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) {
255		if (errorp->error_e_class == C_IGNORE)
256			continue;
257		if (look_at_subclass && errorp->error_s_class == C_DUPL)
258			continue;
259		(void) printf("Error %d, (%s error) [%s], text = \"",
260		    i,
261		    class_table[errorp->error_e_class],
262		    lang_table[errorp->error_language].lang_name);
263		wordvprint(stdout, errorp->error_lgtext, errorp->error_text);
264		(void) printf("\"\n");
265	}
266}
267
268void
269wordvprint(FILE *fyle, int wordc, char *wordv[])
270{
271	int	i;
272	char *sep = "";
273
274	for (i = 0; i < wordc; i++)
275		if (wordv[i]) {
276			(void) fprintf(fyle, "%s%s", sep, wordv[i]);
277			sep = " ";
278		}
279}
280
281/*
282 *	Given a string, parse it into a number of words, and build
283 *	a wordc wordv combination pointing into it.
284 */
285void
286wordvbuild(char *string, int *r_wordc, char ***r_wordv)
287{
288	char 	*cp;
289	char	*saltedbuffer;
290	char	**wordv;
291	int	wordcount;
292	int	wordindex;
293
294	saltedbuffer = strsave(string);
295	for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++) {
296		while (*cp && isspace(*cp))
297			cp++;
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