rpc_scan.c revision 92921
11897Swollman/*
21897Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
31897Swollman * unrestricted use provided that this legend is included on all tape
41897Swollman * media and as a part of the software program in whole or part.  Users
51897Swollman * may copy or modify Sun RPC without charge, but are not authorized
61897Swollman * to license or distribute it to anyone else except as part of a product or
71897Swollman * program developed by the user.
812798Swpaul *
91897Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
101897Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
111897Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
1212798Swpaul *
131897Swollman * Sun RPC is provided with no support and without any obligation on the
141897Swollman * part of Sun Microsystems, Inc. to assist in its use, correction,
151897Swollman * modification or enhancement.
1612798Swpaul *
171897Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
181897Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
191897Swollman * OR ANY PART THEREOF.
2012798Swpaul *
211897Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue
221897Swollman * or profits or other special, indirect and consequential damages, even if
231897Swollman * Sun has been advised of the possibility of such damages.
2412798Swpaul *
251897Swollman * Sun Microsystems, Inc.
261897Swollman * 2550 Garcia Avenue
271897Swollman * Mountain View, California  94043
2867191Sbrian *
2967191Sbrian * $FreeBSD: head/usr.bin/rpcgen/rpc_scan.c 92921 2002-03-22 01:33:25Z imp $
301897Swollman */
3112798Swpaul
3212798Swpaul#ident	"@(#)rpc_scan.c	1.13	93/07/05 SMI"
3312798Swpaul
341897Swollman#ifndef lint
3512798Swpaulstatic char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
361897Swollman#endif
371897Swollman
381897Swollman/*
3912798Swpaul * rpc_scan.c, Scanner for the RPC protocol compiler
4012798Swpaul * Copyright (C) 1987, Sun Microsystems, Inc.
411897Swollman */
4212798Swpaul
4367191Sbrian#include <sys/types.h>
4467191Sbrian
4512798Swpaul#include <sys/wait.h>
461897Swollman#include <stdio.h>
471897Swollman#include <ctype.h>
4812798Swpaul#include <string.h>
491897Swollman#include "rpc_scan.h"
5012798Swpaul#include "rpc_parse.h"
511897Swollman#include "rpc_util.h"
521897Swollman
531897Swollman#define startcomment(where) (where[0] == '/' && where[1] == '*')
541897Swollman#define endcomment(where) (where[-1] == '*' && where[0] == '/')
551897Swollman
561897Swollmanstatic int pushed = 0;	/* is a token pushed */
571897Swollmanstatic token lasttok;	/* last token, if pushed */
581897Swollman
5992921Simpstatic void unget_token( token * );
6092921Simpstatic void findstrconst( char **, char **);
6192921Simpstatic void findchrconst( char **, char **);
6292921Simpstatic void findconst( char **, char **);
6392921Simpstatic void findkind( char **, token * );
6492921Simpstatic int cppline( char * );
6592921Simpstatic int directive( char * );
6692921Simpstatic void printdirective( char * );
6792921Simpstatic void docppline( char *, int *, char ** );
6812798Swpaul
691897Swollman/*
7012798Swpaul * scan expecting 1 given token
711897Swollman */
721897Swollmanvoid
731897Swollmanscan(expect, tokp)
741897Swollman	tok_kind expect;
751897Swollman	token *tokp;
761897Swollman{
771897Swollman	get_token(tokp);
781897Swollman	if (tokp->kind != expect) {
791897Swollman		expected1(expect);
801897Swollman	}
811897Swollman}
821897Swollman
831897Swollman/*
8412798Swpaul * scan expecting any of the 2 given tokens
851897Swollman */
861897Swollmanvoid
871897Swollmanscan2(expect1, expect2, tokp)
881897Swollman	tok_kind expect1;
891897Swollman	tok_kind expect2;
901897Swollman	token *tokp;
911897Swollman{
921897Swollman	get_token(tokp);
931897Swollman	if (tokp->kind != expect1 && tokp->kind != expect2) {
941897Swollman		expected2(expect1, expect2);
951897Swollman	}
961897Swollman}
971897Swollman
981897Swollman/*
9912798Swpaul * scan expecting any of the 3 given token
1001897Swollman */
1011897Swollmanvoid
1021897Swollmanscan3(expect1, expect2, expect3, tokp)
1031897Swollman	tok_kind expect1;
1041897Swollman	tok_kind expect2;
1051897Swollman	tok_kind expect3;
1061897Swollman	token *tokp;
1071897Swollman{
1081897Swollman	get_token(tokp);
1091897Swollman	if (tokp->kind != expect1 && tokp->kind != expect2
1101897Swollman	    && tokp->kind != expect3) {
1111897Swollman		expected3(expect1, expect2, expect3);
1121897Swollman	}
1131897Swollman}
1141897Swollman
1151897Swollman/*
11612798Swpaul * scan expecting a constant, possibly symbolic
1171897Swollman */
1181897Swollmanvoid
1191897Swollmanscan_num(tokp)
1201897Swollman	token *tokp;
1211897Swollman{
1221897Swollman	get_token(tokp);
1231897Swollman	switch (tokp->kind) {
1241897Swollman	case TOK_IDENT:
1251897Swollman		break;
1261897Swollman	default:
1271897Swollman		error("constant or identifier expected");
1281897Swollman	}
1291897Swollman}
1301897Swollman
1311897Swollman/*
13212798Swpaul * Peek at the next token
1331897Swollman */
1341897Swollmanvoid
1351897Swollmanpeek(tokp)
1361897Swollman	token *tokp;
1371897Swollman{
1381897Swollman	get_token(tokp);
1391897Swollman	unget_token(tokp);
1401897Swollman}
1411897Swollman
1421897Swollman/*
14312798Swpaul * Peek at the next token and scan it if it matches what you expect
1441897Swollman */
1451897Swollmanint
1461897Swollmanpeekscan(expect, tokp)
1471897Swollman	tok_kind expect;
1481897Swollman	token *tokp;
1491897Swollman{
1501897Swollman	peek(tokp);
1511897Swollman	if (tokp->kind == expect) {
1521897Swollman		get_token(tokp);
1531897Swollman		return (1);
1541897Swollman	}
1551897Swollman	return (0);
1561897Swollman}
1571897Swollman
1581897Swollman/*
15912798Swpaul * Get the next token, printing out any directive that are encountered.
1601897Swollman */
1611897Swollmanvoid
1621897Swollmanget_token(tokp)
1631897Swollman	token *tokp;
1641897Swollman{
1651897Swollman	int commenting;
16612798Swpaul	int stat = 0;
16712798Swpaul
16812798Swpaul
1691897Swollman	if (pushed) {
1701897Swollman		pushed = 0;
1711897Swollman		*tokp = lasttok;
1721897Swollman		return;
1731897Swollman	}
1741897Swollman	commenting = 0;
1751897Swollman	for (;;) {
1761897Swollman		if (*where == 0) {
1771897Swollman			for (;;) {
1781897Swollman				if (!fgets(curline, MAXLINESIZE, fin)) {
1791897Swollman					tokp->kind = TOK_EOF;
18012798Swpaul					/* now check if cpp returned non NULL value */
18112798Swpaul					waitpid(childpid, &stat, WUNTRACED);
18212798Swpaul					if (stat > 0) {
18312798Swpaul					/* Set return value from rpcgen */
18412798Swpaul						nonfatalerrors = stat >> 8;
18512798Swpaul					}
1861897Swollman					*where = 0;
1871897Swollman					return;
1881897Swollman				}
1891897Swollman				linenum++;
1901897Swollman				if (commenting) {
1911897Swollman					break;
1921897Swollman				} else if (cppline(curline)) {
19312798Swpaul					docppline(curline, &linenum,
1941897Swollman						  &infilename);
1951897Swollman				} else if (directive(curline)) {
1961897Swollman					printdirective(curline);
1971897Swollman				} else {
1981897Swollman					break;
1991897Swollman				}
2001897Swollman			}
2011897Swollman			where = curline;
2021897Swollman		} else if (isspace(*where)) {
2031897Swollman			while (isspace(*where)) {
2041897Swollman				where++;	/* eat */
2051897Swollman			}
2061897Swollman		} else if (commenting) {
20712798Swpaul			for (where++; *where; where++) {
20812798Swpaul				if (endcomment(where)) {
20912798Swpaul					where++;
21012798Swpaul					commenting--;
21112798Swpaul					break;
21212798Swpaul				}
2131897Swollman			}
2141897Swollman		} else if (startcomment(where)) {
2151897Swollman			where += 2;
2161897Swollman			commenting++;
2171897Swollman		} else {
2181897Swollman			break;
2191897Swollman		}
2201897Swollman	}
2211897Swollman
2221897Swollman	/*
22312798Swpaul	 * 'where' is not whitespace, comment or directive Must be a token!
2241897Swollman	 */
2251897Swollman	switch (*where) {
2261897Swollman	case ':':
2271897Swollman		tokp->kind = TOK_COLON;
2281897Swollman		where++;
2291897Swollman		break;
2301897Swollman	case ';':
2311897Swollman		tokp->kind = TOK_SEMICOLON;
2321897Swollman		where++;
2331897Swollman		break;
2341897Swollman	case ',':
2351897Swollman		tokp->kind = TOK_COMMA;
2361897Swollman		where++;
2371897Swollman		break;
2381897Swollman	case '=':
2391897Swollman		tokp->kind = TOK_EQUAL;
2401897Swollman		where++;
2411897Swollman		break;
2421897Swollman	case '*':
2431897Swollman		tokp->kind = TOK_STAR;
2441897Swollman		where++;
2451897Swollman		break;
2461897Swollman	case '[':
2471897Swollman		tokp->kind = TOK_LBRACKET;
2481897Swollman		where++;
2491897Swollman		break;
2501897Swollman	case ']':
2511897Swollman		tokp->kind = TOK_RBRACKET;
2521897Swollman		where++;
2531897Swollman		break;
2541897Swollman	case '{':
2551897Swollman		tokp->kind = TOK_LBRACE;
2561897Swollman		where++;
2571897Swollman		break;
2581897Swollman	case '}':
2591897Swollman		tokp->kind = TOK_RBRACE;
2601897Swollman		where++;
2611897Swollman		break;
2621897Swollman	case '(':
2631897Swollman		tokp->kind = TOK_LPAREN;
2641897Swollman		where++;
2651897Swollman		break;
2661897Swollman	case ')':
2671897Swollman		tokp->kind = TOK_RPAREN;
2681897Swollman		where++;
2691897Swollman		break;
2701897Swollman	case '<':
2711897Swollman		tokp->kind = TOK_LANGLE;
2721897Swollman		where++;
2731897Swollman		break;
2741897Swollman	case '>':
2751897Swollman		tokp->kind = TOK_RANGLE;
2761897Swollman		where++;
2771897Swollman		break;
2781897Swollman
2791897Swollman	case '"':
2801897Swollman		tokp->kind = TOK_STRCONST;
2811897Swollman		findstrconst(&where, &tokp->str);
2821897Swollman		break;
28312798Swpaul	case '\'':
28412798Swpaul		tokp->kind = TOK_CHARCONST;
28512798Swpaul		findchrconst(&where, &tokp->str);
28612798Swpaul		break;
2871897Swollman
2881897Swollman	case '-':
2891897Swollman	case '0':
2901897Swollman	case '1':
2911897Swollman	case '2':
2921897Swollman	case '3':
2931897Swollman	case '4':
2941897Swollman	case '5':
2951897Swollman	case '6':
2961897Swollman	case '7':
2971897Swollman	case '8':
2981897Swollman	case '9':
2991897Swollman		tokp->kind = TOK_IDENT;
3001897Swollman		findconst(&where, &tokp->str);
3011897Swollman		break;
3021897Swollman
3031897Swollman	default:
3041897Swollman		if (!(isalpha(*where) || *where == '_')) {
3051897Swollman			char buf[100];
3061897Swollman			char *p;
3071897Swollman
3081897Swollman			s_print(buf, "illegal character in file: ");
3091897Swollman			p = buf + strlen(buf);
3101897Swollman			if (isprint(*where)) {
3111897Swollman				s_print(p, "%c", *where);
3121897Swollman			} else {
3131897Swollman				s_print(p, "%d", *where);
3141897Swollman			}
3151897Swollman			error(buf);
3161897Swollman		}
3171897Swollman		findkind(&where, tokp);
3181897Swollman		break;
3191897Swollman	}
3201897Swollman}
3211897Swollman
32217142Sjkhstatic void
3231897Swollmanunget_token(tokp)
3241897Swollman	token *tokp;
3251897Swollman{
3261897Swollman	lasttok = *tokp;
3271897Swollman	pushed = 1;
3281897Swollman}
3291897Swollman
33017142Sjkhstatic void
3311897Swollmanfindstrconst(str, val)
3321897Swollman	char **str;
3331897Swollman	char **val;
3341897Swollman{
3351897Swollman	char *p;
3361897Swollman	int size;
3371897Swollman
3381897Swollman	p = *str;
3391897Swollman	do {
34017142Sjkh		p++;
3411897Swollman	} while (*p && *p != '"');
3421897Swollman	if (*p == 0) {
3431897Swollman		error("unterminated string constant");
3441897Swollman	}
3451897Swollman	p++;
3461897Swollman	size = p - *str;
3471897Swollman	*val = alloc(size + 1);
3481897Swollman	(void) strncpy(*val, *str, size);
3491897Swollman	(*val)[size] = 0;
3501897Swollman	*str = p;
3511897Swollman}
3521897Swollman
35317142Sjkhstatic void
35412798Swpaulfindchrconst(str, val)
35512798Swpaul	char **str;
35612798Swpaul	char **val;
35712798Swpaul{
35812798Swpaul	char *p;
35912798Swpaul	int size;
36012798Swpaul
36112798Swpaul	p = *str;
36212798Swpaul	do {
36317142Sjkh		p++;
36412798Swpaul	} while (*p && *p != '\'');
36512798Swpaul	if (*p == 0) {
36612798Swpaul		error("unterminated string constant");
36712798Swpaul	}
36812798Swpaul	p++;
36912798Swpaul	size = p - *str;
37012798Swpaul	if (size != 3) {
37112798Swpaul		error("empty char string");
37212798Swpaul	}
37312798Swpaul	*val = alloc(size + 1);
37412798Swpaul	(void) strncpy(*val, *str, size);
37512798Swpaul	(*val)[size] = 0;
37612798Swpaul	*str = p;
37712798Swpaul}
37812798Swpaul
37917142Sjkhstatic void
3801897Swollmanfindconst(str, val)
3811897Swollman	char **str;
3821897Swollman	char **val;
3831897Swollman{
3841897Swollman	char *p;
3851897Swollman	int size;
3861897Swollman
3871897Swollman	p = *str;
3881897Swollman	if (*p == '0' && *(p + 1) == 'x') {
3891897Swollman		p++;
3901897Swollman		do {
3911897Swollman			p++;
3921897Swollman		} while (isxdigit(*p));
3931897Swollman	} else {
3941897Swollman		do {
3951897Swollman			p++;
3961897Swollman		} while (isdigit(*p));
3971897Swollman	}
3981897Swollman	size = p - *str;
3991897Swollman	*val = alloc(size + 1);
4001897Swollman	(void) strncpy(*val, *str, size);
4011897Swollman	(*val)[size] = 0;
4021897Swollman	*str = p;
4031897Swollman}
4041897Swollman
4051897Swollmanstatic token symbols[] = {
4061897Swollman			  {TOK_CONST, "const"},
4071897Swollman			  {TOK_UNION, "union"},
4081897Swollman			  {TOK_SWITCH, "switch"},
4091897Swollman			  {TOK_CASE, "case"},
4101897Swollman			  {TOK_DEFAULT, "default"},
4111897Swollman			  {TOK_STRUCT, "struct"},
4121897Swollman			  {TOK_TYPEDEF, "typedef"},
4131897Swollman			  {TOK_ENUM, "enum"},
4141897Swollman			  {TOK_OPAQUE, "opaque"},
4151897Swollman			  {TOK_BOOL, "bool"},
4161897Swollman			  {TOK_VOID, "void"},
4171897Swollman			  {TOK_CHAR, "char"},
4181897Swollman			  {TOK_INT, "int"},
4191897Swollman			  {TOK_UNSIGNED, "unsigned"},
4201897Swollman			  {TOK_SHORT, "short"},
4211897Swollman			  {TOK_LONG, "long"},
42212798Swpaul			  {TOK_HYPER, "hyper"},
4231897Swollman			  {TOK_FLOAT, "float"},
4241897Swollman			  {TOK_DOUBLE, "double"},
42512798Swpaul			  {TOK_QUAD, "quadruple"},
4261897Swollman			  {TOK_STRING, "string"},
4271897Swollman			  {TOK_PROGRAM, "program"},
4281897Swollman			  {TOK_VERSION, "version"},
4291897Swollman			  {TOK_EOF, "??????"},
4301897Swollman};
4311897Swollman
43217142Sjkhstatic void
4331897Swollmanfindkind(mark, tokp)
4341897Swollman	char **mark;
4351897Swollman	token *tokp;
4361897Swollman{
4371897Swollman	int len;
4381897Swollman	token *s;
4391897Swollman	char *str;
4401897Swollman
4411897Swollman	str = *mark;
4421897Swollman	for (s = symbols; s->kind != TOK_EOF; s++) {
4431897Swollman		len = strlen(s->str);
4441897Swollman		if (strncmp(str, s->str, len) == 0) {
4451897Swollman			if (!isalnum(str[len]) && str[len] != '_') {
4461897Swollman				tokp->kind = s->kind;
4471897Swollman				tokp->str = s->str;
4481897Swollman				*mark = str + len;
4491897Swollman				return;
4501897Swollman			}
4511897Swollman		}
4521897Swollman	}
4531897Swollman	tokp->kind = TOK_IDENT;
4541897Swollman	for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
4551897Swollman	tokp->str = alloc(len + 1);
4561897Swollman	(void) strncpy(tokp->str, str, len);
4571897Swollman	tokp->str[len] = 0;
4581897Swollman	*mark = str + len;
4591897Swollman}
4601897Swollman
46117142Sjkhstatic int
4621897Swollmancppline(line)
4631897Swollman	char *line;
4641897Swollman{
4651897Swollman	return (line == curline && *line == '#');
4661897Swollman}
4671897Swollman
46817142Sjkhstatic int
4691897Swollmandirective(line)
4701897Swollman	char *line;
4711897Swollman{
4721897Swollman	return (line == curline && *line == '%');
4731897Swollman}
4741897Swollman
47517142Sjkhstatic void
4761897Swollmanprintdirective(line)
4771897Swollman	char *line;
4781897Swollman{
4791897Swollman	f_print(fout, "%s", line + 1);
4801897Swollman}
4811897Swollman
48217142Sjkhstatic void
4831897Swollmandocppline(line, lineno, fname)
4841897Swollman	char *line;
4851897Swollman	int *lineno;
4861897Swollman	char **fname;
4871897Swollman{
4881897Swollman	char *file;
4891897Swollman	int num;
4901897Swollman	char *p;
4911897Swollman
4921897Swollman	line++;
4931897Swollman	while (isspace(*line)) {
4941897Swollman		line++;
4951897Swollman	}
4961897Swollman	num = atoi(line);
4971897Swollman	while (isdigit(*line)) {
4981897Swollman		line++;
4991897Swollman	}
5001897Swollman	while (isspace(*line)) {
5011897Swollman		line++;
5021897Swollman	}
5031897Swollman	if (*line != '"') {
5041897Swollman		error("preprocessor error");
5051897Swollman	}
5061897Swollman	line++;
5071897Swollman	p = file = alloc(strlen(line) + 1);
5081897Swollman	while (*line && *line != '"') {
5091897Swollman		*p++ = *line++;
5101897Swollman	}
5111897Swollman	if (*line == 0) {
5121897Swollman		error("preprocessor error");
5131897Swollman	}
5141897Swollman	*p = 0;
5151897Swollman	if (*file == 0) {
5161897Swollman		*fname = NULL;
5171897Swollman	} else {
5181897Swollman		*fname = file;
5191897Swollman	}
5201897Swollman	*lineno = num - 1;
5211897Swollman}
522