Commit | Line | Data |
---|---|---|
805e021f CE |
1 | %{ |
2 | #include <afsconfig.h> | |
3 | #include <afs/param.h> | |
4 | #include <roken.h> | |
5 | ||
6 | /* | |
7 | * | |
8 | * Copyright 1986, 1987 by the MIT Student Information Processing Board | |
9 | * | |
10 | * For copyright info, see mit-sipb-cr.h. | |
11 | */ | |
12 | #ifndef AFS_NT40_ENV | |
13 | #include <unistd.h> | |
14 | #endif | |
15 | #include <string.h> | |
16 | #include <assert.h> | |
17 | #include <ctype.h> | |
18 | #ifdef AFS_NT40_ENV | |
19 | #include <sys/types.h> | |
20 | #include <afs/afsutil.h> | |
21 | #else | |
22 | #include <sys/time.h> | |
23 | #endif | |
24 | #include "error_table.h" | |
25 | #include "mit-sipb-cr.h" | |
26 | ||
27 | /* | |
28 | * If __STDC__ is defined, function prototypes in the SunOS 5.5.1 lex | |
29 | * and yacc templates are visible. We turn this on explicitly on | |
30 | * NT because the prototypes help supress certain warning from the | |
31 | * Microsoft C compiler. | |
32 | */ | |
33 | ||
34 | #ifdef AFS_NT40_ENV | |
35 | #include <malloc.h> | |
36 | # ifndef __STDC__ | |
37 | # define __STDC__ 1 | |
38 | # endif | |
39 | #endif | |
40 | ||
41 | #include <stdio.h> | |
42 | #include <stdlib.h> | |
43 | #include <string.h> | |
44 | ||
45 | #include "internal.h" | |
46 | ||
47 | int char_to_num(char c); | |
48 | char *gensym(const char *x); | |
49 | char *current_token = NULL; | |
50 | extern char *table_name; | |
51 | ||
52 | char *quote(const char *string); | |
53 | void set_table_1num(char *string); | |
54 | int char_to_1num(char c); | |
55 | void add_ec(const char *name, const char *description); | |
56 | void add_ec_val(const char *name, const char *val, const char *description); | |
57 | void put_ecs(void); | |
58 | void set_table_num(char *string); | |
59 | void set_table_fun(char *astring); | |
60 | ||
61 | extern int yylex (void); | |
62 | ||
63 | %} | |
64 | %union { | |
65 | char *dynstr; | |
66 | } | |
67 | ||
68 | %token ERROR_TABLE ERROR_CODE_ENTRY END | |
69 | %token <dynstr> STRING QUOTED_STRING | |
70 | %type <dynstr> ec_name description table_id table_fun header | |
71 | %{ | |
72 | %} | |
73 | %start error_table | |
74 | %% | |
75 | ||
76 | error_table : ERROR_TABLE header error_codes END | |
77 | { table_name = strdup($2); | |
78 | current_token = table_name; | |
79 | put_ecs(); } | |
80 | ; | |
81 | ||
82 | header : table_fun table_id | |
83 | { current_token = $1; | |
84 | $$ = $2; } | |
85 | | table_id | |
86 | { current_token = $1; | |
87 | set_table_fun(strdup("1")); | |
88 | $$ = $1; | |
89 | } | |
90 | ; | |
91 | ||
92 | table_fun : STRING | |
93 | { current_token = $1; | |
94 | set_table_fun($1); | |
95 | $$ = $1; } | |
96 | ; | |
97 | ||
98 | ||
99 | table_id : STRING | |
100 | { current_token = $1; | |
101 | set_table_num($1); | |
102 | $$ = $1; } | |
103 | ; | |
104 | ||
105 | error_codes : error_codes ec_entry | |
106 | | ec_entry | |
107 | ; | |
108 | ||
109 | ec_entry : ERROR_CODE_ENTRY ec_name ',' description | |
110 | { add_ec($2, $4); | |
111 | free($2); | |
112 | free($4); } | |
113 | | ERROR_CODE_ENTRY ec_name '=' STRING ',' description | |
114 | { add_ec_val($2, $4, $6); | |
115 | free($2); | |
116 | free($4); | |
117 | free($6); | |
118 | } | |
119 | ; | |
120 | ||
121 | ec_name : STRING | |
122 | { $$ = strdup($1); | |
123 | current_token = $$; } | |
124 | ; | |
125 | ||
126 | description : QUOTED_STRING | |
127 | { $$ = strdup($1); | |
128 | current_token = $$; } | |
129 | ; | |
130 | ||
131 | %% | |
132 | ||
133 | /* | |
134 | * Copyright 2000, International Business Machines Corporation and others. | |
135 | * All Rights Reserved. | |
136 | * | |
137 | * This software has been released under the terms of the IBM Public | |
138 | * License. For details, see the LICENSE file in the top-level source | |
139 | * directory or online at http://www.openafs.org/dl/license10.html | |
140 | */ | |
141 | ||
142 | extern FILE *hfile, *cfile, *msfile; | |
143 | extern int use_msf; | |
144 | ||
145 | static afs_int32 gensym_n = 0; | |
146 | ||
147 | char *gensym(const char *x) | |
148 | { | |
149 | char *symbol; | |
150 | if (!gensym_n) { | |
151 | struct timeval tv; | |
152 | gettimeofday(&tv, (void *)0); | |
153 | gensym_n = (tv.tv_sec%10000)*100 + tv.tv_usec/10000; | |
154 | } | |
155 | symbol = malloc(32 * sizeof(char)); | |
156 | gensym_n++; | |
157 | sprintf(symbol, "et%ld", (long int) gensym_n); | |
158 | return(symbol); | |
159 | } | |
160 | ||
161 | char * | |
162 | quote(const char *string) | |
163 | { | |
164 | char *rv; | |
165 | rv = malloc(strlen(string)+3); | |
166 | strcpy(rv, "\""); | |
167 | strcat(rv, string); | |
168 | strcat(rv, "\""); | |
169 | return(rv); | |
170 | } | |
171 | ||
172 | afs_int32 table_number = 0; | |
173 | int current = 0; | |
174 | char **error_codes = NULL; | |
175 | ||
176 | void add_ec(const char *name, const char *description) | |
177 | { | |
178 | if (msfile) { | |
179 | if (current > 0) | |
180 | #ifndef sun | |
181 | fprintf(msfile, "%d\t%s\n", current, description); | |
182 | #else | |
183 | fprintf(msfile, "%d %s\n", current, description); | |
184 | #endif /* !sun */ | |
185 | } else if (cfile){ | |
186 | fprintf(cfile, "\t\"%s\",\n", description); | |
187 | } | |
188 | if (error_codes == NULL) { | |
189 | error_codes = malloc(sizeof(char *)); | |
190 | *error_codes = NULL; | |
191 | } | |
192 | error_codes = (char **)realloc((char *)error_codes, | |
193 | (current + 2)*sizeof(char *)); | |
194 | error_codes[current++] = strdup(name); | |
195 | error_codes[current] = NULL; | |
196 | } | |
197 | ||
198 | void add_ec_val(const char *name, const char *val, const char *description) | |
199 | { | |
200 | const int ncurrent = atoi(val); | |
201 | if (ncurrent < current) { | |
202 | printf("Error code %s (%d) out of order", name, | |
203 | current); | |
204 | return; | |
205 | } | |
206 | ||
207 | while (ncurrent > current) { | |
208 | if (cfile) | |
209 | fputs("\tNULL,\n", cfile); | |
210 | current++; | |
211 | } | |
212 | if (msfile) { | |
213 | if (current > 0) | |
214 | #ifndef sun | |
215 | fprintf(msfile, "%d\t%s\n", current, description); | |
216 | #else | |
217 | fprintf(msfile, "%d %s\n", current, description); | |
218 | #endif /* ! sun */ | |
219 | } else if (cfile) { | |
220 | fprintf(cfile, "\t\"%s\",\n", description); | |
221 | } | |
222 | if (error_codes == NULL) { | |
223 | error_codes = malloc(sizeof(char *)); | |
224 | *error_codes = NULL; | |
225 | } | |
226 | error_codes = (char **)realloc((char *)error_codes, | |
227 | (current + 2)*sizeof(char *)); | |
228 | error_codes[current++] = strdup(name); | |
229 | error_codes[current] = NULL; | |
230 | } | |
231 | ||
232 | void put_ecs(void) | |
233 | { | |
234 | int i; | |
235 | if (!hfile) | |
236 | return; | |
237 | for (i = 0; i < current; i++) { | |
238 | if (error_codes[i] != NULL) | |
239 | fprintf(hfile, "#define %-40s (%ldL)\n", | |
240 | error_codes[i], (long int) table_number + i); | |
241 | } | |
242 | } | |
243 | ||
244 | /* | |
245 | * char_to_num -- maps letters and numbers into a small numbering space | |
246 | * uppercase -> 1-26 | |
247 | * lowercase -> 27-52 | |
248 | * digits -> 53-62 | |
249 | * underscore-> 63 | |
250 | */ | |
251 | ||
252 | static const char char_set[] = | |
253 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; | |
254 | ||
255 | int char_to_num(char c) | |
256 | { | |
257 | const char *where; | |
258 | int diff; | |
259 | ||
260 | where = strchr (char_set, c); | |
261 | if (where) { | |
262 | diff = where - char_set + 1; | |
263 | assert (diff < (1 << ERRCODE_RANGE)); | |
264 | return diff; | |
265 | } | |
266 | else if (isprint (c)) | |
267 | fprintf (stderr, | |
268 | "Illegal character `%c' in error table name\n", | |
269 | c); | |
270 | else | |
271 | fprintf (stderr, | |
272 | "Illegal character %03o in error table name\n", | |
273 | c); | |
274 | exit (1); | |
275 | } | |
276 | ||
277 | void set_table_num(char *string) | |
278 | { | |
279 | if (use_msf) { | |
280 | set_table_1num(string); | |
281 | return; | |
282 | } | |
283 | if (strlen(string) > 4) { | |
284 | fprintf(stderr, "Table name %s too long, truncated ", | |
285 | string); | |
286 | string[4] = '\0'; | |
287 | fprintf(stderr, "to %s\n", string); | |
288 | } | |
289 | if (char_to_num (string[0]) > char_to_num ('z')) { | |
290 | fprintf (stderr, "%s%s%s%s", | |
291 | "First character of error table name must be ", | |
292 | "a letter; name ``", | |
293 | string, "'' rejected\n"); | |
294 | exit (1); | |
295 | } | |
296 | while (*string != '\0') { | |
297 | table_number = (table_number << BITS_PER_CHAR) | |
298 | + char_to_num(*string); | |
299 | string++; | |
300 | } | |
301 | table_number = table_number << ERRCODE_RANGE; | |
302 | } | |
303 | ||
304 | void set_table_fun(char *astring) | |
305 | { | |
306 | char *tp; | |
307 | unsigned int tc; | |
308 | ||
309 | for(tp=astring; (tc = *tp) != 0; tp++) { | |
310 | if (!isdigit(tc)) { | |
311 | fprintf(stderr, "Table function '%s' must be a decimal integer.\n", | |
312 | astring); | |
313 | exit(1); | |
314 | } | |
315 | } | |
316 | if (use_msf) | |
317 | table_number += (atoi(astring)) << 28; | |
318 | } | |
319 | ||
320 | /* for compatibility with old comerr's, we truncate package name to 4 | |
321 | * characters, but only store first 3 in the error code. Note that this | |
322 | * function, as a side effect, truncates the table name down to 4 chars. | |
323 | */ | |
324 | void set_table_1num(char *string) | |
325 | { | |
326 | afs_int32 temp; | |
327 | int ctr; | |
328 | ||
329 | if ((temp = strlen(string)) > 4) { | |
330 | fprintf(stderr, "Table name %s too long, truncated ", | |
331 | string); | |
332 | string[4] = '\0'; | |
333 | fprintf(stderr, "to %s\n", string); | |
334 | } | |
335 | if (temp == 4) { | |
336 | fprintf(stderr, "Table name %s too long, only 3 characters fit in error code.\n", | |
337 | string); | |
338 | } | |
339 | if (char_to_1num (string[0]) > char_to_1num ('z')) { | |
340 | fprintf (stderr, "%s%s%s%s", | |
341 | "First character of error table name must be ", | |
342 | "a letter; name ``", | |
343 | string, "'' rejected\n"); | |
344 | exit (1); | |
345 | } | |
346 | temp = 0; | |
347 | for(ctr=0; ctr < 3; ctr++) { /* copy at most 3 chars to integer */ | |
348 | if (*string == '\0') break; /* and watch for early end */ | |
349 | temp = (temp * 050) /* "radix fifty" is base 050 = 40 */ | |
350 | + char_to_1num(*string); | |
351 | string++; | |
352 | } | |
353 | table_number += temp << 12; | |
354 | } | |
355 | ||
356 | /* | |
357 | * char_to_num -- maps letters and numbers into very small space | |
358 | * 0-9 -> 0-9 | |
359 | * mixed case -> 10-35 | |
360 | * _ -> 36 | |
361 | * others are reserved | |
362 | */ | |
363 | ||
364 | static const char char_1set[] = | |
365 | "abcdefghijklmnopqrstuvwxyz_0123456789"; | |
366 | ||
367 | int char_to_1num(char c) | |
368 | { | |
369 | const char *where; | |
370 | int diff; | |
371 | ||
372 | if (isupper(c)) c = tolower(c); | |
373 | ||
374 | where = strchr (char_1set, c); | |
375 | if (where) { | |
376 | /* start at 1 so we can decode */ | |
377 | diff = where - char_1set; | |
378 | assert (diff < 050); /* it is radix 50, after all */ | |
379 | return diff; | |
380 | } | |
381 | else if (isprint (c)) | |
382 | fprintf (stderr, | |
383 | "Illegal character `%c' in error table name\n", | |
384 | c); | |
385 | else | |
386 | fprintf (stderr, | |
387 | "Illegal character %03o in error table name\n", | |
388 | c); | |
389 | exit (1); | |
390 | } | |
391 | ||
392 | #ifdef AFS_NT40_ENV | |
393 | #include "et_lex.lex_nt.c" | |
394 | #else | |
395 | #include "et_lex.lex.c" | |
396 | #endif |