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