xref: /titanic_51/usr/src/cmd/avs/errgen/errgen.c (revision 4201a95e0468170d576f82c3aa63afecf718497a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  *	Read an errgen status resource file (*.err) from standard input and
28  *	write an SPCS error code C header file (-c), Java resource file (-j),
29  *	libspcs Java exception class file(-e), error text file (-m) or JNI
30  *      exception trinket table to standard output. Lines starting with "#"
31  *      are ignored.
32  *
33  *	Use "errgen -h" to get usage info including module codes and example
34  *      input and output.
35  */
36 
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <libgen.h>
43 #include <limits.h>
44 #include <sys/param.h>
45 
46 /* The public error info header file.  */
47 
48 #include <sys/unistat/spcs_s.h>
49 
50 /* The private error info header file */
51 
52 #include <sys/unistat/spcs_s_impl.h>
53 
54 
55 /*  locals  */
56 
57 static enum {C_MODE, J_MODE, M_MODE, E_MODE, T_MODE, X_MODE} mode = E_MODE;
58 static	char key[SPCS_S_MAXKEY];
59 static	char text[SPCS_S_MAXTEXT];
60 static int mod_number;
61 
62 static char help_path[PATH_MAX];
63 
64 static int count = 1;
65 
66 static char key[SPCS_S_MAXKEY];
67 static char text[SPCS_S_MAXTEXT];
68 static char modname[SPCS_S_MAXMODNAME];
69 
70 /*
71  *	Display help info
72  */
73 
74 static void
75 help()
76 {
77 	char line[SPCS_S_MAXLINE];
78 	FILE *h = fopen(help_path, "r");
79 
80 	if (h) {
81 		while (! feof(h)) {
82 			(void) fgets(line, SPCS_S_MAXLINE, h);
83 			if (! feof(h))
84 				(void) fputs(line, stderr);
85 		}
86 	} else {
87 		perror(strcat("could not open: ", help_path));
88 		exit(1);
89 	}
90 }
91 
92 /*
93  *	Put out a message with terse instructions and err out
94  */
95 
96 static void
97 fatal(char *msg)
98 {
99 	(void) fprintf(stderr, "%s\n\n", msg);
100 	(void) fprintf(stderr, "use errgen -h for help\n");
101 	exit(1);
102 }
103 
104 /*
105  *	Put out the output file preamble
106  */
107 
108 static void
109 do_preamble()
110 {
111 	switch (mode) {
112 	case M_MODE:
113 		(void) fprintf(stdout,
114 			"static\nchar *SPCS_MSG_%s[] = {\n", modname);
115 		(void) fprintf(stdout, "\t\"\",\n");
116 		break;
117 	case T_MODE:
118 		(void) fprintf(stdout,
119 			"static\nchar *SPCS_TRNK_%s[] = {\n", modname);
120 		(void) fprintf(stdout, "\t\"\",\n");
121 		break;
122 	}
123 }
124 
125 /*
126  *	Put out the output file trailer
127  */
128 
129 static void
130 do_trailer()
131 {
132 	switch (mode) {
133 	case M_MODE:
134 		(void) fprintf(stdout, "};\n");
135 		(void) fprintf(stdout,
136 			"#define\tSPCS_MSGLEN_%s %d\t/* total codes */\n",
137 			modname, count-1);
138 		break;
139 	case T_MODE:
140 		(void) fprintf(stdout, "};\n");
141 		(void) fprintf(stdout,
142 			"#define\tSPCS_TRNKLEN_%s %d\t/* total codes */\n",
143 			modname, count-1);
144 		break;
145 	}
146 }
147 
148 /*
149  *	Process a single input line
150  */
151 
152 static void
153 do_line()
154 {
155 	spcs_s_udata_t c;
156 	int fc = 0;
157 	int len = 0;
158 	char ptext[SPCS_S_MAXTEXT];
159 	char keystring[SPCS_S_MAXKEY+SPCS_S_MAXPRE];
160 	char *p = text;
161 	int tlen;
162 	char *pt = ptext;
163 	char havebytestream = 0;
164 
165 	c.i = 0;
166 	(void) sprintf(keystring, "%s_E%s", modname, key);
167 	while (*p) {
168 		if (*p == '%') {
169 			if (*(p + 1) != 's') {
170 				(void) fprintf(stderr,
171 				    "ERRGEN: Error in .err file\n");
172 				(void) fprintf(stderr,
173 				    "%c is an illegal format spec after %%",
174 				    *p);
175 				(void) fprintf(stderr,
176 				    " at line: %d pos: %d\n", count,
177 					/* LINTED possible ptrdiff_t overflow */
178 				    (int)(p - text));
179 				fatal("");
180 			}
181 			len = sprintf(pt, "{%d}", fc);
182 			pt += len;
183 			p++;
184 			fc += 1;
185 			if (fc > SPCS_S_MAXSUPP) {
186 				(void) fprintf(stderr,
187 					"ERRGEN: Error in .err file\n");
188 				(void) fprintf(stderr,
189 				    "SPCS_S_MAXSUPP exceeeded\n");
190 				fatal("Too many %%s specifiers");
191 			}
192 		} else
193 			*pt++ = *p;
194 		p++;
195 	}
196 
197 	/* look for a bytestream indicator */
198 
199 	tlen = strlen(text);
200 
201 	if ((tlen > 2) && (text[tlen - 1] == '@') && (text[tlen - 2] == '@')) {
202 		if (fc)
203 			fatal("ERRGEN: cannot have %%s and @@ ending too");
204 
205 		/* bump the item count and set the bytestream flag */
206 		fc += 1;
207 		havebytestream = 1;
208 	}
209 
210 	*pt = 0;
211 
212 	switch (mode) {
213 	case C_MODE:
214 		c.f.bytestream = havebytestream;
215 		c.f.sup_count = fc;
216 		c.f.module = mod_number;
217 		c.f.code = count;
218 		(void) fprintf(stdout, "#define\t%s 0x%x /* %s */\n",
219 			keystring, c.i, text);
220 		break;
221 	case J_MODE:
222 		(void) fprintf(stdout, "`%s` = %s\n", keystring, ptext);
223 		break;
224 	case X_MODE:
225 		(void) fprintf(stdout,
226 		    "#define\tT_%s \"`%s`\"\n", keystring, keystring);
227 		break;
228 	case T_MODE:
229 		(void) fprintf(stdout, "\t\"`%s`\",\n", keystring);
230 		break;
231 	case M_MODE:
232 		(void) fprintf(stdout, "\t\"%s\",\n", text);
233 		break;
234 	case E_MODE:
235 		(void) fprintf(stdout, "    /**\n     * %s\n    **/\n",
236 			text);
237 		(void) fprintf(stdout, "    public static final String %s",
238 			    keystring);
239 		(void) fprintf(stdout, " = `%s`;\n\n", keystring);
240 		break;
241 	}
242 }
243 
244 int
245 main(int argc, char **argv)
246 {
247 	int i;
248 	int searching = 1;
249 	char searchname[SPCS_S_MAXMODNAME];
250 	char line[SPCS_S_MAXLINE];
251 	char tline[SPCS_S_MAXLINE];
252 	char *p, *p2;
253 
254 	(void) strcpy(help_path, dirname(argv[0]));
255 	(void) strcat(help_path, "/errgen.help");
256 	if ((argc == 1) || ((argc == 2) && (strcmp(argv[1], "-h") == 0))) {
257 		help();
258 		exit(0);
259 	}
260 
261 	if (argc != 3)
262 		fatal("Bad number of arguments");
263 
264 	p = argv[2];
265 	p2 = modname;
266 
267 	while (*p)
268 		*p2++ = toupper(*p++);
269 	*p2 = 0;
270 
271 	switch (argv[1][1]) {
272 	case 'c':
273 		mode = C_MODE;
274 		break;
275 	case 'j':
276 		mode = J_MODE;
277 		break;
278 	case 'e':
279 		mode = E_MODE;
280 		break;
281 	case 'm':
282 		mode = M_MODE;
283 		break;
284 	case 't':
285 		mode = T_MODE;
286 		break;
287 	case 'x':
288 		mode = X_MODE;
289 		break;
290 	default:
291 		fatal("Unknown option switch");
292 	}
293 
294 	if (strcmp(modname, "DSW") == 0) {
295 		(void) strcpy(searchname, "II");
296 	} else if (strcmp(modname, "RDC") == 0) {
297 		(void) strcpy(searchname, "SNDR");
298 	} else if (strcmp(modname, "SDCTL") == 0) {
299 		(void) strcpy(searchname, "NSCTL");
300 	} else {
301 		(void) strcpy(searchname, modname);
302 	}
303 
304 	i = 0;
305 	do {
306 		if (strcmp(module_names[i++], searchname) == 0) {
307 			searching = 0;
308 			mod_number = i - 1;
309 			break;
310 		}
311 	} while (module_names[i]);
312 
313 	if (searching) {
314 		if (i != SPCS_M_MAX)
315 			(void) fprintf(stderr,
316 			"NULL in module_names before SPCS_M_MAX\n");
317 		fatal("Undefined module name");
318 	}
319 
320 	do_preamble();
321 
322 	while (!feof(stdin)) {
323 		(void) fgets(line, SPCS_S_MAXLINE, stdin);
324 		if (feof(stdin)) {
325 			if (count == 0)
326 				fatal("errgen file empty");
327 
328 			do_trailer();
329 			exit(0);
330 		}
331 		line[strlen(line)-1] = 0;
332 		if ((strlen(line) != 0) && (line[0] != '#')) {
333 		    (void) strcpy(tline, line);
334 		    p = strchr(tline, ' ');
335 		    if (p == NULL) {
336 			(void) fprintf(stderr,
337 				    "blank separator missing at line: %d\n",
338 					    count);
339 			    fatal("");
340 		    }
341 		    *p = 0;
342 		    if (strlen(p) > SPCS_S_MAXKEY) {
343 			    (void) fprintf(stderr,
344 			    "message label too long at line: %d\n", count);
345 			    fatal("");
346 		    }
347 		    (void) strcpy(key, tline);
348 		    if (strlen(key) == 0) {
349 			    (void) fprintf(stderr,
350 				    "leading blank at line: %d\n", count);
351 			    fatal("");
352 		    }
353 		    p++;
354 		    if (*p != '=') {
355 			    (void) fprintf(stderr,
356 				    "= separator missing at line: %d\n", count);
357 			    fatal("");
358 		    }
359 		    p++;
360 		    if (*p != ' ') {
361 			    (void) fprintf(stderr,
362 				"blank separator missing at line: %d\n", count);
363 			    fatal("");
364 		    }
365 		    p++;
366 		    if (! *p) {
367 			    (void) fprintf(stderr,
368 				    "msg text missing at line:%d\n", count);
369 			    fatal("");
370 		    }
371 		    (void) strcpy(text, p);
372 
373 		    do_line();
374 		    count++;
375 		}
376 	}
377 
378 	return (0);
379 }
380