xref: /onnv-gate/usr/src/cmd/sgs/error/common/errorsubr.c (revision 7940:e871be8c1471)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55846Sab196087  * Common Development and Distribution License (the "License").
65846Sab196087  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21291Smike_s 
22291Smike_s /*
235846Sab196087  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24291Smike_s  * Use is subject to license terms.
25291Smike_s  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <ctype.h>
29291Smike_s #include <stdlib.h>
30291Smike_s #include <unistd.h>
31291Smike_s #include <stdarg.h>
32291Smike_s #include <string.h>
330Sstevel@tonic-gate #include "error.h"
34291Smike_s 
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate  *	Arrayify a list of rules
370Sstevel@tonic-gate  */
38291Smike_s void
arrayify(int * e_length,Eptr ** e_array,Eptr header)39291Smike_s arrayify(int *e_length, Eptr **e_array, Eptr header)
400Sstevel@tonic-gate {
41291Smike_s 	Eptr	errorp;
42291Smike_s 	Eptr	*array;
43291Smike_s 	int	listlength;
44291Smike_s 	int	listindex;
450Sstevel@tonic-gate 
460Sstevel@tonic-gate 	for (errorp = header, listlength = 0;
47291Smike_s 	    errorp; errorp = errorp->error_next, listlength++)
480Sstevel@tonic-gate 		continue;
49291Smike_s 	array = Calloc(listlength+1, sizeof (Eptr));
50291Smike_s 	for (listindex = 0, errorp = header;
510Sstevel@tonic-gate 	    listindex < listlength;
52291Smike_s 	    listindex++, errorp = errorp->error_next) {
530Sstevel@tonic-gate 		array[listindex] = errorp;
540Sstevel@tonic-gate 		errorp->error_position = listindex;
550Sstevel@tonic-gate 	}
560Sstevel@tonic-gate 	array[listindex] = (Eptr)0;
570Sstevel@tonic-gate 	*e_length = listlength;
580Sstevel@tonic-gate 	*e_array = array;
590Sstevel@tonic-gate }
600Sstevel@tonic-gate 
61291Smike_s /*PRINTFLIKE1*/
62291Smike_s static void
error(char * format,...)63291Smike_s error(char *format, ...)
640Sstevel@tonic-gate {
65291Smike_s 	va_list	args;
66291Smike_s 
67291Smike_s 	va_start(args, format);
68291Smike_s 	(void) fprintf(stderr, "Error: ");
69291Smike_s 	(void) vfprintf(stderr, format, args);
70291Smike_s 	(void) fprintf(stderr, "\n");
71291Smike_s 	(void) fflush(stdout);
72291Smike_s 	(void) fflush(stderr);
73291Smike_s 	va_end(args);
740Sstevel@tonic-gate 	exit(6);
750Sstevel@tonic-gate }
76291Smike_s 
77291Smike_s void *
Calloc(int nelements,int size)78291Smike_s Calloc(int nelements, int size)
790Sstevel@tonic-gate {
80291Smike_s 	void	*back;
81291Smike_s 	if ((back = calloc(nelements, size)) == NULL) {
820Sstevel@tonic-gate 		error("Ran out of memory.\n");
830Sstevel@tonic-gate 		exit(1);
840Sstevel@tonic-gate 	}
85291Smike_s 	return (back);
860Sstevel@tonic-gate }
870Sstevel@tonic-gate 
88291Smike_s char *
strsave(char * instring)89291Smike_s strsave(char *instring)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate 	char	*outstring;
92291Smike_s 	(void) strcpy(outstring = Calloc(1, strlen(instring) + 1),
935846Sab196087 	    instring);
94291Smike_s 	return (outstring);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate  *	find the position of a given character in a string
980Sstevel@tonic-gate  *		(one based)
990Sstevel@tonic-gate  */
100291Smike_s int
position(char * string,char ch)101291Smike_s position(char *string, char ch)
1020Sstevel@tonic-gate {
103291Smike_s 	int	i;
1040Sstevel@tonic-gate 	if (string)
105291Smike_s 	for (i = 1; *string; string++, i++) {
1060Sstevel@tonic-gate 		if (*string == ch)
107291Smike_s 			return (i);
1080Sstevel@tonic-gate 	}
109291Smike_s 	return (-1);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate  *	clobber the first occurance of ch in string by the new character
1130Sstevel@tonic-gate  */
114291Smike_s char *
substitute(char * string,char chold,char chnew)115291Smike_s substitute(char *string, char chold, char chnew)
1160Sstevel@tonic-gate {
117291Smike_s 	char	*cp = string;
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	if (cp)
120291Smike_s 	while (*cp) {
121291Smike_s 		if (*cp == chold) {
1220Sstevel@tonic-gate 			*cp = chnew;
1230Sstevel@tonic-gate 			break;
1240Sstevel@tonic-gate 		}
1250Sstevel@tonic-gate 		cp++;
1260Sstevel@tonic-gate 	}
127291Smike_s 	return (string);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate 
130291Smike_s char
lastchar(char * string)131291Smike_s lastchar(char *string)
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate 	int	length;
134291Smike_s 
135291Smike_s 	if (string == NULL)
136291Smike_s 		return ('\0');
1370Sstevel@tonic-gate 	length = strlen(string);
1380Sstevel@tonic-gate 	if (length >= 1)
139291Smike_s 		return (string[length-1]);
1400Sstevel@tonic-gate 	else
141291Smike_s 		return ('\0');
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate 
144291Smike_s char
firstchar(char * string)145291Smike_s firstchar(char *string)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 	if (string)
148291Smike_s 		return (string[0]);
1490Sstevel@tonic-gate 	else
150291Smike_s 		return ('\0');
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate 
153291Smike_s char
next_lastchar(char * string)154291Smike_s next_lastchar(char *string)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate 	int	length;
157291Smike_s 
158291Smike_s 	if (string == NULL)
159291Smike_s 		return ('\0');
1600Sstevel@tonic-gate 	length = strlen(string);
1610Sstevel@tonic-gate 	if (length >= 2)
162291Smike_s 		return (string[length - 2]);
1630Sstevel@tonic-gate 	else
164291Smike_s 		return ('\0');
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate 
167291Smike_s void
clob_last(char * string,char newstuff)168291Smike_s clob_last(char *string, char newstuff)
1690Sstevel@tonic-gate {
1700Sstevel@tonic-gate 	int	length = 0;
1710Sstevel@tonic-gate 	if (string)
1720Sstevel@tonic-gate 		length = strlen(string);
1730Sstevel@tonic-gate 	if (length >= 1)
1740Sstevel@tonic-gate 		string[length - 1] = newstuff;
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate /*
1780Sstevel@tonic-gate  *	parse a string that is the result of a format %s(%d)
1790Sstevel@tonic-gate  *	return TRUE if this is of the proper format
1800Sstevel@tonic-gate  */
181291Smike_s boolean
persperdexplode(char * string,char ** r_perd,char ** r_pers)182291Smike_s persperdexplode(char *string, char **r_perd, char **r_pers)
1830Sstevel@tonic-gate {
184291Smike_s 	char	*cp;
185291Smike_s 	int	length = 0;
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 	if (string)
1880Sstevel@tonic-gate 		length = strlen(string);
189291Smike_s 	if ((length >= 4) && (string[length - 1] == ')')) {
1900Sstevel@tonic-gate 		for (cp = &string[length - 2];
191291Smike_s 		    (isdigit(*cp)) && (*cp != '('); --cp)
1920Sstevel@tonic-gate 			continue;
193291Smike_s 		if (*cp == '(') {
1940Sstevel@tonic-gate 			string[length - 1] = '\0';	/* clobber the ) */
1950Sstevel@tonic-gate 			*r_perd = strsave(cp+1);
1960Sstevel@tonic-gate 			string[length - 1] = ')';
1970Sstevel@tonic-gate 			*cp = '\0';			/* clobber the ( */
1980Sstevel@tonic-gate 			*r_pers = strsave(string);
1990Sstevel@tonic-gate 			*cp = '(';
200291Smike_s 			return (TRUE);
201291Smike_s 		}
2020Sstevel@tonic-gate 	}
203291Smike_s 	return (FALSE);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate static	char	cincomment[] = CINCOMMENT;
2070Sstevel@tonic-gate static	char	coutcomment[] = COUTCOMMENT;
2080Sstevel@tonic-gate static	char	fincomment[] = FINCOMMENT;
2090Sstevel@tonic-gate static	char	foutcomment[] = FOUTCOMMENT;
2100Sstevel@tonic-gate static	char	newline[] = NEWLINE;
2110Sstevel@tonic-gate static	char	piincomment[] = PIINCOMMENT;
2120Sstevel@tonic-gate static	char	pioutcomment[] = PIOUTCOMMENT;
2130Sstevel@tonic-gate static	char	lispincomment[] = LISPINCOMMENT;
2140Sstevel@tonic-gate static	char	riincomment[] = RIINCOMMENT;
2150Sstevel@tonic-gate static	char	rioutcomment[] = RIOUTCOMMENT;
2160Sstevel@tonic-gate static	char	troffincomment[] = TROFFINCOMMENT;
2170Sstevel@tonic-gate static	char	troffoutcomment[] = TROFFOUTCOMMENT;
2180Sstevel@tonic-gate static	char	mod2incomment[] = MOD2INCOMMENT;
2190Sstevel@tonic-gate static	char	mod2outcomment[] = MOD2OUTCOMMENT;
2200Sstevel@tonic-gate 
221291Smike_s struct lang_desc lang_table[] = {
222291Smike_s 	/* INUNKNOWN	0 */	"unknown", cincomment,	coutcomment,
223291Smike_s 	/* INCPP	1 */	"cpp",	cincomment,    coutcomment,
224291Smike_s 	/* INCC		2 */	"cc",	cincomment,    coutcomment,
225291Smike_s 	/* INAS		3 */	"as",	ASINCOMMENT,   newline,
226291Smike_s 	/* INLD		4 */	"ld",	cincomment,    coutcomment,
227291Smike_s 	/* INLINT	5 */	"lint",	cincomment,    coutcomment,
228291Smike_s 	/* INF77	6 */	"f77",	fincomment,    foutcomment,
229291Smike_s 	/* INPI		7 */	"pi",	piincomment,   pioutcomment,
230291Smike_s 	/* INPC		8 */	"pc",	piincomment,   pioutcomment,
231291Smike_s 	/* INFRANZ	9 */	"franz", lispincomment, newline,
232291Smike_s 	/* INLISP	10 */	"lisp",	lispincomment, newline,
233291Smike_s 	/* INVAXIMA	11 */	"vaxima", lispincomment, newline,
234291Smike_s 	/* INRATFOR	12 */	"ratfor", fincomment,   foutcomment,
235291Smike_s 	/* INLEX	13 */	"lex",	cincomment,    coutcomment,
236291Smike_s 	/* INYACC	14 */	"yacc",	cincomment,    coutcomment,
237291Smike_s 	/* INAPL	15 */	"apl",	".lm", newline,
238291Smike_s 	/* INMAKE	16 */	"make",	ASINCOMMENT,   newline,
239291Smike_s 	/* INRI		17 */	"ri",	riincomment,   rioutcomment,
240291Smike_s 	/* INTROFF	18 */	"troff", troffincomment, troffoutcomment,
241291Smike_s 	/* INMOD2	19 */	"mod2",	mod2incomment, mod2outcomment,
242291Smike_s 	/* INSUNF77	20 */	"Sunf77", fincomment,   foutcomment,
243291Smike_s 	0,	0,	0
2440Sstevel@tonic-gate };
2450Sstevel@tonic-gate 
246291Smike_s void
printerrors(boolean look_at_subclass,int errorc,Eptr errorv[])247291Smike_s printerrors(boolean look_at_subclass, int errorc, Eptr errorv[])
2480Sstevel@tonic-gate {
249291Smike_s 	int	i;
250291Smike_s 	Eptr	errorp;
2510Sstevel@tonic-gate 
252291Smike_s 	for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) {
2530Sstevel@tonic-gate 		if (errorp->error_e_class == C_IGNORE)
2540Sstevel@tonic-gate 			continue;
2550Sstevel@tonic-gate 		if (look_at_subclass && errorp->error_s_class == C_DUPL)
2560Sstevel@tonic-gate 			continue;
257291Smike_s 		(void) printf("Error %d, (%s error) [%s], text = \"",
2585846Sab196087 		    i,
2595846Sab196087 		    class_table[errorp->error_e_class],
2605846Sab196087 		    lang_table[errorp->error_language].lang_name);
261291Smike_s 		wordvprint(stdout, errorp->error_lgtext, errorp->error_text);
262291Smike_s 		(void) printf("\"\n");
2630Sstevel@tonic-gate 	}
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate 
266291Smike_s void
wordvprint(FILE * fyle,int wordc,char * wordv[])267291Smike_s wordvprint(FILE *fyle, int wordc, char *wordv[])
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate 	int	i;
2700Sstevel@tonic-gate 	char *sep = "";
2710Sstevel@tonic-gate 
272291Smike_s 	for (i = 0; i < wordc; i++)
2730Sstevel@tonic-gate 		if (wordv[i]) {
274291Smike_s 			(void) fprintf(fyle, "%s%s", sep, wordv[i]);
2750Sstevel@tonic-gate 			sep = " ";
2760Sstevel@tonic-gate 		}
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate /*
2800Sstevel@tonic-gate  *	Given a string, parse it into a number of words, and build
2810Sstevel@tonic-gate  *	a wordc wordv combination pointing into it.
2820Sstevel@tonic-gate  */
283291Smike_s void
wordvbuild(char * string,int * r_wordc,char *** r_wordv)284291Smike_s wordvbuild(char *string, int *r_wordc, char ***r_wordv)
2850Sstevel@tonic-gate {
286291Smike_s 	char 	*cp;
2875846Sab196087 	char	*saltedbuffer;
2885846Sab196087 	char	**wordv;
2895846Sab196087 	int	wordcount;
2905846Sab196087 	int	wordindex;
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 	saltedbuffer = strsave(string);
293291Smike_s 	for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++) {
294291Smike_s 		while (*cp && isspace(*cp))
2950Sstevel@tonic-gate 			cp++;
296*7940SMatthew.Jacob@Sun.COM 		if (*cp == 0)
297*7940SMatthew.Jacob@Sun.COM 			break;
2985846Sab196087 		while (*cp && !isspace(*cp))
2990Sstevel@tonic-gate 			cp++;
3000Sstevel@tonic-gate 	}
301291Smike_s 	wordv = Calloc(wordcount + 1, sizeof (char *));
302291Smike_s 	for (cp = saltedbuffer, wordindex = 0; wordcount;
303291Smike_s 	    wordindex++, --wordcount) {
3040Sstevel@tonic-gate 		while (*cp && isspace(*cp))
3050Sstevel@tonic-gate 			cp++;
3060Sstevel@tonic-gate 		if (*cp == 0)
3070Sstevel@tonic-gate 			break;
3080Sstevel@tonic-gate 		wordv[wordindex] = cp;
3095846Sab196087 		while (*cp && !isspace(*cp))
3100Sstevel@tonic-gate 			cp++;
3110Sstevel@tonic-gate 		*cp++ = '\0';
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 	if (wordcount != 0)
3140Sstevel@tonic-gate 		error("Initial miscount of the number of words in a line\n");
315291Smike_s 	wordv[wordindex] = NULL;
3160Sstevel@tonic-gate #ifdef FULLDEBUG
3170Sstevel@tonic-gate 	for (wordcount = 0; wordcount < wordindex; wordcount++)
318291Smike_s 		(void) printf("Word %d = \"%s\"\n", wordcount,
319291Smike_s 		    wordv[wordcount]);
320291Smike_s 	(void) printf("\n");
3210Sstevel@tonic-gate #endif
3220Sstevel@tonic-gate 	*r_wordc = wordindex;
3230Sstevel@tonic-gate 	*r_wordv = wordv;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate /*
3260Sstevel@tonic-gate  *	Compare two 0 based wordvectors
3270Sstevel@tonic-gate  */
328291Smike_s int
wordvcmp(char ** wordv1,int wordc,char ** wordv2)329291Smike_s wordvcmp(char **wordv1, int wordc, char **wordv2)
3300Sstevel@tonic-gate {
331291Smike_s 	int i;
332291Smike_s 	int	back;
333291Smike_s 
334291Smike_s 	for (i = 0; i < wordc; i++) {
3350Sstevel@tonic-gate 		if (wordv1[i] == 0 || wordv2[i] == 0)
336291Smike_s 				return (-1);
337291Smike_s 		if (back = strcmp(wordv1[i], wordv2[i])) {
338291Smike_s 			return (back);
3390Sstevel@tonic-gate 		}
3400Sstevel@tonic-gate 	}
341291Smike_s 	return (0);	/* they are equal */
3420Sstevel@tonic-gate }
343291Smike_s 
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate  *	splice a 0 basedword vector onto the tail of a
3460Sstevel@tonic-gate  *	new wordv, allowing the first emptyhead slots to be empty
3470Sstevel@tonic-gate  */
348291Smike_s char **
wordvsplice(int emptyhead,int wordc,char ** wordv)349291Smike_s wordvsplice(int emptyhead, int wordc, char **wordv)
3500Sstevel@tonic-gate {
351291Smike_s 	char	**nwordv;
352291Smike_s 	int	nwordc = emptyhead + wordc;
353291Smike_s 	int	i;
3540Sstevel@tonic-gate 
355291Smike_s 	nwordv = Calloc(nwordc, sizeof (char *));
3560Sstevel@tonic-gate 	for (i = 0; i < emptyhead; i++)
3570Sstevel@tonic-gate 		nwordv[i] = 0;
358291Smike_s 	for (i = emptyhead; i < nwordc; i++) {
3590Sstevel@tonic-gate 		nwordv[i] = wordv[i-emptyhead];
3600Sstevel@tonic-gate 	}
361291Smike_s 	return (nwordv);
3620Sstevel@tonic-gate }
363291Smike_s 
3640Sstevel@tonic-gate /*
3650Sstevel@tonic-gate  *	plural'ize and verb forms
3660Sstevel@tonic-gate  */
3670Sstevel@tonic-gate static	char	*S = "s";
3680Sstevel@tonic-gate static	char	*N = "";
369291Smike_s 
370291Smike_s char *
plural(int n)371291Smike_s plural(int n)
3720Sstevel@tonic-gate {
373291Smike_s 	return (n > 1 ? S : N);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate 
376291Smike_s char *
verbform(int n)377291Smike_s verbform(int n)
378291Smike_s {
379291Smike_s 	return (n > 1 ? N : S);
380291Smike_s }
381