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
help()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
fatal(char * msg)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
do_preamble()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
do_trailer()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
do_line()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
main(int argc,char ** argv)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