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