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