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