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