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