Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / comerr / error_table.y
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