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