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