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