Bump copyright years. Happy new year!
[dragonfly.git] / usr.bin / rpcgen / rpc_scan.c
blob11fc3e887e17b2765e35d63bc6c4eea39b79e765
1 /*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
25 * Sun Microsystems, Inc.
26 * 2550 Garcia Avenue
27 * Mountain View, California 94043
29 * @(#)rpc_scan.c 1.13 93/07/05 SMI; 1.11 89/02/22 (C) 1987 SMI
30 * $FreeBSD: src/usr.bin/rpcgen/rpc_scan.c,v 1.10 2005/11/13 21:17:24 dwmalone Exp $
31 * $DragonFly: src/usr.bin/rpcgen/rpc_scan.c,v 1.5 2008/10/16 01:52:33 swildner Exp $
35 * rpc_scan.c, Scanner for the RPC protocol compiler
36 * Copyright (C) 1987, Sun Microsystems, Inc.
39 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <stdio.h>
43 #include <ctype.h>
44 #include <string.h>
45 #include "rpc_parse.h"
46 #include "rpc_scan.h"
47 #include "rpc_util.h"
49 #define startcomment(where) (where[0] == '/' && where[1] == '*')
50 #define endcomment(where) (where[-1] == '*' && where[0] == '/')
52 static int pushed = 0; /* is a token pushed */
53 static token lasttok; /* last token, if pushed */
55 static void unget_token(token *);
56 static void findstrconst(char **, const char **);
57 static void findchrconst(char **, const char **);
58 static void findconst(char **, const char **);
59 static void findkind(char **, token *);
60 static int cppline(char *);
61 static int directive(char *);
62 static void printdirective(char *);
63 static void docppline(char *, int *, const char **);
66 * scan expecting 1 given token
68 void
69 scan(tok_kind expect, token *tokp)
71 get_token(tokp);
72 if (tokp->kind != expect)
73 expected1(expect);
77 * scan expecting any of the 2 given tokens
79 void
80 scan2(tok_kind expect1, tok_kind expect2, token *tokp)
82 get_token(tokp);
83 if (tokp->kind != expect1 && tokp->kind != expect2)
84 expected2(expect1, expect2);
88 * scan expecting any of the 3 given token
90 void
91 scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
93 get_token(tokp);
94 if (tokp->kind != expect1 && tokp->kind != expect2 &&
95 tokp->kind != expect3)
96 expected3(expect1, expect2, expect3);
100 * scan expecting a constant, possibly symbolic
102 void
103 scan_num(token *tokp)
105 get_token(tokp);
106 switch (tokp->kind) {
107 case TOK_IDENT:
108 break;
109 default:
110 error("constant or identifier expected");
115 * Peek at the next token
117 void
118 peek(token *tokp)
120 get_token(tokp);
121 unget_token(tokp);
125 * Peek at the next token and scan it if it matches what you expect
128 peekscan(tok_kind expect, token *tokp)
130 peek(tokp);
131 if (tokp->kind == expect) {
132 get_token(tokp);
133 return(1);
135 return(0);
139 * Get the next token, printing out any directive that are encountered.
141 void
142 get_token(token *tokp)
144 int commenting;
145 int stat = 0;
147 if (pushed) {
148 pushed = 0;
149 *tokp = lasttok;
150 return;
152 commenting = 0;
153 for (;;) {
154 if (*where == 0) {
155 for (;;) {
156 if (!fgets(curline, MAXLINESIZE, fin)) {
157 tokp->kind = TOK_EOF;
159 * now check if cpp returned
160 * non NULL value
162 waitpid(childpid, &stat, WUNTRACED);
163 if (stat > 0) {
165 * Set return value from rpcgen
167 nonfatalerrors = stat >> 8;
169 *where = 0;
170 return;
172 linenum++;
173 if (commenting)
174 break;
175 else if (cppline(curline))
176 docppline(curline, &linenum,
177 &infilename);
178 else if (directive(curline))
179 printdirective(curline);
180 else
181 break;
183 where = curline;
184 } else if (isspace(*where)) {
185 while (isspace(*where))
186 where++; /* eat */
187 } else if (commenting) {
188 for (where++; *where; where++) {
189 if (endcomment(where)) {
190 where++;
191 commenting--;
192 break;
195 } else if (startcomment(where)) {
196 where += 2;
197 commenting++;
198 } else {
199 break;
204 * 'where' is not whitespace, comment or directive Must be a token!
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;
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;
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;
284 default:
285 if (!(isalpha(*where) || *where == '_')) {
286 char buf[100];
287 char *p;
289 s_print(buf, "illegal character in file: ");
290 p = buf + strlen(buf);
291 if (isprint(*where)) {
292 s_print(p, "%c", *where);
293 } else {
294 s_print(p, "%d", *where);
296 error(buf);
298 findkind(&where, tokp);
299 break;
303 static void
304 unget_token(token *tokp)
306 lasttok = *tokp;
307 pushed = 1;
310 static void
311 findstrconst(char **str, const char **val)
313 char *p;
314 char *tmp;
315 int size;
317 p = *str;
318 do {
319 p++;
320 } while (*p && *p != '"');
321 if (*p == 0)
322 error("unterminated string constant");
323 p++;
324 size = p - *str;
325 tmp = xmalloc(size + 1);
326 strncpy(tmp, *str, size);
327 tmp[size] = 0;
328 *val = tmp;
329 *str = p;
332 static void
333 findchrconst(char **str, const char **val)
335 char *p;
336 char *tmp;
337 int size;
339 p = *str;
340 do {
341 p++;
342 } while (*p && *p != '\'');
343 if (*p == 0)
344 error("unterminated string constant");
345 p++;
346 size = p - *str;
347 if (size != 3)
348 error("empty char string");
349 tmp = xmalloc(size + 1);
350 strncpy(tmp, *str, size);
351 tmp[size] = 0;
352 *val = tmp;
353 *str = p;
356 static void
357 findconst(char **str, const char **val)
359 char *p;
360 char *tmp;
361 int size;
363 p = *str;
364 if (*p == '0' && *(p + 1) == 'x') {
365 p++;
366 do {
367 p++;
368 } while (isxdigit(*p));
369 } else {
370 do {
371 p++;
372 } while (isdigit(*p));
374 size = p - *str;
375 tmp = xmalloc(size + 1);
376 strncpy(tmp, *str, size);
377 tmp[size] = 0;
378 *val = tmp;
379 *str = p;
382 static token symbols[] = {
383 {TOK_CONST, "const"},
384 {TOK_UNION, "union"},
385 {TOK_SWITCH, "switch"},
386 {TOK_CASE, "case"},
387 {TOK_DEFAULT, "default"},
388 {TOK_STRUCT, "struct"},
389 {TOK_TYPEDEF, "typedef"},
390 {TOK_ENUM, "enum"},
391 {TOK_OPAQUE, "opaque"},
392 {TOK_BOOL, "bool"},
393 {TOK_VOID, "void"},
394 {TOK_CHAR, "char"},
395 {TOK_INT, "int"},
396 {TOK_UNSIGNED, "unsigned"},
397 {TOK_SHORT, "short"},
398 {TOK_LONG, "long"},
399 {TOK_HYPER, "hyper"},
400 {TOK_FLOAT, "float"},
401 {TOK_DOUBLE, "double"},
402 {TOK_QUAD, "quadruple"},
403 {TOK_STRING, "string"},
404 {TOK_PROGRAM, "program"},
405 {TOK_VERSION, "version"},
406 {TOK_EOF, "??????"},
409 static void
410 findkind(char **mark, token *tokp)
412 int len;
413 token *s;
414 char *str, *tmp;
416 str = *mark;
417 for (s = symbols; s->kind != TOK_EOF; s++) {
418 len = strlen(s->str);
419 if (strncmp(str, s->str, len) == 0) {
420 if (!isalnum(str[len]) && str[len] != '_') {
421 tokp->kind = s->kind;
422 tokp->str = s->str;
423 *mark = str + len;
424 return;
428 tokp->kind = TOK_IDENT;
429 for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
430 tmp = xmalloc(len + 1);
431 strncpy(tmp, str, len);
432 tmp[len] = 0;
433 tokp->str = tmp;
434 *mark = str + len;
437 static int
438 cppline(char *line)
440 return(line == curline && *line == '#');
443 static int
444 directive(char *line)
446 return(line == curline && *line == '%');
449 static void
450 printdirective(char *line)
452 f_print(fout, "%s", line + 1);
455 static void
456 docppline(char *line, int *lineno, const char **fname)
458 char *file;
459 int num;
460 char *p;
462 line++;
463 while (isspace(*line))
464 line++;
465 num = atoi(line);
466 while (isdigit(*line))
467 line++;
468 while (isspace(*line))
469 line++;
470 if (*line != '"')
471 error("preprocessor error");
472 line++;
473 p = file = xmalloc(strlen(line) + 1);
474 while (*line && *line != '"')
475 *p++ = *line++;
476 if (*line == 0)
477 error("preprocessor error");
478 *p = 0;
479 if (*file == 0)
480 *fname = NULL;
481 else
482 *fname = file;
483 *lineno = num - 1;