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