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