subr.c revision 1.3 1 /* $NetBSD: subr.c,v 1.3 1995/09/02 06:15:49 jtc 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.3 1995/09/02 06:15:49 jtc 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 *saltedbuffer;
337 char **wordv;
338 int wordcount;
339 int wordindex;
340
341 saltedbuffer = strsave(string);
342 for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++){
343 while (*cp && isspace(*cp))
344 cp++;
345 if (*cp == 0)
346 break;
347 while (!isspace(*cp))
348 cp++;
349 }
350 wordv = (char **)Calloc(wordcount + 1, sizeof (char *));
351 for (cp=saltedbuffer,wordindex=0; wordcount; wordindex++,--wordcount){
352 while (*cp && isspace(*cp))
353 cp++;
354 if (*cp == 0)
355 break;
356 wordv[wordindex] = cp;
357 while(!isspace(*cp))
358 cp++;
359 *cp++ = '\0';
360 }
361 if (wordcount != 0)
362 error("Initial miscount of the number of words in a line\n");
363 wordv[wordindex] = (char *)0;
364 #ifdef FULLDEBUG
365 for (wordcount = 0; wordcount < wordindex; wordcount++)
366 printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]);
367 printf("\n");
368 #endif
369 *r_wordc = wordindex;
370 *r_wordv = wordv;
371 }
372 /*
373 * Compare two 0 based wordvectors
374 */
375 int wordvcmp(wordv1, wordc, wordv2)
376 char **wordv1;
377 int wordc;
378 char **wordv2;
379 {
380 reg int i;
381 int back;
382 for (i = 0; i < wordc; i++){
383 if (wordv1[i] == 0 || wordv2[i] == 0)
384 return(-1);
385 if (back = strcmp(wordv1[i], wordv2[i])){
386 return(back);
387 }
388 }
389 return(0); /* they are equal */
390 }
391
392 /*
393 * splice a 0 basedword vector onto the tail of a
394 * new wordv, allowing the first emptyhead slots to be empty
395 */
396 char **wordvsplice(emptyhead, wordc, wordv)
397 int emptyhead;
398 int wordc;
399 char **wordv;
400 {
401 reg char **nwordv;
402 int nwordc = emptyhead + wordc;
403 reg int i;
404
405 nwordv = (char **)Calloc(nwordc, sizeof (char *));
406 for (i = 0; i < emptyhead; i++)
407 nwordv[i] = 0;
408 for(i = emptyhead; i < nwordc; i++){
409 nwordv[i] = wordv[i-emptyhead];
410 }
411 return(nwordv);
412 }
413 /*
414 * plural'ize and verb forms
415 */
416 static char *S = "s";
417 static char *N = "";
418 char *plural(n)
419 int n;
420 {
421 return( n > 1 ? S : N);
422 }
423 char *verbform(n)
424 int n;
425 {
426 return( n > 1 ? N : S);
427 }
428
429