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