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