Annotation of src/usr.bin/rpcgen/rpc_scan.c, Revision 1.16
1.16 ! deraadt 1: /* $OpenBSD: rpc_scan.c,v 1.15 2010/09/01 14:43:34 millert Exp $ */
1.1 deraadt 2: /* $NetBSD: rpc_scan.c,v 1.4 1995/06/11 21:50:02 pk Exp $ */
1.15 millert 3:
1.1 deraadt 4: /*
1.15 millert 5: * Copyright (c) 2010, Oracle America, Inc.
1.1 deraadt 6: *
1.15 millert 7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions are
9: * met:
1.1 deraadt 10: *
1.15 millert 11: * * Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * * Redistributions in binary form must reproduce the above
14: * copyright notice, this list of conditions and the following
15: * disclaimer in the documentation and/or other materials
16: * provided with the distribution.
17: * * Neither the name of the "Oracle America, Inc." nor the names of its
18: * contributors may be used to endorse or promote products derived
19: * from this software without specific prior written permission.
1.1 deraadt 20: *
1.15 millert 21: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24: * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25: * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1 deraadt 33: */
34:
35: /*
1.7 deraadt 36: * rpc_scan.c, Scanner for the RPC protocol compiler
1.1 deraadt 37: */
38: #include <stdlib.h>
39: #include <stdio.h>
40: #include <ctype.h>
41: #include <string.h>
42: #include "rpc_scan.h"
43: #include "rpc_parse.h"
44: #include "rpc_util.h"
45:
1.10 deraadt 46: static void unget_token(token *tokp);
47: static void findstrconst(char **, char **);
48: static void findchrconst(char **, char **);
49: static void findconst(char **, char **);
50: static void findkind(char **, token *);
51: static int cppline(char *);
52: static int directive(char *);
53: static void printdirective(char *);
54: static void docppline(char *, int *, char **);
1.1 deraadt 55:
56: #define startcomment(where) (where[0] == '/' && where[1] == '*')
57: #define endcomment(where) (where[-1] == '*' && where[0] == '/')
58:
59: static int pushed = 0; /* is a token pushed */
60: static token lasttok; /* last token, if pushed */
61:
62: /*
1.7 deraadt 63: * scan expecting 1 given token
1.1 deraadt 64: */
65: void
66: scan(expect, tokp)
67: tok_kind expect;
68: token *tokp;
69: {
70: get_token(tokp);
1.7 deraadt 71: if (tokp->kind != expect)
1.1 deraadt 72: expected1(expect);
73: }
74:
75: /*
1.7 deraadt 76: * scan expecting any of the 2 given tokens
1.1 deraadt 77: */
78: void
79: scan2(expect1, expect2, tokp)
80: tok_kind expect1;
81: tok_kind expect2;
82: token *tokp;
83: {
84: get_token(tokp);
1.7 deraadt 85: if (tokp->kind != expect1 && tokp->kind != expect2)
1.1 deraadt 86: expected2(expect1, expect2);
87: }
88:
89: /*
1.7 deraadt 90: * scan expecting any of the 3 given token
1.1 deraadt 91: */
92: void
93: scan3(expect1, expect2, expect3, tokp)
94: tok_kind expect1;
95: tok_kind expect2;
96: tok_kind expect3;
97: token *tokp;
98: {
99: get_token(tokp);
1.7 deraadt 100: if (tokp->kind != expect1 && tokp->kind != expect2 &&
101: tokp->kind != expect3)
1.1 deraadt 102: expected3(expect1, expect2, expect3);
103: }
104:
105: /*
1.7 deraadt 106: * scan expecting a constant, possibly symbolic
1.1 deraadt 107: */
108: void
109: scan_num(tokp)
110: token *tokp;
111: {
112: get_token(tokp);
113: switch (tokp->kind) {
114: case TOK_IDENT:
115: break;
116: default:
117: error("constant or identifier expected");
118: }
119: }
120:
121: /*
1.7 deraadt 122: * Peek at the next token
1.1 deraadt 123: */
124: void
125: peek(tokp)
126: token *tokp;
127: {
128: get_token(tokp);
129: unget_token(tokp);
130: }
131:
132: /*
1.7 deraadt 133: * Peek at the next token and scan it if it matches what you expect
1.1 deraadt 134: */
135: int
136: peekscan(expect, tokp)
137: tok_kind expect;
138: token *tokp;
139: {
140: peek(tokp);
141: if (tokp->kind == expect) {
142: get_token(tokp);
143: return (1);
144: }
145: return (0);
146: }
147:
148: /*
1.7 deraadt 149: * Get the next token, printing out any directive that are encountered.
1.1 deraadt 150: */
151: void
152: get_token(tokp)
153: token *tokp;
154: {
155: int commenting;
156:
157: if (pushed) {
158: pushed = 0;
159: *tokp = lasttok;
160: return;
161: }
162: commenting = 0;
163: for (;;) {
164: if (*where == 0) {
165: for (;;) {
166: if (!fgets(curline, MAXLINESIZE, fin)) {
167: tokp->kind = TOK_EOF;
168: *where = 0;
169: return;
170: }
171: linenum++;
172: if (commenting) {
173: break;
174: } else if (cppline(curline)) {
1.7 deraadt 175: docppline(curline, &linenum,
176: &infilename);
1.1 deraadt 177: } else if (directive(curline)) {
178: printdirective(curline);
179: } else {
180: break;
181: }
182: }
183: where = curline;
184: } else if (isspace(*where)) {
185: while (isspace(*where)) {
186: where++; /* eat */
187: }
188: } else if (commenting) {
189: for (where++; *where; where++) {
190: if (endcomment(where)) {
191: where++;
192: commenting--;
193: break;
194: }
195: }
196: } else if (startcomment(where)) {
197: where += 2;
198: commenting++;
199: } else {
200: break;
201: }
202: }
203:
204: /*
1.7 deraadt 205: * 'where' is not whitespace, comment or directive Must be a token!
1.1 deraadt 206: */
207: switch (*where) {
208: case ':':
209: tokp->kind = TOK_COLON;
210: where++;
211: break;
212: case ';':
213: tokp->kind = TOK_SEMICOLON;
214: where++;
215: break;
216: case ',':
217: tokp->kind = TOK_COMMA;
218: where++;
219: break;
220: case '=':
221: tokp->kind = TOK_EQUAL;
222: where++;
223: break;
224: case '*':
225: tokp->kind = TOK_STAR;
226: where++;
227: break;
228: case '[':
229: tokp->kind = TOK_LBRACKET;
230: where++;
231: break;
232: case ']':
233: tokp->kind = TOK_RBRACKET;
234: where++;
235: break;
236: case '{':
237: tokp->kind = TOK_LBRACE;
238: where++;
239: break;
240: case '}':
241: tokp->kind = TOK_RBRACE;
242: where++;
243: break;
244: case '(':
245: tokp->kind = TOK_LPAREN;
246: where++;
247: break;
248: case ')':
249: tokp->kind = TOK_RPAREN;
250: where++;
251: break;
252: case '<':
253: tokp->kind = TOK_LANGLE;
254: where++;
255: break;
256: case '>':
257: tokp->kind = TOK_RANGLE;
258: where++;
259: break;
260:
261: case '"':
262: tokp->kind = TOK_STRCONST;
263: findstrconst(&where, &tokp->str);
264: break;
265: case '\'':
266: tokp->kind = TOK_CHARCONST;
267: findchrconst(&where, &tokp->str);
268: break;
269:
270: case '-':
271: case '0':
272: case '1':
273: case '2':
274: case '3':
275: case '4':
276: case '5':
277: case '6':
278: case '7':
279: case '8':
280: case '9':
281: tokp->kind = TOK_IDENT;
282: findconst(&where, &tokp->str);
283: break;
284:
285: default:
286: if (!(isalpha(*where) || *where == '_')) {
1.11 deraadt 287: char buf[100], chs[20];
1.1 deraadt 288:
289: if (isprint(*where)) {
1.11 deraadt 290: snprintf(chs, sizeof chs, "%c", *where);
1.1 deraadt 291: } else {
1.11 deraadt 292: snprintf(chs, sizeof chs, "%d", *where);
1.1 deraadt 293: }
1.11 deraadt 294:
295: snprintf(buf, sizeof buf,
296: "illegal character in file: %s", chs);
1.1 deraadt 297: error(buf);
298: }
299: findkind(&where, tokp);
300: break;
301: }
302: }
303:
1.10 deraadt 304: static void
1.1 deraadt 305: unget_token(tokp)
306: token *tokp;
307: {
308: lasttok = *tokp;
309: pushed = 1;
310: }
311:
1.10 deraadt 312: static void
1.1 deraadt 313: findstrconst(str, val)
314: char **str;
315: char **val;
316: {
317: char *p;
318: int size;
319:
320: p = *str;
321: do {
1.10 deraadt 322: p++;
1.1 deraadt 323: } while (*p && *p != '"');
324: if (*p == 0) {
325: error("unterminated string constant");
326: }
327: p++;
328: size = p - *str;
329: *val = alloc(size + 1);
1.10 deraadt 330: if (val == NULL)
331: error("alloc failed");
1.1 deraadt 332: (void) strncpy(*val, *str, size);
333: (*val)[size] = 0;
334: *str = p;
335: }
336:
1.10 deraadt 337: static void
1.1 deraadt 338: findchrconst(str, val)
339: char **str;
340: char **val;
341: {
342: char *p;
343: int size;
344:
345: p = *str;
346: do {
1.10 deraadt 347: p++;
1.1 deraadt 348: } while (*p && *p != '\'');
349: if (*p == 0) {
350: error("unterminated string constant");
351: }
352: p++;
353: size = p - *str;
354: if (size != 3) {
355: error("empty char string");
356: }
357: *val = alloc(size + 1);
1.10 deraadt 358: if (val == NULL)
359: error("alloc failed");
1.1 deraadt 360: (void) strncpy(*val, *str, size);
361: (*val)[size] = 0;
362: *str = p;
363: }
364:
1.10 deraadt 365: static void
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);
1.10 deraadt 386: if (val == NULL)
387: error("alloc failed");
1.1 deraadt 388: (void) strncpy(*val, *str, size);
389: (*val)[size] = 0;
390: *str = p;
391: }
392:
393: static token symbols[] = {
1.7 deraadt 394: {TOK_CONST, "const"},
395: {TOK_UNION, "union"},
396: {TOK_SWITCH, "switch"},
397: {TOK_CASE, "case"},
398: {TOK_DEFAULT, "default"},
399: {TOK_STRUCT, "struct"},
400: {TOK_TYPEDEF, "typedef"},
401: {TOK_ENUM, "enum"},
402: {TOK_OPAQUE, "opaque"},
403: {TOK_BOOL, "bool"},
404: {TOK_VOID, "void"},
405: {TOK_CHAR, "char"},
406: {TOK_INT, "int"},
407: {TOK_UNSIGNED, "unsigned"},
408: {TOK_SHORT, "short"},
409: {TOK_LONG, "long"},
410: {TOK_FLOAT, "float"},
411: {TOK_DOUBLE, "double"},
412: {TOK_STRING, "string"},
413: {TOK_PROGRAM, "program"},
414: {TOK_VERSION, "version"},
415: {TOK_EOF, "??????"},
1.1 deraadt 416: };
417:
1.10 deraadt 418: static void
1.1 deraadt 419: findkind(mark, tokp)
420: char **mark;
421: token *tokp;
422: {
423: int len;
424: token *s;
425: char *str;
426:
427: str = *mark;
428: for (s = symbols; s->kind != TOK_EOF; s++) {
429: len = strlen(s->str);
430: if (strncmp(str, s->str, len) == 0) {
431: if (!isalnum(str[len]) && str[len] != '_') {
432: tokp->kind = s->kind;
433: tokp->str = s->str;
434: *mark = str + len;
435: return;
436: }
437: }
438: }
439: tokp->kind = TOK_IDENT;
440: for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
441: tokp->str = alloc(len + 1);
1.10 deraadt 442: if (tokp->str == NULL)
443: error("alloc failed");
1.1 deraadt 444: (void) strncpy(tokp->str, str, len);
445: tokp->str[len] = 0;
446: *mark = str + len;
447: }
448:
1.10 deraadt 449: static int
1.1 deraadt 450: cppline(line)
451: char *line;
452: {
453: return (line == curline && *line == '#');
454: }
455:
1.10 deraadt 456: static int
1.1 deraadt 457: directive(line)
458: char *line;
459: {
460: return (line == curline && *line == '%');
461: }
462:
1.10 deraadt 463: static void
1.1 deraadt 464: printdirective(line)
465: char *line;
466: {
1.9 deraadt 467: fprintf(fout, "%s", line + 1);
1.1 deraadt 468: }
469:
1.10 deraadt 470: static void
1.1 deraadt 471: docppline(line, lineno, fname)
472: char *line;
473: int *lineno;
474: char **fname;
475: {
476: char *file;
477: int num;
478: char *p;
479:
480: line++;
481: while (isspace(*line)) {
482: line++;
483: }
484: num = atoi(line);
485: while (isdigit(*line)) {
486: line++;
487: }
488: while (isspace(*line)) {
489: line++;
490: }
491: if (*line != '"') {
492: error("preprocessor error");
493: }
494: line++;
495: p = file = alloc(strlen(line) + 1);
1.10 deraadt 496: if (p == NULL)
497: error("alloc failed");
1.1 deraadt 498: while (*line && *line != '"') {
499: *p++ = *line++;
500: }
501: if (*line == 0) {
502: error("preprocessor error");
503: }
504: *p = 0;
505: if (*file == 0) {
506: *fname = NULL;
1.12 dhill 507: free(file);
1.1 deraadt 508: } else {
509: *fname = file;
510: }
511: *lineno = num - 1;
512: }