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