afs: casting NULL is generally unnecessary
[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 = 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 {
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 (!msfile)
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 {        
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         for (i = 0; i < current; i++) {
236              if (error_codes[i] != NULL)
237                   fprintf(hfile, "#define %-40s (%ldL)\n",
238                           error_codes[i], (long int) table_number + i);
239         }
240 }
241
242 /*
243  * char_to_num -- maps letters and numbers into a small numbering space
244  *      uppercase ->  1-26
245  *      lowercase -> 27-52
246  *      digits    -> 53-62
247  *      underscore-> 63
248  */
249
250 static const char char_set[] =
251         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
252
253 int char_to_num(char c)
254 {
255         const char *where;
256         int diff;
257
258         where = strchr (char_set, c);
259         if (where) {
260                 diff = where - char_set + 1;
261                 assert (diff < (1 << ERRCODE_RANGE));
262                 return diff;
263         }
264         else if (isprint (c))
265                 fprintf (stderr,
266                          "Illegal character `%c' in error table name\n",
267                          c);
268         else
269                 fprintf (stderr,
270                          "Illegal character %03o in error table name\n",
271                          c);
272         exit (1);
273 }
274
275 void set_table_num(char *string)
276 {
277         if (msfile) {
278             set_table_1num(string);
279             return;
280         }
281         if (strlen(string) > 4) {
282                 fprintf(stderr, "Table name %s too long, truncated ",
283                         string);
284                 string[4] = '\0';
285                 fprintf(stderr, "to %s\n", string);
286         }
287         if (char_to_num (string[0]) > char_to_num ('z')) {
288                 fprintf (stderr, "%s%s%s%s",
289                          "First character of error table name must be ",
290                          "a letter; name ``",
291                          string, "'' rejected\n");
292                 exit (1);
293         }
294         while (*string != '\0') {
295                 table_number = (table_number << BITS_PER_CHAR)
296                         + char_to_num(*string);
297                 string++;
298         }
299         table_number = table_number << ERRCODE_RANGE;
300 }
301
302 void set_table_fun(char *astring)
303 {
304     char *tp;
305     unsigned int tc;
306
307     for(tp=astring; (tc = *tp) != 0; tp++) {
308         if (!isdigit(tc)) {
309             fprintf(stderr, "Table function '%s' must be a decimal integer.\n",
310                     astring);
311             exit(1);
312         }
313     }
314     if (msfile) 
315         table_number += (atoi(astring)) << 28;
316 }
317
318 /* for compatibility with old comerr's, we truncate package name to 4
319  * characters, but only store first 3 in the error code.  Note that this
320  * function, as a side effect, truncates the table name down to 4 chars.
321  */
322 void set_table_1num(char *string)
323 {
324         afs_int32 temp;
325         int ctr;
326
327         if ((temp = strlen(string)) > 4) {
328                 fprintf(stderr, "Table name %s too long, truncated ",
329                         string);
330                 string[4] = '\0';
331                 fprintf(stderr, "to %s\n", string);
332         }
333         if (temp == 4) {
334             fprintf(stderr, "Table name %s too long, only 3 characters fit in error code.\n",
335                     string);
336         }
337         if (char_to_1num (string[0]) > char_to_1num ('z')) {
338                 fprintf (stderr, "%s%s%s%s",
339                          "First character of error table name must be ",
340                          "a letter; name ``",
341                          string, "'' rejected\n");
342                 exit (1);
343         }
344         temp = 0;
345         for(ctr=0; ctr < 3; ctr++) {            /* copy at most 3 chars to integer */
346             if (*string == '\0') break;         /* and watch for early end */
347             temp = (temp * 050)                 /* "radix fifty" is base 050 = 40 */
348                 + char_to_1num(*string);
349             string++;
350         }
351         table_number += temp << 12;
352 }
353
354 /*
355  * char_to_num -- maps letters and numbers into very small space
356  *      0-9        -> 0-9
357  *      mixed case -> 10-35
358  *      _          -> 36
359  *      others are reserved
360  */
361
362 static const char char_1set[] =
363         "abcdefghijklmnopqrstuvwxyz_0123456789";
364
365 int char_to_1num(char c)
366 {
367         const char *where;
368         int diff;
369
370         if (isupper(c)) c = tolower(c);
371
372         where = strchr (char_1set, c);
373         if (where) {
374                 /* start at 1 so we can decode */
375                 diff = where - char_1set;
376                 assert (diff < 050);    /* it is radix 50, after all */
377                 return diff;
378         }
379         else if (isprint (c))
380                 fprintf (stderr,
381                          "Illegal character `%c' in error table name\n",
382                          c);
383         else
384                 fprintf (stderr,
385                          "Illegal character %03o in error table name\n",
386                          c);
387         exit (1);
388 }
389
390 #ifdef AFS_NT40_ENV
391 #include "et_lex.lex_nt.c"
392 #else
393 #include "et_lex.lex.c"
394 #endif