Home | History | Annotate | Line # | Download | only in rpcgen
      1 /*	$NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 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.15 2015/05/09 23:28:43 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 			if (isprint((unsigned char)*where)) {
    287 				error("Illegal character '%c' in file", *where);
    288 			} else {
    289 				error("Illegal character %d in file", *where);
    290 			}
    291 		}
    292 		findkind(&where, tokp);
    293 		break;
    294 	}
    295 }
    296 
    297 static void
    298 unget_token(token *tokp)
    299 {
    300 	lasttok = *tokp;
    301 	pushed = 1;
    302 }
    303 
    304 static void
    305 findstrconst(char **str, const char **val)
    306 {
    307 	char *p;
    308 	int     size;
    309 	char *tmp;
    310 
    311 	p = *str;
    312 	do {
    313 		p++;
    314 	} while (*p && *p != '"');
    315 	if (*p == 0) {
    316 		error("Unterminated string constant");
    317 	}
    318 	p++;
    319 	size = p - *str;
    320 	tmp = alloc(size + 1);
    321 	(void) strncpy(tmp, *str, size);
    322 	tmp[size] = 0;
    323 	*val = tmp;
    324 	*str = p;
    325 }
    326 
    327 static void
    328 findchrconst(char **str, const char **val)
    329 {
    330 	char *p;
    331 	int     size;
    332 	char *tmp;
    333 
    334 	p = *str;
    335 	do {
    336 		p++;
    337 	} while (*p && *p != '\'');
    338 	if (*p == 0) {
    339 		error("Unterminated string constant");
    340 	}
    341 	p++;
    342 	size = p - *str;
    343 	if (size != 3) {
    344 		error("Empty character");
    345 	}
    346 	tmp = alloc(size + 1);
    347 	(void) strncpy(tmp, *str, size);
    348 	tmp[size] = 0;
    349 	*val = tmp;
    350 	*str = p;
    351 }
    352 
    353 static void
    354 findconst(char **str, const char **val)
    355 {
    356 	char *p;
    357 	int     size;
    358 	char *tmp;
    359 
    360 	p = *str;
    361 	if (*p == '0' && *(p + 1) == 'x') {
    362 		p++;
    363 		do {
    364 			p++;
    365 		} while (isxdigit((unsigned char)*p));
    366 	} else {
    367 		do {
    368 			p++;
    369 		} while (isdigit((unsigned char)*p));
    370 	}
    371 	size = p - *str;
    372 	tmp = alloc(size + 1);
    373 	(void) strncpy(tmp, *str, size);
    374 	tmp[size] = 0;
    375 	*val = tmp;
    376 	*str = p;
    377 }
    378 
    379 static const token symbols[] = {
    380 	{TOK_CONST, "const"},
    381 	{TOK_UNION, "union"},
    382 	{TOK_SWITCH, "switch"},
    383 	{TOK_CASE, "case"},
    384 	{TOK_DEFAULT, "default"},
    385 	{TOK_STRUCT, "struct"},
    386 	{TOK_TYPEDEF, "typedef"},
    387 	{TOK_ENUM, "enum"},
    388 	{TOK_OPAQUE, "opaque"},
    389 	{TOK_BOOL, "bool"},
    390 	{TOK_VOID, "void"},
    391 	{TOK_CHAR, "char"},
    392 	{TOK_INT, "int"},
    393 	{TOK_UNSIGNED, "unsigned"},
    394 	{TOK_SHORT, "short"},
    395 	{TOK_LONG, "long"},
    396 	{TOK_HYPER, "hyper"},
    397 	{TOK_FLOAT, "float"},
    398 	{TOK_DOUBLE, "double"},
    399 	{TOK_QUAD, "quadruple"},
    400 	{TOK_STRING, "string"},
    401 	{TOK_PROGRAM, "program"},
    402 	{TOK_VERSION, "version"},
    403 	{TOK_EOF, "??????"},
    404 };
    405 
    406 static void
    407 findkind(char **mark, token *tokp)
    408 {
    409 	int     len;
    410 	const token *s;
    411 	char *str;
    412 	char *tmp;
    413 
    414 	str = *mark;
    415 	for (s = symbols; s->kind != TOK_EOF; s++) {
    416 		len = strlen(s->str);
    417 		if (strncmp(str, s->str, len) == 0) {
    418 			if (!isalnum((unsigned char)str[len]) &&
    419 			    str[len] != '_') {
    420 				tokp->kind = s->kind;
    421 				tokp->str = s->str;
    422 				*mark = str + len;
    423 				return;
    424 			}
    425 		}
    426 	}
    427 	tokp->kind = TOK_IDENT;
    428 	for (len = 0; isalnum((unsigned char)str[len]) ||
    429 	    str[len] == '_'; len++);
    430 	tmp = alloc(len + 1);
    431 	(void) strncpy(tmp, str, len);
    432 	tmp[len] = 0;
    433 	tokp->str = tmp;
    434 	*mark = str + len;
    435 }
    436 
    437 static int
    438 cppline(const char *line)
    439 {
    440 	return (line == curline && *line == '#');
    441 }
    442 
    443 static int
    444 directive(const char *line)
    445 {
    446 	return (line == curline && *line == '%');
    447 }
    448 
    449 static void
    450 printdirective(const char *line)
    451 {
    452 	f_print(fout, "%s", line + 1);
    453 }
    454 
    455 static void
    456 docppline(char *line, int *lineno, const char **fname)
    457 {
    458 	char   *file;
    459 	int     num;
    460 	char   *p;
    461 
    462 	line++;
    463 	while (isspace((unsigned char)*line)) {
    464 		line++;
    465 	}
    466 	num = atoi(line);
    467 	while (isdigit((unsigned char)*line)) {
    468 		line++;
    469 	}
    470 	while (isspace((unsigned char)*line)) {
    471 		line++;
    472 	}
    473 	if (*line != '"') {
    474 		error("Preprocessor error");
    475 	}
    476 	line++;
    477 	p = file = alloc(strlen(line) + 1);
    478 	while (*line && *line != '"') {
    479 		*p++ = *line++;
    480 	}
    481 	if (*line == 0) {
    482 		error("Preprocessor error");
    483 	}
    484 	*p = 0;
    485 	if (*file == 0) {
    486 		*fname = NULL;
    487 		free(file);
    488 	} else {
    489 		*fname = file;
    490 	}
    491 	*lineno = num - 1;
    492 }
    493