Sync usage with man page.
[netbsd-mini2440.git] / usr.bin / rpcgen / rpc_scan.c
blob2acc2caeeab098fd8f3a10b0ecaeb05295eb6624
1 /* $NetBSD: rpc_scan.c,v 1.10 2006/03/20 17:01:26 elad 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.
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.
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.
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.
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.
27 * Sun Microsystems, Inc.
28 * 2550 Garcia Avenue
29 * Mountain View, California 94043
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
34 #endif
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.10 2006/03/20 17:01:26 elad Exp $");
42 #endif
43 #endif
46 * rpc_scan.c, Scanner for the RPC protocol compiler
47 * Copyright (C) 1987, Sun Microsystems, Inc.
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"
57 #define startcomment(where) (where[0] == '/' && where[1] == '*')
58 #define endcomment(where) (where[-1] == '*' && where[0] == '/')
60 static void unget_token __P((token *));
61 static void findstrconst __P((char **, char **));
62 static void findchrconst __P((char **, char **));
63 static void findconst __P((char **, char **));
64 static void findkind __P((char **, token *));
65 static int cppline __P((char *));
66 static int directive __P((char *));
67 static void printdirective __P((char *));
68 static void docppline __P((char *, int *, char **));
70 static int pushed = 0; /* is a token pushed */
71 static token lasttok; /* last token, if pushed */
74 * scan expecting 1 given token
76 void
77 scan(expect, tokp)
78 tok_kind expect;
79 token *tokp;
81 get_token(tokp);
82 if (tokp->kind != expect) {
83 expected1(expect);
87 * scan expecting any of the 2 given tokens
89 void
90 scan2(expect1, expect2, tokp)
91 tok_kind expect1;
92 tok_kind expect2;
93 token *tokp;
95 get_token(tokp);
96 if (tokp->kind != expect1 && tokp->kind != expect2) {
97 expected2(expect1, expect2);
101 * scan expecting any of the 3 given token
103 void
104 scan3(expect1, expect2, expect3, tokp)
105 tok_kind expect1;
106 tok_kind expect2;
107 tok_kind expect3;
108 token *tokp;
110 get_token(tokp);
111 if (tokp->kind != expect1 && tokp->kind != expect2
112 && tokp->kind != expect3) {
113 expected3(expect1, expect2, expect3);
117 * scan expecting a constant, possibly symbolic
119 void
120 scan_num(tokp)
121 token *tokp;
123 get_token(tokp);
124 switch (tokp->kind) {
125 case TOK_IDENT:
126 break;
127 default:
128 error("constant or identifier expected");
132 * Peek at the next token
134 void
135 peek(tokp)
136 token *tokp;
138 get_token(tokp);
139 unget_token(tokp);
142 * Peek at the next token and scan it if it matches what you expect
145 peekscan(expect, tokp)
146 tok_kind expect;
147 token *tokp;
149 peek(tokp);
150 if (tokp->kind == expect) {
151 get_token(tokp);
152 return (1);
154 return (0);
157 * Get the next token, printing out any directive that are encountered.
159 void
160 get_token(tokp)
161 token *tokp;
163 int commenting;
165 if (pushed) {
166 pushed = 0;
167 *tokp = lasttok;
168 return;
170 commenting = 0;
171 for (;;) {
172 if (*where == 0) {
173 for (;;) {
174 if (!fgets(curline, MAXLINESIZE, fin)) {
175 tokp->kind = TOK_EOF;
176 *where = 0;
177 return;
179 linenum++;
180 if (commenting) {
181 break;
182 } else
183 if (cppline(curline)) {
184 docppline(curline, &linenum,
185 &infilename);
186 } else
187 if (directive(curline)) {
188 printdirective(curline);
189 } else {
190 break;
193 where = curline;
194 } else
195 if (isspace((unsigned char)*where)) {
196 while (isspace((unsigned char)*where)) {
197 where++; /* eat */
199 } else
200 if (commenting) {
201 for (where++; *where; where++) {
202 if (endcomment(where)) {
203 where++;
204 commenting--;
205 break;
208 } else
209 if (startcomment(where)) {
210 where += 2;
211 commenting++;
212 } else {
213 break;
218 * 'where' is not whitespace, comment or directive Must be a token!
220 switch (*where) {
221 case ':':
222 tokp->kind = TOK_COLON;
223 where++;
224 break;
225 case ';':
226 tokp->kind = TOK_SEMICOLON;
227 where++;
228 break;
229 case ',':
230 tokp->kind = TOK_COMMA;
231 where++;
232 break;
233 case '=':
234 tokp->kind = TOK_EQUAL;
235 where++;
236 break;
237 case '*':
238 tokp->kind = TOK_STAR;
239 where++;
240 break;
241 case '[':
242 tokp->kind = TOK_LBRACKET;
243 where++;
244 break;
245 case ']':
246 tokp->kind = TOK_RBRACKET;
247 where++;
248 break;
249 case '{':
250 tokp->kind = TOK_LBRACE;
251 where++;
252 break;
253 case '}':
254 tokp->kind = TOK_RBRACE;
255 where++;
256 break;
257 case '(':
258 tokp->kind = TOK_LPAREN;
259 where++;
260 break;
261 case ')':
262 tokp->kind = TOK_RPAREN;
263 where++;
264 break;
265 case '<':
266 tokp->kind = TOK_LANGLE;
267 where++;
268 break;
269 case '>':
270 tokp->kind = TOK_RANGLE;
271 where++;
272 break;
274 case '"':
275 tokp->kind = TOK_STRCONST;
276 findstrconst(&where, &tokp->str);
277 break;
278 case '\'':
279 tokp->kind = TOK_CHARCONST;
280 findchrconst(&where, &tokp->str);
281 break;
283 case '-':
284 case '0':
285 case '1':
286 case '2':
287 case '3':
288 case '4':
289 case '5':
290 case '6':
291 case '7':
292 case '8':
293 case '9':
294 tokp->kind = TOK_IDENT;
295 findconst(&where, &tokp->str);
296 break;
298 default:
299 if (!(isalpha((unsigned char)*where) || *where == '_')) {
300 char buf[100];
301 char *p;
303 s_print(buf, "illegal character in file: ");
304 p = buf + strlen(buf);
305 if (isprint((unsigned char)*where)) {
306 s_print(p, "%c", *where);
307 } else {
308 s_print(p, "%d", *where);
310 error(buf);
312 findkind(&where, tokp);
313 break;
317 static void
318 unget_token(tokp)
319 token *tokp;
321 lasttok = *tokp;
322 pushed = 1;
325 static void
326 findstrconst(str, val)
327 char **str;
328 char **val;
330 char *p;
331 int size;
333 p = *str;
334 do {
335 p++;
336 } while (*p && *p != '"');
337 if (*p == 0) {
338 error("unterminated string constant");
340 p++;
341 size = p - *str;
342 *val = alloc(size + 1);
343 (void) strncpy(*val, *str, size);
344 (*val)[size] = 0;
345 *str = p;
348 static void
349 findchrconst(str, val)
350 char **str;
351 char **val;
353 char *p;
354 int size;
356 p = *str;
357 do {
358 p++;
359 } while (*p && *p != '\'');
360 if (*p == 0) {
361 error("unterminated string constant");
363 p++;
364 size = p - *str;
365 if (size != 3) {
366 error("empty char string");
368 *val = alloc(size + 1);
369 (void) strncpy(*val, *str, size);
370 (*val)[size] = 0;
371 *str = p;
374 static void
375 findconst(str, val)
376 char **str;
377 char **val;
379 char *p;
380 int size;
382 p = *str;
383 if (*p == '0' && *(p + 1) == 'x') {
384 p++;
385 do {
386 p++;
387 } while (isxdigit((unsigned char)*p));
388 } else {
389 do {
390 p++;
391 } while (isdigit((unsigned char)*p));
393 size = p - *str;
394 *val = alloc(size + 1);
395 (void) strncpy(*val, *str, size);
396 (*val)[size] = 0;
397 *str = p;
400 static token symbols[] = {
401 {TOK_CONST, "const"},
402 {TOK_UNION, "union"},
403 {TOK_SWITCH, "switch"},
404 {TOK_CASE, "case"},
405 {TOK_DEFAULT, "default"},
406 {TOK_STRUCT, "struct"},
407 {TOK_TYPEDEF, "typedef"},
408 {TOK_ENUM, "enum"},
409 {TOK_OPAQUE, "opaque"},
410 {TOK_BOOL, "bool"},
411 {TOK_VOID, "void"},
412 {TOK_CHAR, "char"},
413 {TOK_INT, "int"},
414 {TOK_UNSIGNED, "unsigned"},
415 {TOK_SHORT, "short"},
416 {TOK_LONG, "long"},
417 {TOK_HYPER, "hyper"},
418 {TOK_FLOAT, "float"},
419 {TOK_DOUBLE, "double"},
420 {TOK_QUAD, "quadruple"},
421 {TOK_STRING, "string"},
422 {TOK_PROGRAM, "program"},
423 {TOK_VERSION, "version"},
424 {TOK_EOF, "??????"},
427 static void
428 findkind(mark, tokp)
429 char **mark;
430 token *tokp;
432 int len;
433 token *s;
434 char *str;
436 str = *mark;
437 for (s = symbols; s->kind != TOK_EOF; s++) {
438 len = strlen(s->str);
439 if (strncmp(str, s->str, len) == 0) {
440 if (!isalnum((unsigned char)str[len]) &&
441 str[len] != '_') {
442 tokp->kind = s->kind;
443 tokp->str = s->str;
444 *mark = str + len;
445 return;
449 tokp->kind = TOK_IDENT;
450 for (len = 0; isalnum((unsigned char)str[len]) ||
451 str[len] == '_'; len++);
452 tokp->str = alloc(len + 1);
453 (void) strncpy(tokp->str, str, len);
454 tokp->str[len] = 0;
455 *mark = str + len;
458 static int
459 cppline(line)
460 char *line;
462 return (line == curline && *line == '#');
465 static int
466 directive(line)
467 char *line;
469 return (line == curline && *line == '%');
472 static void
473 printdirective(line)
474 char *line;
476 f_print(fout, "%s", line + 1);
479 static void
480 docppline(line, lineno, fname)
481 char *line;
482 int *lineno;
483 char **fname;
485 char *file;
486 int num;
487 char *p;
489 line++;
490 while (isspace((unsigned char)*line)) {
491 line++;
493 num = atoi(line);
494 while (isdigit((unsigned char)*line)) {
495 line++;
497 while (isspace((unsigned char)*line)) {
498 line++;
500 if (*line != '"') {
501 error("preprocessor error");
503 line++;
504 p = file = alloc(strlen(line) + 1);
505 while (*line && *line != '"') {
506 *p++ = *line++;
508 if (*line == 0) {
509 error("preprocessor error");
511 *p = 0;
512 if (*file == 0) {
513 *fname = NULL;
514 free(file);
515 } else {
516 *fname = file;
518 *lineno = num - 1;