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