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