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