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