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