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