Fix warnings in comerr directory
[openafs.git] / src / comerr / error_table.y
1 %{
2 #include <afsconfig.h>
3 #include <afs/param.h>
4
5 /*
6  *
7  * Copyright 1986, 1987 by the MIT Student Information Processing Board
8  *
9  * For copyright info, see mit-sipb-cr.h.
10  */
11 #ifndef AFS_NT40_ENV
12 #include <unistd.h>
13 #endif
14 #include <string.h>
15 #include <assert.h>
16 #include <ctype.h>
17 #ifdef AFS_NT40_ENV
18 #include <sys/types.h>
19 #include <afs/afsutil.h>
20 #else
21 #include <sys/time.h>
22 #endif
23 #include <sys/timeb.h>
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 = (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 extern int yylex (void);
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 /* 
135  * Copyright 2000, International Business Machines Corporation and others.
136  * All Rights Reserved.
137  * 
138  * This software has been released under the terms of the IBM Public
139  * License.  For details, see the LICENSE file in the top-level source
140  * directory or online at http://www.openafs.org/dl/license10.html
141  */
142
143 extern FILE *hfile, *cfile, *msfile;
144 extern int use_msf;
145
146 static afs_int32 gensym_n = 0;
147
148 char *gensym(const char *x)
149 {
150         char *symbol;
151         if (!gensym_n) {
152                 struct timeval tv;
153                 gettimeofday(&tv, (void *)0);
154                 gensym_n = (tv.tv_sec%10000)*100 + tv.tv_usec/10000;
155         }
156         symbol = (char *)malloc(32 * sizeof(char));
157         gensym_n++;
158         sprintf(symbol, "et%ld", (long int) gensym_n);
159         return(symbol);
160 }
161
162 char *
163 ds(const char *string)
164 {
165         char *rv;
166         rv = (char *)malloc(strlen(string)+1);
167         strcpy(rv, string);
168         return(rv);
169 }
170
171 char *
172 quote(const char *string)
173 {
174         char *rv;
175         rv = (char *)malloc(strlen(string)+3);
176         strcpy(rv, "\"");
177         strcat(rv, string);
178         strcat(rv, "\"");
179         return(rv);
180 }
181
182 afs_int32 table_number = 0;
183 int current = 0;
184 char **error_codes = (char **)NULL;
185
186 void add_ec(const char *name, const char *description)
187 {
188         if (msfile) {
189             if (current > 0)
190 #ifndef sun
191                 fprintf(msfile, "%d\t%s\n", current, description);
192 #else
193                 fprintf(msfile, "%d %s\n", current, description);
194 #endif /* !sun */
195         } else {
196             fprintf(cfile, "\t\"%s\",\n", description);
197         }
198         if (error_codes == (char **)NULL) {
199                 error_codes = (char **)malloc(sizeof(char *));
200                 *error_codes = (char *)NULL;
201         }
202         error_codes = (char **)realloc((char *)error_codes,
203                                        (current + 2)*sizeof(char *));
204         error_codes[current++] = ds(name);
205         error_codes[current] = (char *)NULL;
206 }
207
208 void add_ec_val(const char *name, const char *val, const char *description)
209 {
210         const int ncurrent = atoi(val);
211         if (ncurrent < current) {
212                 printf("Error code %s (%d) out of order", name,
213                        current);
214                 return;
215         }
216       
217         while (ncurrent > current) {
218              if (!msfile)
219                  fputs("\t(char *)NULL,\n", cfile);
220              current++;
221          }
222         if (msfile) {
223             if (current > 0)
224 #ifndef sun
225                 fprintf(msfile, "%d\t%s\n", current, description);
226 #else
227                 fprintf(msfile, "%d %s\n", current, description);
228 #endif /* ! sun */
229         } else {        
230             fprintf(cfile, "\t\"%s\",\n", description);
231         }
232         if (error_codes == (char **)NULL) {
233                 error_codes = (char **)malloc(sizeof(char *));
234                 *error_codes = (char *)NULL;
235         }
236         error_codes = (char **)realloc((char *)error_codes,
237                                        (current + 2)*sizeof(char *));
238         error_codes[current++] = ds(name);
239         error_codes[current] = (char *)NULL;
240
241
242 void put_ecs(void)
243 {
244         int i;
245         for (i = 0; i < current; i++) {
246              if (error_codes[i] != (char *)NULL)
247                   fprintf(hfile, "#define %-40s (%ldL)\n",
248                           error_codes[i], (long int) table_number + i);
249         }
250 }
251
252 /*
253  * char_to_num -- maps letters and numbers into a small numbering space
254  *      uppercase ->  1-26
255  *      lowercase -> 27-52
256  *      digits    -> 53-62
257  *      underscore-> 63
258  */
259
260 static const char char_set[] =
261         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
262
263 int char_to_num(char c)
264 {
265         const char *where;
266         int diff;
267
268         where = strchr (char_set, c);
269         if (where) {
270                 diff = where - char_set + 1;
271                 assert (diff < (1 << ERRCODE_RANGE));
272                 return diff;
273         }
274         else if (isprint (c))
275                 fprintf (stderr,
276                          "Illegal character `%c' in error table name\n",
277                          c);
278         else
279                 fprintf (stderr,
280                          "Illegal character %03o in error table name\n",
281                          c);
282         exit (1);
283 }
284
285 void set_table_num(char *string)
286 {
287         if (msfile) {
288             set_table_1num(string);
289             return;
290         }
291         if (strlen(string) > 4) {
292                 fprintf(stderr, "Table name %s too long, truncated ",
293                         string);
294                 string[4] = '\0';
295                 fprintf(stderr, "to %s\n", string);
296         }
297         if (char_to_num (string[0]) > char_to_num ('z')) {
298                 fprintf (stderr, "%s%s%s%s",
299                          "First character of error table name must be ",
300                          "a letter; name ``",
301                          string, "'' rejected\n");
302                 exit (1);
303         }
304         while (*string != '\0') {
305                 table_number = (table_number << BITS_PER_CHAR)
306                         + char_to_num(*string);
307                 string++;
308         }
309         table_number = table_number << ERRCODE_RANGE;
310 }
311
312 void set_table_fun(char *astring)
313 {
314     register char *tp;
315     unsigned int tc;
316
317     for(tp=astring; (tc = *tp) != 0; tp++) {
318         if (!isdigit(tc)) {
319             fprintf(stderr, "Table function '%s' must be a decimal integer.\n",
320                     astring);
321             exit(1);
322         }
323     }
324     if (msfile) 
325         table_number += (atoi(astring)) << 28;
326 }
327
328 /* for compatibility with old comerr's, we truncate package name to 4
329  * characters, but only store first 3 in the error code.  Note that this
330  * function, as a side effect, truncates the table name down to 4 chars.
331  */
332 void set_table_1num(char *string)
333 {
334         afs_int32 temp;
335         int ctr;
336
337         if ((temp = strlen(string)) > 4) {
338                 fprintf(stderr, "Table name %s too long, truncated ",
339                         string);
340                 string[4] = '\0';
341                 fprintf(stderr, "to %s\n", string);
342         }
343         if (temp == 4) {
344             fprintf(stderr, "Table name %s too long, only 3 characters fit in error code.\n",
345                     string);
346         }
347         if (char_to_1num (string[0]) > char_to_1num ('z')) {
348                 fprintf (stderr, "%s%s%s%s",
349                          "First character of error table name must be ",
350                          "a letter; name ``",
351                          string, "'' rejected\n");
352                 exit (1);
353         }
354         temp = 0;
355         for(ctr=0; ctr < 3; ctr++) {            /* copy at most 3 chars to integer */
356             if (*string == '\0') break;         /* and watch for early end */
357             temp = (temp * 050)                 /* "radix fifty" is base 050 = 40 */
358                 + char_to_1num(*string);
359             string++;
360         }
361         table_number += temp << 12;
362 }
363
364 /*
365  * char_to_num -- maps letters and numbers into very small space
366  *      0-9        -> 0-9
367  *      mixed case -> 10-35
368  *      _          -> 36
369  *      others are reserved
370  */
371
372 static const char char_1set[] =
373         "abcdefghijklmnopqrstuvwxyz_0123456789";
374
375 int char_to_1num(char c)
376 {
377         const char *where;
378         int diff;
379
380         if (isupper(c)) c = tolower(c);
381
382         where = strchr (char_1set, c);
383         if (where) {
384                 /* start at 1 so we can decode */
385                 diff = where - char_1set;
386                 assert (diff < 050);    /* it is radix 50, after all */
387                 return diff;
388         }
389         else if (isprint (c))
390                 fprintf (stderr,
391                          "Illegal character `%c' in error table name\n",
392                          c);
393         else
394                 fprintf (stderr,
395                          "Illegal character %03o in error table name\n",
396                          c);
397         exit (1);
398 }
399
400 #ifdef AFS_NT40_ENV
401 #include "et_lex.lex_nt.c"
402 #else
403 #include "et_lex.lex.c"
404 #endif