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