Annotation of src/usr.bin/rpcgen/rpc_scan.c, Revision 1.2
1.2 ! deraadt 1: /* $OpenBSD: rpc_scan.c,v 1.4 1995/06/11 21:50:02 pk 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: /*
38: * rpc_scan.c, Scanner for the RPC protocol compiler
39: * Copyright (C) 1987, Sun Microsystems, Inc.
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:
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 **));
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: /*
67: * scan expecting 1 given token
68: */
69: void
70: scan(expect, tokp)
71: tok_kind expect;
72: token *tokp;
73: {
74: get_token(tokp);
75: if (tokp->kind != expect) {
76: expected1(expect);
77: }
78: }
79:
80: /*
81: * scan expecting any of the 2 given tokens
82: */
83: void
84: scan2(expect1, expect2, tokp)
85: tok_kind expect1;
86: tok_kind expect2;
87: token *tokp;
88: {
89: get_token(tokp);
90: if (tokp->kind != expect1 && tokp->kind != expect2) {
91: expected2(expect1, expect2);
92: }
93: }
94:
95: /*
96: * scan expecting any of the 3 given token
97: */
98: void
99: scan3(expect1, expect2, expect3, tokp)
100: tok_kind expect1;
101: tok_kind expect2;
102: tok_kind expect3;
103: token *tokp;
104: {
105: get_token(tokp);
106: if (tokp->kind != expect1 && tokp->kind != expect2
107: && tokp->kind != expect3) {
108: expected3(expect1, expect2, expect3);
109: }
110: }
111:
112: /*
113: * scan expecting a constant, possibly symbolic
114: */
115: void
116: scan_num(tokp)
117: token *tokp;
118: {
119: get_token(tokp);
120: switch (tokp->kind) {
121: case TOK_IDENT:
122: break;
123: default:
124: error("constant or identifier expected");
125: }
126: }
127:
128: /*
129: * Peek at the next token
130: */
131: void
132: peek(tokp)
133: token *tokp;
134: {
135: get_token(tokp);
136: unget_token(tokp);
137: }
138:
139: /*
140: * Peek at the next token and scan it if it matches what you expect
141: */
142: int
143: peekscan(expect, tokp)
144: tok_kind expect;
145: token *tokp;
146: {
147: peek(tokp);
148: if (tokp->kind == expect) {
149: get_token(tokp);
150: return (1);
151: }
152: return (0);
153: }
154:
155: /*
156: * Get the next token, printing out any directive that are encountered.
157: */
158: void
159: get_token(tokp)
160: token *tokp;
161: {
162: int commenting;
163:
164: if (pushed) {
165: pushed = 0;
166: *tokp = lasttok;
167: return;
168: }
169: commenting = 0;
170: for (;;) {
171: if (*where == 0) {
172: for (;;) {
173: if (!fgets(curline, MAXLINESIZE, fin)) {
174: tokp->kind = TOK_EOF;
175: *where = 0;
176: return;
177: }
178: linenum++;
179: if (commenting) {
180: break;
181: } else if (cppline(curline)) {
182: docppline(curline, &linenum,
183: &infilename);
184: } else if (directive(curline)) {
185: printdirective(curline);
186: } else {
187: break;
188: }
189: }
190: where = curline;
191: } else if (isspace(*where)) {
192: while (isspace(*where)) {
193: where++; /* eat */
194: }
195: } else if (commenting) {
196: for (where++; *where; where++) {
197: if (endcomment(where)) {
198: where++;
199: commenting--;
200: break;
201: }
202: }
203: } else if (startcomment(where)) {
204: where += 2;
205: commenting++;
206: } else {
207: break;
208: }
209: }
210:
211: /*
212: * 'where' is not whitespace, comment or directive Must be a token!
213: */
214: switch (*where) {
215: case ':':
216: tokp->kind = TOK_COLON;
217: where++;
218: break;
219: case ';':
220: tokp->kind = TOK_SEMICOLON;
221: where++;
222: break;
223: case ',':
224: tokp->kind = TOK_COMMA;
225: where++;
226: break;
227: case '=':
228: tokp->kind = TOK_EQUAL;
229: where++;
230: break;
231: case '*':
232: tokp->kind = TOK_STAR;
233: where++;
234: break;
235: case '[':
236: tokp->kind = TOK_LBRACKET;
237: where++;
238: break;
239: case ']':
240: tokp->kind = TOK_RBRACKET;
241: where++;
242: break;
243: case '{':
244: tokp->kind = TOK_LBRACE;
245: where++;
246: break;
247: case '}':
248: tokp->kind = TOK_RBRACE;
249: where++;
250: break;
251: case '(':
252: tokp->kind = TOK_LPAREN;
253: where++;
254: break;
255: case ')':
256: tokp->kind = TOK_RPAREN;
257: where++;
258: break;
259: case '<':
260: tokp->kind = TOK_LANGLE;
261: where++;
262: break;
263: case '>':
264: tokp->kind = TOK_RANGLE;
265: where++;
266: break;
267:
268: case '"':
269: tokp->kind = TOK_STRCONST;
270: findstrconst(&where, &tokp->str);
271: break;
272: case '\'':
273: tokp->kind = TOK_CHARCONST;
274: findchrconst(&where, &tokp->str);
275: break;
276:
277: case '-':
278: case '0':
279: case '1':
280: case '2':
281: case '3':
282: case '4':
283: case '5':
284: case '6':
285: case '7':
286: case '8':
287: case '9':
288: tokp->kind = TOK_IDENT;
289: findconst(&where, &tokp->str);
290: break;
291:
292: default:
293: if (!(isalpha(*where) || *where == '_')) {
294: char buf[100];
295: char *p;
296:
297: s_print(buf, "illegal character in file: ");
298: p = buf + strlen(buf);
299: if (isprint(*where)) {
300: s_print(p, "%c", *where);
301: } else {
302: s_print(p, "%d", *where);
303: }
304: error(buf);
305: }
306: findkind(&where, tokp);
307: break;
308: }
309: }
310:
311: static
312: unget_token(tokp)
313: token *tokp;
314: {
315: lasttok = *tokp;
316: pushed = 1;
317: }
318:
319: static
320: findstrconst(str, val)
321: char **str;
322: char **val;
323: {
324: char *p;
325: int size;
326:
327: p = *str;
328: do {
329: *p++;
330: } while (*p && *p != '"');
331: if (*p == 0) {
332: error("unterminated string constant");
333: }
334: p++;
335: size = p - *str;
336: *val = alloc(size + 1);
337: (void) strncpy(*val, *str, size);
338: (*val)[size] = 0;
339: *str = p;
340: }
341:
342: static
343: findchrconst(str, val)
344: char **str;
345: char **val;
346: {
347: char *p;
348: int size;
349:
350: p = *str;
351: do {
352: *p++;
353: } while (*p && *p != '\'');
354: if (*p == 0) {
355: error("unterminated string constant");
356: }
357: p++;
358: size = p - *str;
359: if (size != 3) {
360: error("empty char string");
361: }
362: *val = alloc(size + 1);
363: (void) strncpy(*val, *str, size);
364: (*val)[size] = 0;
365: *str = p;
366: }
367:
368: static
369: findconst(str, val)
370: char **str;
371: char **val;
372: {
373: char *p;
374: int size;
375:
376: p = *str;
377: if (*p == '0' && *(p + 1) == 'x') {
378: p++;
379: do {
380: p++;
381: } while (isxdigit(*p));
382: } else {
383: do {
384: p++;
385: } while (isdigit(*p));
386: }
387: size = p - *str;
388: *val = alloc(size + 1);
389: (void) strncpy(*val, *str, size);
390: (*val)[size] = 0;
391: *str = p;
392: }
393:
394: static token symbols[] = {
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, "??????"},
417: };
418:
419: static
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);
443: (void) strncpy(tokp->str, str, len);
444: tokp->str[len] = 0;
445: *mark = str + len;
446: }
447:
448: static
449: cppline(line)
450: char *line;
451: {
452: return (line == curline && *line == '#');
453: }
454:
455: static
456: directive(line)
457: char *line;
458: {
459: return (line == curline && *line == '%');
460: }
461:
462: static
463: printdirective(line)
464: char *line;
465: {
466: f_print(fout, "%s", line + 1);
467: }
468:
469: static
470: docppline(line, lineno, fname)
471: char *line;
472: int *lineno;
473: char **fname;
474: {
475: char *file;
476: int num;
477: char *p;
478:
479: line++;
480: while (isspace(*line)) {
481: line++;
482: }
483: num = atoi(line);
484: while (isdigit(*line)) {
485: line++;
486: }
487: while (isspace(*line)) {
488: line++;
489: }
490: if (*line != '"') {
491: error("preprocessor error");
492: }
493: line++;
494: p = file = alloc(strlen(line) + 1);
495: while (*line && *line != '"') {
496: *p++ = *line++;
497: }
498: if (*line == 0) {
499: error("preprocessor error");
500: }
501: *p = 0;
502: if (*file == 0) {
503: *fname = NULL;
504: } else {
505: *fname = file;
506: }
507: *lineno = num - 1;
508: }