Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / usr.bin / error / subr.c
blobb0cf025804e646f9ff57f12a589fc0456766331d
1 /* $NetBSD: subr.c,v 1.18 2009/08/13 05:53:58 dholland Exp $ */
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
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. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/6/93";
36 #endif
37 __RCSID("$NetBSD: subr.c,v 1.18 2009/08/13 05:53:58 dholland Exp $");
38 #endif /* not lint */
40 #include <ctype.h>
41 #include <err.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include "error.h"
48 * Arrayify a list of rules
50 void
51 arrayify(int *e_length, Eptr **e_array, Eptr header)
53 Eptr errorp;
54 Eptr *array;
55 int listlength;
56 int listindex;
58 for (errorp = header, listlength = 0;
59 errorp; errorp = errorp->error_next, listlength++)
60 continue;
61 array = Calloc(listlength+1, sizeof (Eptr));
62 for (listindex = 0, errorp = header;
63 listindex < listlength;
64 listindex++, errorp = errorp->error_next) {
65 array[listindex] = errorp;
66 errorp->error_position = listindex;
68 array[listindex] = NULL;
69 *e_length = listlength;
70 *e_array = array;
73 void *
74 Calloc(size_t nelements, size_t size)
76 void *back;
78 back = calloc(nelements, size);
79 if (back == NULL)
80 errx(1, "Ran out of memory.");
81 return (back);
84 char *
85 Strdup(const char *s)
87 char *ret;
89 ret = strdup(s);
90 if (ret == NULL) {
91 errx(1, "Ran out of memory.");
93 return ret;
97 * find the position of a given character in a string
98 * (one based)
101 position(const char *string, char ch)
103 int i;
105 if (string)
106 for (i=1; *string; string++, i++) {
107 if (*string == ch)
108 return (i);
110 return (-1);
114 * clobber the first occurance of ch in string by the new character
116 char *
117 substitute(char *string, char chold, char chnew)
119 char *cp = string;
121 if (cp)
122 while (*cp) {
123 if (*cp == chold) {
124 *cp = chnew;
125 break;
127 cp++;
129 return (string);
132 char
133 lastchar(const char *string)
135 int length;
137 if (string == NULL)
138 return ('\0');
139 length = strlen(string);
140 if (length >= 1)
141 return (string[length-1]);
142 else
143 return ('\0');
146 char
147 firstchar(const char *string)
149 if (string)
150 return (string[0]);
151 else
152 return ('\0');
155 char
156 next_lastchar(const char *string)
158 int length;
160 if (string == NULL)
161 return ('\0');
162 length = strlen(string);
163 if (length >= 2)
164 return (string[length - 2]);
165 else
166 return ('\0');
169 void
170 clob_last(char *string, char newstuff)
172 int length = 0;
174 if (string)
175 length = strlen(string);
176 if (length >= 1)
177 string[length - 1] = newstuff;
181 * parse a string that is the result of a format %s(%d)
182 * return TRUE if this is of the proper format
184 bool
185 persperdexplode(char *string, char **r_perd, char **r_pers)
187 char *cp;
188 int length = 0;
190 if (string)
191 length = strlen(string);
192 if (length >= 4 && string[length - 1] == ')') {
193 for (cp = &string[length - 2];
194 isdigit((unsigned char)*cp) && *cp != '(';
195 --cp)
196 continue;
197 if (*cp == '(') {
198 string[length - 1] = '\0'; /* clobber the ) */
199 *r_perd = strdup(cp+1);
200 string[length - 1] = ')';
201 *cp = '\0'; /* clobber the ( */
202 *r_pers = strdup(string);
203 *cp = '(';
204 return true;
207 return false;
210 #if 0 /* unused */
212 * parse a quoted string that is the result of a format \"%s\"(%d)
213 * return TRUE if this is of the proper format
215 static boolean
216 qpersperdexplode(char *string, char **r_perd, char **r_pers)
218 char *cp;
219 int length = 0;
221 if (string)
222 length = strlen(string);
223 if (length >= 4 && string[length - 1] == ')') {
224 for (cp = &string[length - 2];
225 isdigit((unsigned char)*cp) && *cp != '(';
226 --cp)
227 continue;
228 if (*cp == '(' && *(cp - 1) == '"') {
229 string[length - 1] = '\0';
230 *r_perd = strdup(cp+1);
231 string[length - 1] = ')';
232 *(cp - 1) = '\0'; /* clobber the " */
233 *r_pers = strdup(string + 1);
234 *(cp - 1) = '"';
235 return true;
238 return false;
240 #endif /* 0 - unused */
242 static char cincomment[] = CINCOMMENT;
243 static char coutcomment[] = COUTCOMMENT;
244 static char fincomment[] = FINCOMMENT;
245 static char foutcomment[] = FOUTCOMMENT;
246 static char newline[] = NEWLINE;
247 static char piincomment[] = PIINCOMMENT;
248 static char pioutcomment[] = PIOUTCOMMENT;
249 static char lispincomment[] = LISPINCOMMENT;
250 static char riincomment[] = RIINCOMMENT;
251 static char rioutcomment[] = RIOUTCOMMENT;
252 static char troffincomment[] = TROFFINCOMMENT;
253 static char troffoutcomment[] = TROFFOUTCOMMENT;
254 static char mod2incomment[] = MOD2INCOMMENT;
255 static char mod2outcomment[] = MOD2OUTCOMMENT;
257 struct lang_desc lang_table[] = {
258 { /*INUNKNOWN 0*/ "unknown", cincomment, coutcomment },
259 { /*INCPP 1*/ "cpp", cincomment, coutcomment },
260 { /*INCC 2*/ "cc", cincomment, coutcomment },
261 { /*INAS 3*/ "as", ASINCOMMENT, newline },
262 { /*INLD 4*/ "ld", cincomment, coutcomment },
263 { /*INLINT 5*/ "lint", cincomment, coutcomment },
264 { /*INF77 6*/ "f77", fincomment, foutcomment },
265 { /*INPI 7*/ "pi", piincomment, pioutcomment },
266 { /*INPC 8*/ "pc", piincomment, pioutcomment },
267 { /*INFRANZ 9*/ "franz", lispincomment, newline },
268 { /*INLISP 10*/ "lisp", lispincomment, newline },
269 { /*INVAXIMA 11*/ "vaxima", lispincomment, newline },
270 { /*INRATFOR 12*/ "ratfor", fincomment, foutcomment },
271 { /*INLEX 13*/ "lex", cincomment, coutcomment },
272 { /*INYACC 14*/ "yacc", cincomment, coutcomment },
273 { /*INAPL 15*/ "apl", ".lm", newline },
274 { /*INMAKE 16*/ "make", ASINCOMMENT, newline },
275 { /*INRI 17*/ "ri", riincomment, rioutcomment },
276 { /*INTROFF 18*/ "troff", troffincomment, troffoutcomment },
277 { /*INMOD2 19*/ "mod2", mod2incomment, mod2outcomment },
278 { 0, 0, 0 }
281 void
282 printerrors(bool look_at_subclass, int errorc, Eptr errorv[])
284 int i;
285 Eptr errorp;
287 for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) {
288 if (errorp->error_e_class == C_IGNORE)
289 continue;
290 if (look_at_subclass && errorp->error_s_class == C_DUPL)
291 continue;
292 printf("Error %d, (%s error) [%s], text = \"",
294 class_table[errorp->error_e_class],
295 lang_table[errorp->error_language].lang_name);
296 wordvprint(stdout,errorp->error_lgtext,errorp->error_text);
297 printf("\"\n");
301 void
302 wordvprint(FILE *fyle, int wordc, char **wordv)
304 int i;
305 const char *sep = "";
307 for (i = 0; i < wordc; i++)
308 if (wordv[i]) {
309 fprintf(fyle, "%s%s",sep,wordv[i]);
310 sep = " ";
315 * Given a string, parse it into a number of words, and build
316 * a wordc wordv combination pointing into it.
318 void
319 wordvbuild(char *string, int *r_wordc, char ***r_wordv)
321 char *cp;
322 char **wordv;
323 int wordcount;
324 int wordindex;
326 for (wordcount = 0, cp = string; *cp; wordcount++) {
327 while (*cp && isspace((unsigned char)*cp))
328 cp++;
329 if (*cp == '\0')
330 break;
331 while (*cp && !isspace((unsigned char)*cp))
332 cp++;
334 wordv = Calloc(wordcount + 1, sizeof (char *));
335 for (cp=string, wordindex=0; wordcount; wordindex++, --wordcount) {
336 while (*cp && isspace((unsigned char)*cp))
337 cp++;
338 if (*cp == '\0')
339 break;
340 wordv[wordindex] = cp;
341 while (*cp && !isspace((unsigned char)*cp))
342 cp++;
343 *cp++ = '\0';
345 if (wordcount != 0)
346 errx(6, "Initial miscount of the number of words in a line");
347 wordv[wordindex] = NULL;
348 #ifdef FULLDEBUG
349 for (wordcount = 0; wordcount < wordindex; wordcount++)
350 printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]);
351 printf("\n");
352 #endif
353 *r_wordc = wordindex;
354 *r_wordv = wordv;
358 * Compare two 0 based wordvectors
361 wordvcmp(char **wordv1, int wordc, char **wordv2)
363 int i;
364 int back;
366 for (i = 0; i < wordc; i++) {
367 if (wordv1[i] == NULL || wordv2[i] == NULL)
368 return (-1);
369 if ((back = strcmp(wordv1[i], wordv2[i])) != 0)
370 return (back);
372 return (0); /* they are equal */
376 * splice a 0 basedword vector onto the tail of a
377 * new wordv, allowing the first emptyhead slots to be empty
379 char **
380 wordvsplice(int emptyhead, int wordc, char **wordv)
382 char **nwordv;
383 int nwordc = emptyhead + wordc;
384 int i;
386 nwordv = Calloc(nwordc, sizeof (char *));
387 for (i = 0; i < emptyhead; i++)
388 nwordv[i] = NULL;
389 for (i = emptyhead; i < nwordc; i++) {
390 nwordv[i] = wordv[i-emptyhead];
392 return (nwordv);
396 * plural and verb forms
398 static const char *S = "s";
399 static const char *N = "";
401 const char *
402 plural(int n)
404 return (n > 1 ? S : N);
407 const char *
408 verbform(int n)
410 return (n > 1 ? N : S);