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