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