1 /* $NetBSD: subr.c,v 1.18 2009/08/13 05:53:58 dholland Exp $ */
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
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
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)subr.c 8.1 (Berkeley) 6/6/93";
37 __RCSID("$NetBSD: subr.c,v 1.18 2009/08/13 05:53:58 dholland Exp $");
48 * Arrayify a list of rules
51 arrayify(int *e_length
, Eptr
**e_array
, Eptr header
)
58 for (errorp
= header
, listlength
= 0;
59 errorp
; errorp
= errorp
->error_next
, listlength
++)
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
;
74 Calloc(size_t nelements
, size_t size
)
78 back
= calloc(nelements
, size
);
80 errx(1, "Ran out of memory.");
91 errx(1, "Ran out of memory.");
97 * find the position of a given character in a string
101 position(const char *string
, char ch
)
106 for (i
=1; *string
; string
++, i
++) {
114 * clobber the first occurance of ch in string by the new character
117 substitute(char *string
, char chold
, char chnew
)
133 lastchar(const char *string
)
139 length
= strlen(string
);
141 return (string
[length
-1]);
147 firstchar(const char *string
)
156 next_lastchar(const char *string
)
162 length
= strlen(string
);
164 return (string
[length
- 2]);
170 clob_last(char *string
, char newstuff
)
175 length
= strlen(string
);
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
185 persperdexplode(char *string
, char **r_perd
, char **r_pers
)
191 length
= strlen(string
);
192 if (length
>= 4 && string
[length
- 1] == ')') {
193 for (cp
= &string
[length
- 2];
194 isdigit((unsigned char)*cp
) && *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
);
212 * parse a quoted string that is the result of a format \"%s\"(%d)
213 * return TRUE if this is of the proper format
216 qpersperdexplode(char *string
, char **r_perd
, char **r_pers
)
222 length
= strlen(string
);
223 if (length
>= 4 && string
[length
- 1] == ')') {
224 for (cp
= &string
[length
- 2];
225 isdigit((unsigned char)*cp
) && *cp
!= '(';
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);
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
},
282 printerrors(bool look_at_subclass
, int errorc
, Eptr errorv
[])
287 for (errorp
= errorv
[i
= 0]; i
< errorc
; errorp
= errorv
[++i
]) {
288 if (errorp
->error_e_class
== C_IGNORE
)
290 if (look_at_subclass
&& errorp
->error_s_class
== C_DUPL
)
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
);
302 wordvprint(FILE *fyle
, int wordc
, char **wordv
)
305 const char *sep
= "";
307 for (i
= 0; i
< wordc
; i
++)
309 fprintf(fyle
, "%s%s",sep
,wordv
[i
]);
315 * Given a string, parse it into a number of words, and build
316 * a wordc wordv combination pointing into it.
319 wordvbuild(char *string
, int *r_wordc
, char ***r_wordv
)
326 for (wordcount
= 0, cp
= string
; *cp
; wordcount
++) {
327 while (*cp
&& isspace((unsigned char)*cp
))
331 while (*cp
&& !isspace((unsigned char)*cp
))
334 wordv
= Calloc(wordcount
+ 1, sizeof (char *));
335 for (cp
=string
, wordindex
=0; wordcount
; wordindex
++, --wordcount
) {
336 while (*cp
&& isspace((unsigned char)*cp
))
340 wordv
[wordindex
] = cp
;
341 while (*cp
&& !isspace((unsigned char)*cp
))
346 errx(6, "Initial miscount of the number of words in a line");
347 wordv
[wordindex
] = NULL
;
349 for (wordcount
= 0; wordcount
< wordindex
; wordcount
++)
350 printf("Word %d = \"%s\"\n", wordcount
, wordv
[wordcount
]);
353 *r_wordc
= wordindex
;
358 * Compare two 0 based wordvectors
361 wordvcmp(char **wordv1
, int wordc
, char **wordv2
)
366 for (i
= 0; i
< wordc
; i
++) {
367 if (wordv1
[i
] == NULL
|| wordv2
[i
] == NULL
)
369 if ((back
= strcmp(wordv1
[i
], wordv2
[i
])) != 0)
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
380 wordvsplice(int emptyhead
, int wordc
, char **wordv
)
383 int nwordc
= emptyhead
+ wordc
;
386 nwordv
= Calloc(nwordc
, sizeof (char *));
387 for (i
= 0; i
< emptyhead
; i
++)
389 for (i
= emptyhead
; i
< nwordc
; i
++) {
390 nwordv
[i
] = wordv
[i
-emptyhead
];
396 * plural and verb forms
398 static const char *S
= "s";
399 static const char *N
= "";
404 return (n
> 1 ? S
: N
);
410 return (n
> 1 ? N
: S
);