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
arrayify(int * e_length,Eptr ** e_array,Eptr header)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
error(char * format,...)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 *
Calloc(int nelements,int size)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 *
strsave(char * instring)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
position(char * string,char ch)101 position(char *string, char ch)
102 {
103 	int	i;
104 
105 	if (string) {
106 		for (i = 1; *string; string++, i++) {
107 			if (*string == ch)
108 				return (i);
109 		}
110 	}
111 	return (-1);
112 }
113 /*
114  *	clobber the first occurance of ch in string by the new character
115  */
116 char *
substitute(char * string,char chold,char chnew)117 substitute(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 	}
130 	return (string);
131 }
132 
133 char
lastchar(char * string)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
firstchar(char * string)148 firstchar(char *string)
149 {
150 	if (string)
151 		return (string[0]);
152 	else
153 		return ('\0');
154 }
155 
156 char
next_lastchar(char * string)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
clob_last(char * string,char newstuff)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
persperdexplode(char * string,char ** r_perd,char ** r_pers)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
printerrors(boolean look_at_subclass,int errorc,Eptr errorv[])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
wordvprint(FILE * fyle,int wordc,char * wordv[])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
wordvbuild(char * string,int * r_wordc,char *** r_wordv)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 (*cp && !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 (*cp && !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
wordvcmp(char ** wordv1,int wordc,char ** wordv2)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 **
wordvsplice(int emptyhead,int wordc,char ** wordv)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 *
plural(int n)374 plural(int n)
375 {
376 	return (n > 1 ? S : N);
377 }
378 
379 char *
verbform(int n)380 verbform(int n)
381 {
382 	return (n > 1 ? N : S);
383 }
384