aix-strings-h-preferred-over-string-h-20010628
[openafs.git] / src / rxgen / rpc_scan.c
1 /* @(#)rpc_scan.c       1.1 87/11/04 3.9 RPCSRC */
2 /*
3  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
4  * unrestricted use provided that this legend is included on all tape
5  * media and as a part of the software program in whole or part.  Users
6  * may copy or modify Sun RPC without charge, but are not authorized
7  * to license or distribute it to anyone else except as part of a product or
8  * program developed by the user.
9  * 
10  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
11  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13  * 
14  * Sun RPC is provided with no support and without any obligation on the
15  * part of Sun Microsystems, Inc. to assist in its use, correction,
16  * modification or enhancement.
17  * 
18  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
19  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
20  * OR ANY PART THEREOF.
21  * 
22  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
23  * or profits or other special, indirect and consequential damages, even if
24  * Sun has been advised of the possibility of such damages.
25  * 
26  * Sun Microsystems, Inc.
27  * 2550 Garcia Avenue
28  * Mountain View, California  94043
29  */
30
31 /*
32  * rpc_scan.c, Scanner for the RPC protocol compiler 
33  * Copyright (C) 1987, Sun Microsystems, Inc. 
34  */
35 #include <afs/param.h>
36 #include <afsconfig.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <ctype.h>
40 #ifdef HAVE_STRINGS_H
41 #include <strings.h>
42 #else
43 #ifdef HAVE_STRING_H
44 #include <string.h>
45 #endif
46 #endif
47 #include "rpc_scan.h"
48 #include "rpc_util.h"
49
50 RCSID("$Header$");
51
52 #define startcomment(where) (where[0] == '/' && where[1] == '*')
53 #define endcomment(where) (where[-1] == '*' && where[0] == '/')
54 #define verbatimstart(p) (*(p) == '@' && *((p) + 1) == '{')
55 #define verbatimend(p)  (*(p) == '@' && *((p) + 1) == '}')
56 int pushed = 0; /* is a token pushed */
57 token lasttok;  /* last token, if pushed */
58 int scan_print = 1;
59
60 static findstrconst();
61 static findconst();
62 static cppline();
63 static directive();
64 static docppline();
65
66 /*
67  * scan expecting 1 given token 
68  */
69 void
70 scan(expect, tokp)
71         tok_kind expect;
72         token *tokp;
73 {
74         get_token(tokp);
75         if (tokp->kind != expect) {
76                 expected1(expect);
77         }
78 }
79
80 /*
81  * scan expecting 2 given tokens 
82  */
83 void
84 scan2(expect1, expect2, tokp)
85         tok_kind expect1;
86         tok_kind expect2;
87         token *tokp;
88 {
89         get_token(tokp);
90         if (tokp->kind != expect1 && tokp->kind != expect2) {
91                 expected2(expect1, expect2);
92         }
93 }
94
95 /*
96  * scan expecting 3 given token 
97  */
98 void
99 scan3(expect1, expect2, expect3, tokp)
100         tok_kind expect1;
101         tok_kind expect2;
102         tok_kind expect3;
103         token *tokp;
104 {
105         get_token(tokp);
106         if (tokp->kind != expect1 && tokp->kind != expect2
107             && tokp->kind != expect3) {
108                 expected3(expect1, expect2, expect3);
109         }
110 }
111
112
113 /*
114  * scan expecting 4 given token
115  */
116 void
117 scan4(expect1,expect2,expect3,expect4,tokp)
118         tok_kind expect1;
119         tok_kind expect2;
120         tok_kind expect3;
121         tok_kind expect4;
122         token *tokp;
123 {
124         get_token(tokp);
125         if (tokp->kind != expect1 && tokp->kind != expect2 
126             && tokp->kind != expect3 && tokp->kind != expect4) {
127                 expected4(expect1,expect2,expect3,expect4);
128         }
129 }
130
131 /*
132  * scan expecting a constant, possibly symbolic 
133  */
134 void
135 scan_num(tokp)
136         token *tokp;
137 {
138         get_token(tokp);
139         switch (tokp->kind) {
140         case TOK_IDENT:
141                 break;
142         default:
143                 error("constant or identifier expected");
144         }
145 }
146
147
148 /*
149  * Peek at the next token 
150  */
151 void
152 peek(tokp)
153         token *tokp;
154 {
155         get_token(tokp);
156         unget_token(tokp);
157 }
158
159
160 /*
161  * Peek at the next token and scan it if it matches what you expect 
162  */
163 int
164 peekscan(expect, tokp)
165         tok_kind expect;
166         token *tokp;
167 {
168         peek(tokp);
169         if (tokp->kind == expect) {
170                 get_token(tokp);
171                 return (1);
172         }
173         return (0);
174 }
175
176
177
178 /*
179  * Get the next token, printing out any directive that are encountered. 
180  */
181 void
182 get_token(tokp)
183         token *tokp;
184 {
185         int commenting;
186         int verbatim = 0;
187
188         if (pushed) {
189                 pushed = 0;
190                 *tokp = lasttok;
191                 return;
192         }
193         commenting = 0;
194         for (;;) {
195                 if (*where == 0) {
196                         for (;;) {
197                                 if (!fgets(curline, MAXLINESIZE, fin)) {
198                                         tokp->kind = TOK_EOF;
199                                         *where = 0;
200                                         return;
201                                 }
202                                 linenum++;
203                                 if (verbatim) {
204                                     fputs(curline, fout);
205                                     break;
206                                 }
207                                 if (commenting) {
208                                         break;
209                                 } else if (cppline(curline)) {
210                                         docppline(curline, &linenum, 
211                                                   &infilename);
212                                 } else if (directive(curline)) {
213                                         printdirective(curline);
214                                 } else {
215                                         break;
216                                 }
217                         }
218                         where = curline;
219                 } else if (isspace(*where)) {
220                         while (isspace(*where)) {
221                                 where++;        /* eat */
222                         }
223                 } else if (verbatim) {
224                       where++;
225                       if (verbatimend(where)) {
226                           where++;
227                           verbatim--;
228                       }
229                 } else if (verbatimstart(where)) {
230                     where += 2;
231                     verbatim++;
232                 } else if (commenting) {
233                         where++;
234                         if (endcomment(where)) {
235                                 where++;
236                                 commenting--;
237                         }
238                 } else if (startcomment(where)) {
239                         where += 2;
240                         commenting++;
241                 } else {
242                         break;
243                 }
244         }
245
246         /*
247          * 'where' is not whitespace, comment or directive Must be a token! 
248          */
249         switch (*where) {
250         case ':':
251                 tokp->kind = TOK_COLON;
252                 where++;
253                 break;
254         case ';':
255                 tokp->kind = TOK_SEMICOLON;
256                 where++;
257                 break;
258         case ',':
259                 tokp->kind = TOK_COMMA;
260                 where++;
261                 break;
262         case '=':
263                 tokp->kind = TOK_EQUAL;
264                 where++;
265                 break;
266         case '*':
267                 tokp->kind = TOK_STAR;
268                 where++;
269                 break;
270         case '[':
271                 tokp->kind = TOK_LBRACKET;
272                 where++;
273                 break;
274         case ']':
275                 tokp->kind = TOK_RBRACKET;
276                 where++;
277                 break;
278         case '{':
279                 tokp->kind = TOK_LBRACE;
280                 where++;
281                 break;
282         case '}':
283                 tokp->kind = TOK_RBRACE;
284                 where++;
285                 break;
286         case '(':
287                 tokp->kind = TOK_LPAREN;
288                 where++;
289                 break;
290         case ')':
291                 tokp->kind = TOK_RPAREN;
292                 where++;
293                 break;
294         case '<':
295                 tokp->kind = TOK_LANGLE;
296                 where++;
297                 break;
298         case '>':
299                 tokp->kind = TOK_RANGLE;
300                 where++;
301                 break;
302
303         case '"':
304                 tokp->kind = TOK_STRCONST;
305                 findstrconst(&where, &tokp->str);
306                 break;
307
308         case '-':
309         case '0':
310         case '1':
311         case '2':
312         case '3':
313         case '4':
314         case '5':
315         case '6':
316         case '7':
317         case '8':
318         case '9':
319                 tokp->kind = TOK_IDENT;
320                 findconst(&where, &tokp->str);
321                 break;
322
323
324         default:
325                 if (!(isalpha(*where) || *where == '_')) {
326                         char buf[100];
327                         char *p;
328
329                         s_print(buf, "illegal character in file: ");
330                         p = buf + strlen(buf);
331                         if (isprint(*where)) {
332                                 s_print(p, "%c", *where);
333                         } else {
334                                 s_print(p, "%d", *where);
335                         }
336                         error(buf);
337                 }
338                 findkind(&where, tokp);
339                 break;
340         }
341 }
342
343
344 unget_token(tokp)
345         token *tokp;
346 {
347         lasttok = *tokp;
348         pushed = 1;
349 }
350
351
352 static
353 findstrconst(str, val)
354         char **str;
355         char **val;
356 {
357         char *p;
358         int size;
359
360         p = *str;
361         do {
362                 *p++;
363         } while (*p && *p != '"');
364         if (*p == 0) {
365                 error("unterminated string constant");
366         }
367         p++;
368         size = p - *str;
369         *val = alloc(size + 1);
370         (void) strncpy(*val, *str, size);
371         (*val)[size] = 0;
372         *str = p;
373 }
374
375 static
376 findconst(str, val)
377         char **str;
378         char **val;
379 {
380         char *p;
381         int size;
382
383         p = *str;
384         if (*p == '0' && *(p + 1) == 'x') {
385                 p++;
386                 do {
387                         p++;
388                 } while (isxdigit(*p));
389         } else {
390                 do {
391                         p++;
392                 } while (isdigit(*p));
393         }
394         size = p - *str;
395         *val = alloc(size + 1);
396         (void) strncpy(*val, *str, size);
397         (*val)[size] = 0;
398         *str = p;
399 }
400
401
402
403 static token symbols[] = {
404                           {TOK_CONST, "const"},
405                           {TOK_UNION, "union"},
406                           {TOK_SWITCH, "switch"},
407                           {TOK_CASE, "case"},
408                           {TOK_DEFAULT, "default"},
409                           {TOK_STRUCT, "struct"},
410                           {TOK_TYPEDEF, "typedef"},
411                           {TOK_ENUM, "enum"},
412                           {TOK_OPAQUE, "opaque"},
413                           {TOK_BOOL, "bool"},
414                           {TOK_VOID, "void"},
415                           {TOK_CHAR, "char"},
416                           {TOK_INT, "int"},
417                           {TOK_UNSIGNED, "unsigned"},
418                           {TOK_SHORT, "short"},
419                           {TOK_INT32, "afs_int32"},
420                           {TOK_FLOAT, "float"},
421                           {TOK_DOUBLE, "double"},
422                           {TOK_STRING, "string"},
423                           {TOK_PROGRAM, "program"},
424                           {TOK_VERSION, "version"},
425                           { TOK_PACKAGE, "package" },
426                           { TOK_PREFIX, "prefix" },
427                           { TOK_STATINDEX, "statindex" },
428                           { TOK_SPECIAL, "special" },
429                           { TOK_STARTINGOPCODE, "startingopcode" },
430                           { TOK_CUSTOMIZED, "customized" },
431                           { TOK_PROC, "proc" },
432                           { TOK_SPLITPREFIX, "splitprefix" },
433                           { TOK_SPLIT, "split" },
434                           { TOK_MULTI, "multi" },
435                           { TOK_IN,   "IN" },
436                           { TOK_OUT,  "OUT" },
437                           { TOK_INOUT, "INOUT" },
438                           { TOK_AFSUUID, "afsUUID" },
439                           {TOK_EOF, "??????"},
440 };
441
442
443 findkind(mark, tokp)
444         char **mark;
445         token *tokp;
446 {
447
448         int len;
449         token *s;
450         char *str;
451
452         str = *mark;
453         for (s = symbols; s->kind != TOK_EOF; s++) {
454                 len = strlen(s->str);
455                 if (strncmp(str, s->str, len) == 0) {
456                         if (!isalnum(str[len]) && str[len] != '_') {
457                                 tokp->kind = s->kind;
458                                 tokp->str = s->str;
459                                 *mark = str + len;
460                                 return;
461                         }
462                 }
463         }
464         tokp->kind = TOK_IDENT;
465         for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
466         tokp->str = alloc(len + 1);
467         (void) strncpy(tokp->str, str, len);
468         tokp->str[len] = 0;
469         *mark = str + len;
470 }
471
472 static
473 cppline(line)
474         char *line;
475 {
476         return (line == curline && *line == '#');
477 }
478
479 static
480 directive(line)
481         char *line;
482 {
483         return (line == curline && *line == '%');
484 }
485
486 printdirective(line)
487         char *line;
488 {
489         f_print(fout, "%s", line + 1);
490 }
491
492 static
493 docppline(line, lineno, fname)
494         char *line;
495         int *lineno;
496         char **fname;
497 {
498         char *file;
499         int num;
500         char *p;
501
502         line++;
503         while (isspace(*line)) {
504                 line++;
505         }
506         num = atoi(line);
507         while (isdigit(*line)) {
508                 line++;
509         }
510         while (isspace(*line)) {
511                 line++;
512         }
513 #ifdef  AFS_HPUX_ENV
514         if (*line == '\0') {
515             *fname = NULL;
516             *lineno = num - 1;
517             return;
518         }
519 #endif
520         if (*line != '"') {
521 #ifdef  AFS_AIX41_ENV
522             if (!strncmp(line, "line", 4)) {
523                 while (*line) 
524                     *line++;
525                 *fname = NULL;
526                 *lineno = num - 1;
527                 return;
528             }
529 #endif
530                 error("preprocessor error");
531         }
532         line++;
533         p = file = alloc(strlen(line) + 1);
534         while (*line && *line != '"') {
535                 *p++ = *line++;
536         }
537         if (*line == 0) {
538                 error("preprocessor error");
539         }
540         *p = 0;
541         if (*file == 0) {
542                 *fname = NULL;
543         } else {
544                 *fname = file;
545         }
546         *lineno = num - 1;
547 }
548
549
550 static
551 deverbatim()
552 {
553     for (where += 2; ! verbatimend(where) ; where++) {   
554         if (*where == 0) {
555             if (! fgets(curline, MAXLINESIZE, fin)) {
556                 error("unterminated code: %} is missing");
557             }
558             linenum++;
559             where = curline - 1;
560             if (verbatimend(curline)) {
561                 where++;
562                 break;
563             }
564             fputs(curline, fout);
565         }
566     }
567     where += 2;
568 }