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