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 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 *
substitute(char * string,char chold,char chnew)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
lastchar(char * string)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
firstchar(char * string)145 firstchar(char *string)
146 {
147 if (string)
148 return (string[0]);
149 else
150 return ('\0');
151 }
152
153 char
next_lastchar(char * string)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
clob_last(char * string,char newstuff)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
persperdexplode(char * string,char ** r_perd,char ** r_pers)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
printerrors(boolean look_at_subclass,int errorc,Eptr errorv[])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
wordvprint(FILE * fyle,int wordc,char * wordv[])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
wordvbuild(char * string,int * r_wordc,char *** r_wordv)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
wordvcmp(char ** wordv1,int wordc,char ** wordv2)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 **
wordvsplice(int emptyhead,int wordc,char ** wordv)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 *
plural(int n)371 plural(int n)
372 {
373 return (n > 1 ? S : N);
374 }
375
376 char *
verbform(int n)377 verbform(int n)
378 {
379 return (n > 1 ? N : S);
380 }
381