subr.c revision 1.4 1 /* $NetBSD: subr.c,v 1.4 1995/09/10 15:55:15 christos Exp $ */
2
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/6/93";
39 #endif
40 static char rcsid[] = "$NetBSD: subr.c,v 1.4 1995/09/10 15:55:15 christos Exp $";
41 #endif /* not lint */
42
43 #include <stdio.h>
44 #include <ctype.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include "error.h"
48 /*
49 * Arrayify a list of rules
50 */
51 arrayify(e_length, e_array, header)
52 int *e_length;
53 Eptr **e_array;
54 Eptr header;
55 {
56 reg Eptr errorp;
57 reg Eptr *array;
58 reg int listlength;
59 reg int listindex;
60
61 for (errorp = header, listlength = 0;
62 errorp; errorp = errorp->error_next, listlength++)
63 continue;
64 array = (Eptr*)Calloc(listlength+1, sizeof (Eptr));
65 for(listindex = 0, errorp = header;
66 listindex < listlength;
67 listindex++, errorp = errorp->error_next){
68 array[listindex] = errorp;
69 errorp->error_position = listindex;
70 }
71 array[listindex] = (Eptr)0;
72 *e_length = listlength;
73 *e_array = array;
74 }
75
76 /*VARARGS1*/
77 error(msg, a1, a2, a3)
78 char *msg;
79 {
80 fprintf(stderr, "Error: ");
81 fprintf(stderr, msg, a1, a2, a3);
82 fprintf(stderr, "\n");
83 fflush(stdout);
84 fflush(stderr);
85 exit(6);
86 }
87 /*ARGSUSED*/
88 char *Calloc(nelements, size)
89 int nelements;
90 int size;
91 {
92 char *back;
93 if ( (back = (char *)calloc(nelements, size)) == (char *)NULL){
94 error("Ran out of memory.\n");
95 exit(1);
96 }
97 return(back);
98 }
99
100 char *strsave(instring)
101 char *instring;
102 {
103 char *outstring;
104 (void)strcpy(outstring = (char *)Calloc(1, strlen(instring) + 1),
105 instring);
106 return(outstring);
107 }
108 /*
109 * find the position of a given character in a string
110 * (one based)
111 */
112 int position(string, ch)
113 reg char *string;
114 reg char ch;
115 {
116 reg int i;
117 if (string)
118 for (i=1; *string; string++, i++){
119 if (*string == ch)
120 return(i);
121 }
122 return(-1);
123 }
124 /*
125 * clobber the first occurance of ch in string by the new character
126 */
127 char *substitute(string, chold, chnew)
128 char *string;
129 char chold, chnew;
130 {
131 reg char *cp = string;
132
133 if (cp)
134 while (*cp){
135 if (*cp == chold){
136 *cp = chnew;
137 break;
138 }
139 cp++;
140 }
141 return(string);
142 }
143
144 char lastchar(string)
145 char *string;
146 {
147 int length;
148 if (string == 0) return('\0');
149 length = strlen(string);
150 if (length >= 1)
151 return(string[length-1]);
152 else
153 return('\0');
154 }
155
156 char firstchar(string)
157 char *string;
158 {
159 if (string)
160 return(string[0]);
161 else
162 return('\0');
163 }
164
165 char next_lastchar(string)
166 char *string;
167 {
168 int length;
169 if (string == 0) return('\0');
170 length = strlen(string);
171 if (length >= 2)
172 return(string[length - 2]);
173 else
174 return('\0');
175 }
176
177 clob_last(string, newstuff)
178 char *string, newstuff;
179 {
180 int length = 0;
181 if (string)
182 length = strlen(string);
183 if (length >= 1)
184 string[length - 1] = newstuff;
185 }
186
187 /*
188 * parse a string that is the result of a format %s(%d)
189 * return TRUE if this is of the proper format
190 */
191 boolean persperdexplode(string, r_perd, r_pers)
192 char *string;
193 char **r_perd, **r_pers;
194 {
195 reg char *cp;
196 int length = 0;
197
198 if (string)
199 length = strlen(string);
200 if ( (length >= 4)
201 && (string[length - 1] == ')' ) ){
202 for (cp = &string[length - 2];
203 (isdigit(*cp)) && (*cp != '(');
204 --cp)
205 continue;
206 if (*cp == '('){
207 string[length - 1] = '\0'; /* clobber the ) */
208 *r_perd = strsave(cp+1);
209 string[length - 1] = ')';
210 *cp = '\0'; /* clobber the ( */
211 *r_pers = strsave(string);
212 *cp = '(';
213 return(TRUE);
214 }
215 }
216 return(FALSE);
217 }
218 /*
219 * parse a quoted string that is the result of a format \"%s\"(%d)
220 * return TRUE if this is of the proper format
221 */
222 boolean qpersperdexplode(string, r_perd, r_pers)
223 char *string;
224 char **r_perd, **r_pers;
225 {
226 reg char *cp;
227 int length = 0;
228
229 if (string)
230 length = strlen(string);
231 if ( (length >= 4)
232 && (string[length - 1] == ')' ) ){
233 for (cp = &string[length - 2];
234 (isdigit(*cp)) && (*cp != '(');
235 --cp)
236 continue;
237 if (*cp == '(' && *(cp - 1) == '"'){
238 string[length - 1] = '\0';
239 *r_perd = strsave(cp+1);
240 string[length - 1] = ')';
241 *(cp - 1) = '\0'; /* clobber the " */
242 *r_pers = strsave(string + 1);
243 *(cp - 1) = '"';
244 return(TRUE);
245 }
246 }
247 return(FALSE);
248 }
249
250 static char cincomment[] = CINCOMMENT;
251 static char coutcomment[] = COUTCOMMENT;
252 static char fincomment[] = FINCOMMENT;
253 static char foutcomment[] = FOUTCOMMENT;
254 static char newline[] = NEWLINE;
255 static char piincomment[] = PIINCOMMENT;
256 static char pioutcomment[] = PIOUTCOMMENT;
257 static char lispincomment[] = LISPINCOMMENT;
258 static char riincomment[] = RIINCOMMENT;
259 static char rioutcomment[] = RIOUTCOMMENT;
260 static char troffincomment[] = TROFFINCOMMENT;
261 static char troffoutcomment[] = TROFFOUTCOMMENT;
262 static char mod2incomment[] = MOD2INCOMMENT;
263 static char mod2outcomment[] = MOD2OUTCOMMENT;
264
265 struct lang_desc lang_table[] = {
266 /*INUNKNOWN 0*/ "unknown", cincomment, coutcomment,
267 /*INCPP 1*/ "cpp", cincomment, coutcomment,
268 /*INCC 2*/ "cc", cincomment, coutcomment,
269 /*INAS 3*/ "as", ASINCOMMENT, newline,
270 /*INLD 4*/ "ld", cincomment, coutcomment,
271 /*INLINT 5*/ "lint", cincomment, coutcomment,
272 /*INF77 6*/ "f77", fincomment, foutcomment,
273 /*INPI 7*/ "pi", piincomment, pioutcomment,
274 /*INPC 8*/ "pc", piincomment, pioutcomment,
275 /*INFRANZ 9*/ "franz",lispincomment, newline,
276 /*INLISP 10*/ "lisp", lispincomment, newline,
277 /*INVAXIMA 11*/ "vaxima",lispincomment,newline,
278 /*INRATFOR 12*/ "ratfor",fincomment, foutcomment,
279 /*INLEX 13*/ "lex", cincomment, coutcomment,
280 /*INYACC 14*/ "yacc", cincomment, coutcomment,
281 /*INAPL 15*/ "apl", ".lm", newline,
282 /*INMAKE 16*/ "make", ASINCOMMENT, newline,
283 /*INRI 17*/ "ri", riincomment, rioutcomment,
284 /*INTROFF 18*/ "troff",troffincomment,troffoutcomment,
285 /*INMOD2 19*/ "mod2", mod2incomment, mod2outcomment,
286 0, 0, 0
287 };
288
289 printerrors(look_at_subclass, errorc, errorv)
290 boolean look_at_subclass;
291 int errorc;
292 Eptr errorv[];
293 {
294 reg int i;
295 reg Eptr errorp;
296
297 for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]){
298 if (errorp->error_e_class == C_IGNORE)
299 continue;
300 if (look_at_subclass && errorp->error_s_class == C_DUPL)
301 continue;
302 printf("Error %d, (%s error) [%s], text = \"",
303 i,
304 class_table[errorp->error_e_class],
305 lang_table[errorp->error_language].lang_name);
306 wordvprint(stdout,errorp->error_lgtext,errorp->error_text);
307 printf("\"\n");
308 }
309 }
310
311 wordvprint(fyle, wordc, wordv)
312 FILE *fyle;
313 int wordc;
314 char *wordv[];
315 {
316 int i;
317 char *sep = "";
318
319 for(i = 0; i < wordc; i++)
320 if (wordv[i]) {
321 fprintf(fyle, "%s%s",sep,wordv[i]);
322 sep = " ";
323 }
324 }
325
326 /*
327 * Given a string, parse it into a number of words, and build
328 * a wordc wordv combination pointing into it.
329 */
330 wordvbuild(string, r_wordc, r_wordv)
331 char *string;
332 int *r_wordc;
333 char ***r_wordv;
334 {
335 reg char *cp;
336 char **wordv;
337 int wordcount;
338 int wordindex;
339
340 for (wordcount = 0, cp = string; *cp; wordcount++){
341 while (*cp && isspace(*cp))
342 cp++;
343 if (*cp == 0)
344 break;
345 while (!isspace(*cp))
346 cp++;
347 }
348 wordv = (char **)Calloc(wordcount + 1, sizeof (char *));
349 for (cp=string,wordindex=0; wordcount; wordindex++,--wordcount){
350 while (*cp && isspace(*cp))
351 cp++;
352 if (*cp == 0)
353 break;
354 wordv[wordindex] = cp;
355 while(!isspace(*cp))
356 cp++;
357 *cp++ = '\0';
358 }
359 if (wordcount != 0)
360 error("Initial miscount of the number of words in a line\n");
361 wordv[wordindex] = (char *)0;
362 #ifdef FULLDEBUG
363 for (wordcount = 0; wordcount < wordindex; wordcount++)
364 printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]);
365 printf("\n");
366 #endif
367 *r_wordc = wordindex;
368 *r_wordv = wordv;
369 }
370 /*
371 * Compare two 0 based wordvectors
372 */
373 int wordvcmp(wordv1, wordc, wordv2)
374 char **wordv1;
375 int wordc;
376 char **wordv2;
377 {
378 reg int i;
379 int back;
380 for (i = 0; i < wordc; i++){
381 if (wordv1[i] == 0 || wordv2[i] == 0)
382 return(-1);
383 if (back = strcmp(wordv1[i], wordv2[i])){
384 return(back);
385 }
386 }
387 return(0); /* they are equal */
388 }
389
390 /*
391 * splice a 0 basedword vector onto the tail of a
392 * new wordv, allowing the first emptyhead slots to be empty
393 */
394 char **wordvsplice(emptyhead, wordc, wordv)
395 int emptyhead;
396 int wordc;
397 char **wordv;
398 {
399 reg char **nwordv;
400 int nwordc = emptyhead + wordc;
401 reg int i;
402
403 nwordv = (char **)Calloc(nwordc, sizeof (char *));
404 for (i = 0; i < emptyhead; i++)
405 nwordv[i] = 0;
406 for(i = emptyhead; i < nwordc; i++){
407 nwordv[i] = wordv[i-emptyhead];
408 }
409 return(nwordv);
410 }
411 /*
412 * plural'ize and verb forms
413 */
414 static char *S = "s";
415 static char *N = "";
416 char *plural(n)
417 int n;
418 {
419 return( n > 1 ? S : N);
420 }
421 char *verbform(n)
422 int n;
423 {
424 return( n > 1 ? N : S);
425 }
426
427