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