10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
55846Sab196087 * Common Development and Distribution License (the "License").
65846Sab196087 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21291Smike_s
22291Smike_s /*
235846Sab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24291Smike_s * Use is subject to license terms.
25291Smike_s */
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <ctype.h>
29291Smike_s #include <stdlib.h>
30291Smike_s #include <unistd.h>
31291Smike_s #include <stdarg.h>
32291Smike_s #include <string.h>
330Sstevel@tonic-gate #include "error.h"
34291Smike_s
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate * Arrayify a list of rules
370Sstevel@tonic-gate */
38291Smike_s void
arrayify(int * e_length,Eptr ** e_array,Eptr header)39291Smike_s arrayify(int *e_length, Eptr **e_array, Eptr header)
400Sstevel@tonic-gate {
41291Smike_s Eptr errorp;
42291Smike_s Eptr *array;
43291Smike_s int listlength;
44291Smike_s int listindex;
450Sstevel@tonic-gate
460Sstevel@tonic-gate for (errorp = header, listlength = 0;
47291Smike_s errorp; errorp = errorp->error_next, listlength++)
480Sstevel@tonic-gate continue;
49291Smike_s array = Calloc(listlength+1, sizeof (Eptr));
50291Smike_s for (listindex = 0, errorp = header;
510Sstevel@tonic-gate listindex < listlength;
52291Smike_s listindex++, errorp = errorp->error_next) {
530Sstevel@tonic-gate array[listindex] = errorp;
540Sstevel@tonic-gate errorp->error_position = listindex;
550Sstevel@tonic-gate }
560Sstevel@tonic-gate array[listindex] = (Eptr)0;
570Sstevel@tonic-gate *e_length = listlength;
580Sstevel@tonic-gate *e_array = array;
590Sstevel@tonic-gate }
600Sstevel@tonic-gate
61291Smike_s /*PRINTFLIKE1*/
62291Smike_s static void
error(char * format,...)63291Smike_s error(char *format, ...)
640Sstevel@tonic-gate {
65291Smike_s va_list args;
66291Smike_s
67291Smike_s va_start(args, format);
68291Smike_s (void) fprintf(stderr, "Error: ");
69291Smike_s (void) vfprintf(stderr, format, args);
70291Smike_s (void) fprintf(stderr, "\n");
71291Smike_s (void) fflush(stdout);
72291Smike_s (void) fflush(stderr);
73291Smike_s va_end(args);
740Sstevel@tonic-gate exit(6);
750Sstevel@tonic-gate }
76291Smike_s
77291Smike_s void *
Calloc(int nelements,int size)78291Smike_s Calloc(int nelements, int size)
790Sstevel@tonic-gate {
80291Smike_s void *back;
81291Smike_s if ((back = calloc(nelements, size)) == NULL) {
820Sstevel@tonic-gate error("Ran out of memory.\n");
830Sstevel@tonic-gate exit(1);
840Sstevel@tonic-gate }
85291Smike_s return (back);
860Sstevel@tonic-gate }
870Sstevel@tonic-gate
88291Smike_s char *
strsave(char * instring)89291Smike_s strsave(char *instring)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate char *outstring;
92291Smike_s (void) strcpy(outstring = Calloc(1, strlen(instring) + 1),
935846Sab196087 instring);
94291Smike_s return (outstring);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate /*
970Sstevel@tonic-gate * find the position of a given character in a string
980Sstevel@tonic-gate * (one based)
990Sstevel@tonic-gate */
100291Smike_s int
position(char * string,char ch)101291Smike_s position(char *string, char ch)
1020Sstevel@tonic-gate {
103291Smike_s int i;
1040Sstevel@tonic-gate if (string)
105291Smike_s for (i = 1; *string; string++, i++) {
1060Sstevel@tonic-gate if (*string == ch)
107291Smike_s return (i);
1080Sstevel@tonic-gate }
109291Smike_s return (-1);
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate * clobber the first occurance of ch in string by the new character
1130Sstevel@tonic-gate */
114291Smike_s char *
substitute(char * string,char chold,char chnew)115291Smike_s substitute(char *string, char chold, char chnew)
1160Sstevel@tonic-gate {
117291Smike_s char *cp = string;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate if (cp)
120291Smike_s while (*cp) {
121291Smike_s if (*cp == chold) {
1220Sstevel@tonic-gate *cp = chnew;
1230Sstevel@tonic-gate break;
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate cp++;
1260Sstevel@tonic-gate }
127291Smike_s return (string);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate
130291Smike_s char
lastchar(char * string)131291Smike_s lastchar(char *string)
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate int length;
134291Smike_s
135291Smike_s if (string == NULL)
136291Smike_s return ('\0');
1370Sstevel@tonic-gate length = strlen(string);
1380Sstevel@tonic-gate if (length >= 1)
139291Smike_s return (string[length-1]);
1400Sstevel@tonic-gate else
141291Smike_s return ('\0');
1420Sstevel@tonic-gate }
1430Sstevel@tonic-gate
144291Smike_s char
firstchar(char * string)145291Smike_s firstchar(char *string)
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate if (string)
148291Smike_s return (string[0]);
1490Sstevel@tonic-gate else
150291Smike_s return ('\0');
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
153291Smike_s char
next_lastchar(char * string)154291Smike_s next_lastchar(char *string)
1550Sstevel@tonic-gate {
1560Sstevel@tonic-gate int length;
157291Smike_s
158291Smike_s if (string == NULL)
159291Smike_s return ('\0');
1600Sstevel@tonic-gate length = strlen(string);
1610Sstevel@tonic-gate if (length >= 2)
162291Smike_s return (string[length - 2]);
1630Sstevel@tonic-gate else
164291Smike_s return ('\0');
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate
167291Smike_s void
clob_last(char * string,char newstuff)168291Smike_s clob_last(char *string, char newstuff)
1690Sstevel@tonic-gate {
1700Sstevel@tonic-gate int length = 0;
1710Sstevel@tonic-gate if (string)
1720Sstevel@tonic-gate length = strlen(string);
1730Sstevel@tonic-gate if (length >= 1)
1740Sstevel@tonic-gate string[length - 1] = newstuff;
1750Sstevel@tonic-gate }
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate /*
1780Sstevel@tonic-gate * parse a string that is the result of a format %s(%d)
1790Sstevel@tonic-gate * return TRUE if this is of the proper format
1800Sstevel@tonic-gate */
181291Smike_s boolean
persperdexplode(char * string,char ** r_perd,char ** r_pers)182291Smike_s persperdexplode(char *string, char **r_perd, char **r_pers)
1830Sstevel@tonic-gate {
184291Smike_s char *cp;
185291Smike_s int length = 0;
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate if (string)
1880Sstevel@tonic-gate length = strlen(string);
189291Smike_s if ((length >= 4) && (string[length - 1] == ')')) {
1900Sstevel@tonic-gate for (cp = &string[length - 2];
191291Smike_s (isdigit(*cp)) && (*cp != '('); --cp)
1920Sstevel@tonic-gate continue;
193291Smike_s if (*cp == '(') {
1940Sstevel@tonic-gate string[length - 1] = '\0'; /* clobber the ) */
1950Sstevel@tonic-gate *r_perd = strsave(cp+1);
1960Sstevel@tonic-gate string[length - 1] = ')';
1970Sstevel@tonic-gate *cp = '\0'; /* clobber the ( */
1980Sstevel@tonic-gate *r_pers = strsave(string);
1990Sstevel@tonic-gate *cp = '(';
200291Smike_s return (TRUE);
201291Smike_s }
2020Sstevel@tonic-gate }
203291Smike_s return (FALSE);
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate static char cincomment[] = CINCOMMENT;
2070Sstevel@tonic-gate static char coutcomment[] = COUTCOMMENT;
2080Sstevel@tonic-gate static char fincomment[] = FINCOMMENT;
2090Sstevel@tonic-gate static char foutcomment[] = FOUTCOMMENT;
2100Sstevel@tonic-gate static char newline[] = NEWLINE;
2110Sstevel@tonic-gate static char piincomment[] = PIINCOMMENT;
2120Sstevel@tonic-gate static char pioutcomment[] = PIOUTCOMMENT;
2130Sstevel@tonic-gate static char lispincomment[] = LISPINCOMMENT;
2140Sstevel@tonic-gate static char riincomment[] = RIINCOMMENT;
2150Sstevel@tonic-gate static char rioutcomment[] = RIOUTCOMMENT;
2160Sstevel@tonic-gate static char troffincomment[] = TROFFINCOMMENT;
2170Sstevel@tonic-gate static char troffoutcomment[] = TROFFOUTCOMMENT;
2180Sstevel@tonic-gate static char mod2incomment[] = MOD2INCOMMENT;
2190Sstevel@tonic-gate static char mod2outcomment[] = MOD2OUTCOMMENT;
2200Sstevel@tonic-gate
221291Smike_s struct lang_desc lang_table[] = {
222291Smike_s /* INUNKNOWN 0 */ "unknown", cincomment, coutcomment,
223291Smike_s /* INCPP 1 */ "cpp", cincomment, coutcomment,
224291Smike_s /* INCC 2 */ "cc", cincomment, coutcomment,
225291Smike_s /* INAS 3 */ "as", ASINCOMMENT, newline,
226291Smike_s /* INLD 4 */ "ld", cincomment, coutcomment,
227291Smike_s /* INLINT 5 */ "lint", cincomment, coutcomment,
228291Smike_s /* INF77 6 */ "f77", fincomment, foutcomment,
229291Smike_s /* INPI 7 */ "pi", piincomment, pioutcomment,
230291Smike_s /* INPC 8 */ "pc", piincomment, pioutcomment,
231291Smike_s /* INFRANZ 9 */ "franz", lispincomment, newline,
232291Smike_s /* INLISP 10 */ "lisp", lispincomment, newline,
233291Smike_s /* INVAXIMA 11 */ "vaxima", lispincomment, newline,
234291Smike_s /* INRATFOR 12 */ "ratfor", fincomment, foutcomment,
235291Smike_s /* INLEX 13 */ "lex", cincomment, coutcomment,
236291Smike_s /* INYACC 14 */ "yacc", cincomment, coutcomment,
237291Smike_s /* INAPL 15 */ "apl", ".lm", newline,
238291Smike_s /* INMAKE 16 */ "make", ASINCOMMENT, newline,
239291Smike_s /* INRI 17 */ "ri", riincomment, rioutcomment,
240291Smike_s /* INTROFF 18 */ "troff", troffincomment, troffoutcomment,
241291Smike_s /* INMOD2 19 */ "mod2", mod2incomment, mod2outcomment,
242291Smike_s /* INSUNF77 20 */ "Sunf77", fincomment, foutcomment,
243291Smike_s 0, 0, 0
2440Sstevel@tonic-gate };
2450Sstevel@tonic-gate
246291Smike_s void
printerrors(boolean look_at_subclass,int errorc,Eptr errorv[])247291Smike_s printerrors(boolean look_at_subclass, int errorc, Eptr errorv[])
2480Sstevel@tonic-gate {
249291Smike_s int i;
250291Smike_s Eptr errorp;
2510Sstevel@tonic-gate
252291Smike_s for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]) {
2530Sstevel@tonic-gate if (errorp->error_e_class == C_IGNORE)
2540Sstevel@tonic-gate continue;
2550Sstevel@tonic-gate if (look_at_subclass && errorp->error_s_class == C_DUPL)
2560Sstevel@tonic-gate continue;
257291Smike_s (void) printf("Error %d, (%s error) [%s], text = \"",
2585846Sab196087 i,
2595846Sab196087 class_table[errorp->error_e_class],
2605846Sab196087 lang_table[errorp->error_language].lang_name);
261291Smike_s wordvprint(stdout, errorp->error_lgtext, errorp->error_text);
262291Smike_s (void) printf("\"\n");
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate
266291Smike_s void
wordvprint(FILE * fyle,int wordc,char * wordv[])267291Smike_s wordvprint(FILE *fyle, int wordc, char *wordv[])
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate int i;
2700Sstevel@tonic-gate char *sep = "";
2710Sstevel@tonic-gate
272291Smike_s for (i = 0; i < wordc; i++)
2730Sstevel@tonic-gate if (wordv[i]) {
274291Smike_s (void) fprintf(fyle, "%s%s", sep, wordv[i]);
2750Sstevel@tonic-gate sep = " ";
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate /*
2800Sstevel@tonic-gate * Given a string, parse it into a number of words, and build
2810Sstevel@tonic-gate * a wordc wordv combination pointing into it.
2820Sstevel@tonic-gate */
283291Smike_s void
wordvbuild(char * string,int * r_wordc,char *** r_wordv)284291Smike_s wordvbuild(char *string, int *r_wordc, char ***r_wordv)
2850Sstevel@tonic-gate {
286291Smike_s char *cp;
2875846Sab196087 char *saltedbuffer;
2885846Sab196087 char **wordv;
2895846Sab196087 int wordcount;
2905846Sab196087 int wordindex;
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate saltedbuffer = strsave(string);
293291Smike_s for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++) {
294291Smike_s while (*cp && isspace(*cp))
2950Sstevel@tonic-gate cp++;
296*7940SMatthew.Jacob@Sun.COM if (*cp == 0)
297*7940SMatthew.Jacob@Sun.COM break;
2985846Sab196087 while (*cp && !isspace(*cp))
2990Sstevel@tonic-gate cp++;
3000Sstevel@tonic-gate }
301291Smike_s wordv = Calloc(wordcount + 1, sizeof (char *));
302291Smike_s for (cp = saltedbuffer, wordindex = 0; wordcount;
303291Smike_s wordindex++, --wordcount) {
3040Sstevel@tonic-gate while (*cp && isspace(*cp))
3050Sstevel@tonic-gate cp++;
3060Sstevel@tonic-gate if (*cp == 0)
3070Sstevel@tonic-gate break;
3080Sstevel@tonic-gate wordv[wordindex] = cp;
3095846Sab196087 while (*cp && !isspace(*cp))
3100Sstevel@tonic-gate cp++;
3110Sstevel@tonic-gate *cp++ = '\0';
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate if (wordcount != 0)
3140Sstevel@tonic-gate error("Initial miscount of the number of words in a line\n");
315291Smike_s wordv[wordindex] = NULL;
3160Sstevel@tonic-gate #ifdef FULLDEBUG
3170Sstevel@tonic-gate for (wordcount = 0; wordcount < wordindex; wordcount++)
318291Smike_s (void) printf("Word %d = \"%s\"\n", wordcount,
319291Smike_s wordv[wordcount]);
320291Smike_s (void) printf("\n");
3210Sstevel@tonic-gate #endif
3220Sstevel@tonic-gate *r_wordc = wordindex;
3230Sstevel@tonic-gate *r_wordv = wordv;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate /*
3260Sstevel@tonic-gate * Compare two 0 based wordvectors
3270Sstevel@tonic-gate */
328291Smike_s int
wordvcmp(char ** wordv1,int wordc,char ** wordv2)329291Smike_s wordvcmp(char **wordv1, int wordc, char **wordv2)
3300Sstevel@tonic-gate {
331291Smike_s int i;
332291Smike_s int back;
333291Smike_s
334291Smike_s for (i = 0; i < wordc; i++) {
3350Sstevel@tonic-gate if (wordv1[i] == 0 || wordv2[i] == 0)
336291Smike_s return (-1);
337291Smike_s if (back = strcmp(wordv1[i], wordv2[i])) {
338291Smike_s return (back);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate }
341291Smike_s return (0); /* they are equal */
3420Sstevel@tonic-gate }
343291Smike_s
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * splice a 0 basedword vector onto the tail of a
3460Sstevel@tonic-gate * new wordv, allowing the first emptyhead slots to be empty
3470Sstevel@tonic-gate */
348291Smike_s char **
wordvsplice(int emptyhead,int wordc,char ** wordv)349291Smike_s wordvsplice(int emptyhead, int wordc, char **wordv)
3500Sstevel@tonic-gate {
351291Smike_s char **nwordv;
352291Smike_s int nwordc = emptyhead + wordc;
353291Smike_s int i;
3540Sstevel@tonic-gate
355291Smike_s nwordv = Calloc(nwordc, sizeof (char *));
3560Sstevel@tonic-gate for (i = 0; i < emptyhead; i++)
3570Sstevel@tonic-gate nwordv[i] = 0;
358291Smike_s for (i = emptyhead; i < nwordc; i++) {
3590Sstevel@tonic-gate nwordv[i] = wordv[i-emptyhead];
3600Sstevel@tonic-gate }
361291Smike_s return (nwordv);
3620Sstevel@tonic-gate }
363291Smike_s
3640Sstevel@tonic-gate /*
3650Sstevel@tonic-gate * plural'ize and verb forms
3660Sstevel@tonic-gate */
3670Sstevel@tonic-gate static char *S = "s";
3680Sstevel@tonic-gate static char *N = "";
369291Smike_s
370291Smike_s char *
plural(int n)371291Smike_s plural(int n)
3720Sstevel@tonic-gate {
373291Smike_s return (n > 1 ? S : N);
3740Sstevel@tonic-gate }
3750Sstevel@tonic-gate
376291Smike_s char *
verbform(int n)377291Smike_s verbform(int n)
378291Smike_s {
379291Smike_s return (n > 1 ? N : S);
380291Smike_s }
381