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.
8100441Scharnier *
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.
12100441Scharnier *
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.
16100441Scharnier *
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.
20100441Scharnier *
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.
24100441Scharnier *
251897Swollman * Sun Microsystems, Inc.
261897Swollman * 2550 Garcia Avenue
271897Swollman * Mountain View, California  94043
281897Swollman */
2912798Swpaul
30100441Scharnier#if 0
311897Swollman#ifndef lint
32146833Sstefanf#ident	"@(#)rpc_scan.c	1.13	93/07/05 SMI"
3312798Swpaulstatic char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
341897Swollman#endif
3599979Salfred#endif
361897Swollman
37100441Scharnier#include <sys/cdefs.h>
38100441Scharnier__FBSDID("$FreeBSD$");
39100441Scharnier
401897Swollman/*
41100441Scharnier * rpc_scan.c, Scanner for the RPC protocol compiler
42100441Scharnier * Copyright (C) 1987, Sun Microsystems, Inc.
431897Swollman */
4412798Swpaul
4567191Sbrian#include <sys/types.h>
4667191Sbrian
4712798Swpaul#include <sys/wait.h>
481897Swollman#include <stdio.h>
491897Swollman#include <ctype.h>
5012798Swpaul#include <string.h>
51152398Sdwmalone#include "rpc_parse.h"
521897Swollman#include "rpc_scan.h"
531897Swollman#include "rpc_util.h"
541897Swollman
551897Swollman#define startcomment(where) (where[0] == '/' && where[1] == '*')
561897Swollman#define endcomment(where) (where[-1] == '*' && where[0] == '/')
571897Swollman
581897Swollmanstatic int pushed = 0;	/* is a token pushed */
591897Swollmanstatic token lasttok;	/* last token, if pushed */
601897Swollman
6192921Simpstatic void unget_token( token * );
62152398Sdwmalonestatic void findstrconst(char **, const char **);
63152398Sdwmalonestatic void findchrconst(char **, const char **);
64152398Sdwmalonestatic void findconst(char **, const char **);
6592921Simpstatic void findkind( char **, token * );
6692921Simpstatic int cppline( char * );
6792921Simpstatic int directive( char * );
6892921Simpstatic void printdirective( char * );
69152398Sdwmalonestatic void docppline(char *, int *, const char **);
7012798Swpaul
711897Swollman/*
72100441Scharnier * scan expecting 1 given token
731897Swollman */
741897Swollmanvoid
75152398Sdwmalonescan(tok_kind expect, token *tokp)
761897Swollman{
771897Swollman	get_token(tokp);
781897Swollman	if (tokp->kind != expect) {
791897Swollman		expected1(expect);
801897Swollman	}
811897Swollman}
821897Swollman
831897Swollman/*
84100441Scharnier * scan expecting any of the 2 given tokens
851897Swollman */
861897Swollmanvoid
87152398Sdwmalonescan2(tok_kind expect1, tok_kind expect2, token *tokp)
881897Swollman{
891897Swollman	get_token(tokp);
901897Swollman	if (tokp->kind != expect1 && tokp->kind != expect2) {
911897Swollman		expected2(expect1, expect2);
921897Swollman	}
931897Swollman}
941897Swollman
951897Swollman/*
96100441Scharnier * scan expecting any of the 3 given token
971897Swollman */
981897Swollmanvoid
99152398Sdwmalonescan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
1001897Swollman{
1011897Swollman	get_token(tokp);
1021897Swollman	if (tokp->kind != expect1 && tokp->kind != expect2
1031897Swollman	    && tokp->kind != expect3) {
1041897Swollman		expected3(expect1, expect2, expect3);
1051897Swollman	}
1061897Swollman}
1071897Swollman
1081897Swollman/*
109100441Scharnier * scan expecting a constant, possibly symbolic
1101897Swollman */
1111897Swollmanvoid
112152398Sdwmalonescan_num(token *tokp)
1131897Swollman{
1141897Swollman	get_token(tokp);
1151897Swollman	switch (tokp->kind) {
1161897Swollman	case TOK_IDENT:
1171897Swollman		break;
1181897Swollman	default:
1191897Swollman		error("constant or identifier expected");
1201897Swollman	}
1211897Swollman}
1221897Swollman
1231897Swollman/*
124100441Scharnier * Peek at the next token
1251897Swollman */
1261897Swollmanvoid
127152398Sdwmalonepeek(token *tokp)
1281897Swollman{
1291897Swollman	get_token(tokp);
1301897Swollman	unget_token(tokp);
1311897Swollman}
1321897Swollman
1331897Swollman/*
134100441Scharnier * Peek at the next token and scan it if it matches what you expect
1351897Swollman */
1361897Swollmanint
137152398Sdwmalonepeekscan(tok_kind expect, token *tokp)
1381897Swollman{
1391897Swollman	peek(tokp);
1401897Swollman	if (tokp->kind == expect) {
1411897Swollman		get_token(tokp);
1421897Swollman		return (1);
1431897Swollman	}
1441897Swollman	return (0);
1451897Swollman}
1461897Swollman
1471897Swollman/*
148100441Scharnier * Get the next token, printing out any directive that are encountered.
1491897Swollman */
1501897Swollmanvoid
151152398Sdwmaloneget_token(token *tokp)
1521897Swollman{
1531897Swollman	int commenting;
15412798Swpaul	int stat = 0;
15512798Swpaul
15612798Swpaul
1571897Swollman	if (pushed) {
1581897Swollman		pushed = 0;
1591897Swollman		*tokp = lasttok;
1601897Swollman		return;
1611897Swollman	}
1621897Swollman	commenting = 0;
1631897Swollman	for (;;) {
1641897Swollman		if (*where == 0) {
1651897Swollman			for (;;) {
1661897Swollman				if (!fgets(curline, MAXLINESIZE, fin)) {
1671897Swollman					tokp->kind = TOK_EOF;
16812798Swpaul					/* now check if cpp returned non NULL value */
16912798Swpaul					waitpid(childpid, &stat, WUNTRACED);
17012798Swpaul					if (stat > 0) {
17112798Swpaul					/* Set return value from rpcgen */
17212798Swpaul						nonfatalerrors = stat >> 8;
17312798Swpaul					}
1741897Swollman					*where = 0;
1751897Swollman					return;
1761897Swollman				}
1771897Swollman				linenum++;
1781897Swollman				if (commenting) {
1791897Swollman					break;
1801897Swollman				} else if (cppline(curline)) {
181100441Scharnier					docppline(curline, &linenum,
1821897Swollman						  &infilename);
1831897Swollman				} else if (directive(curline)) {
1841897Swollman					printdirective(curline);
1851897Swollman				} else {
1861897Swollman					break;
1871897Swollman				}
1881897Swollman			}
1891897Swollman			where = curline;
1901897Swollman		} else if (isspace(*where)) {
1911897Swollman			while (isspace(*where)) {
1921897Swollman				where++;	/* eat */
1931897Swollman			}
1941897Swollman		} else if (commenting) {
19512798Swpaul			for (where++; *where; where++) {
19612798Swpaul				if (endcomment(where)) {
19712798Swpaul					where++;
19812798Swpaul					commenting--;
19912798Swpaul					break;
20012798Swpaul				}
2011897Swollman			}
2021897Swollman		} else if (startcomment(where)) {
2031897Swollman			where += 2;
2041897Swollman			commenting++;
2051897Swollman		} else {
2061897Swollman			break;
2071897Swollman		}
2081897Swollman	}
2091897Swollman
2101897Swollman	/*
211100441Scharnier	 * 'where' is not whitespace, comment or directive Must be a token!
2121897Swollman	 */
2131897Swollman	switch (*where) {
2141897Swollman	case ':':
2151897Swollman		tokp->kind = TOK_COLON;
2161897Swollman		where++;
2171897Swollman		break;
2181897Swollman	case ';':
2191897Swollman		tokp->kind = TOK_SEMICOLON;
2201897Swollman		where++;
2211897Swollman		break;
2221897Swollman	case ',':
2231897Swollman		tokp->kind = TOK_COMMA;
2241897Swollman		where++;
2251897Swollman		break;
2261897Swollman	case '=':
2271897Swollman		tokp->kind = TOK_EQUAL;
2281897Swollman		where++;
2291897Swollman		break;
2301897Swollman	case '*':
2311897Swollman		tokp->kind = TOK_STAR;
2321897Swollman		where++;
2331897Swollman		break;
2341897Swollman	case '[':
2351897Swollman		tokp->kind = TOK_LBRACKET;
2361897Swollman		where++;
2371897Swollman		break;
2381897Swollman	case ']':
2391897Swollman		tokp->kind = TOK_RBRACKET;
2401897Swollman		where++;
2411897Swollman		break;
2421897Swollman	case '{':
2431897Swollman		tokp->kind = TOK_LBRACE;
2441897Swollman		where++;
2451897Swollman		break;
2461897Swollman	case '}':
2471897Swollman		tokp->kind = TOK_RBRACE;
2481897Swollman		where++;
2491897Swollman		break;
2501897Swollman	case '(':
2511897Swollman		tokp->kind = TOK_LPAREN;
2521897Swollman		where++;
2531897Swollman		break;
2541897Swollman	case ')':
2551897Swollman		tokp->kind = TOK_RPAREN;
2561897Swollman		where++;
2571897Swollman		break;
2581897Swollman	case '<':
2591897Swollman		tokp->kind = TOK_LANGLE;
2601897Swollman		where++;
2611897Swollman		break;
2621897Swollman	case '>':
2631897Swollman		tokp->kind = TOK_RANGLE;
2641897Swollman		where++;
2651897Swollman		break;
2661897Swollman
2671897Swollman	case '"':
2681897Swollman		tokp->kind = TOK_STRCONST;
2691897Swollman		findstrconst(&where, &tokp->str);
2701897Swollman		break;
27112798Swpaul	case '\'':
27212798Swpaul		tokp->kind = TOK_CHARCONST;
27312798Swpaul		findchrconst(&where, &tokp->str);
27412798Swpaul		break;
2751897Swollman
2761897Swollman	case '-':
2771897Swollman	case '0':
2781897Swollman	case '1':
2791897Swollman	case '2':
2801897Swollman	case '3':
2811897Swollman	case '4':
2821897Swollman	case '5':
2831897Swollman	case '6':
2841897Swollman	case '7':
2851897Swollman	case '8':
2861897Swollman	case '9':
2871897Swollman		tokp->kind = TOK_IDENT;
2881897Swollman		findconst(&where, &tokp->str);
2891897Swollman		break;
2901897Swollman
2911897Swollman	default:
2921897Swollman		if (!(isalpha(*where) || *where == '_')) {
2931897Swollman			char buf[100];
2941897Swollman			char *p;
2951897Swollman
2961897Swollman			s_print(buf, "illegal character in file: ");
2971897Swollman			p = buf + strlen(buf);
2981897Swollman			if (isprint(*where)) {
2991897Swollman				s_print(p, "%c", *where);
3001897Swollman			} else {
3011897Swollman				s_print(p, "%d", *where);
3021897Swollman			}
3031897Swollman			error(buf);
3041897Swollman		}
3051897Swollman		findkind(&where, tokp);
3061897Swollman		break;
3071897Swollman	}
3081897Swollman}
3091897Swollman
31017142Sjkhstatic void
311152398Sdwmaloneunget_token(token *tokp)
3121897Swollman{
3131897Swollman	lasttok = *tokp;
3141897Swollman	pushed = 1;
3151897Swollman}
3161897Swollman
31717142Sjkhstatic void
318152398Sdwmalonefindstrconst(char **str, const char **val)
3191897Swollman{
3201897Swollman	char *p;
321152398Sdwmalone	char *tmp;
3221897Swollman	int size;
3231897Swollman
3241897Swollman	p = *str;
3251897Swollman	do {
32617142Sjkh		p++;
3271897Swollman	} while (*p && *p != '"');
3281897Swollman	if (*p == 0) {
3291897Swollman		error("unterminated string constant");
3301897Swollman	}
3311897Swollman	p++;
332223922Sdelphij	size = p - *str + 1;
333223922Sdelphij	tmp = xmalloc(size);
334223922Sdelphij	(void) strlcpy(tmp, *str, size);
335152398Sdwmalone	*val = tmp;
3361897Swollman	*str = p;
3371897Swollman}
3381897Swollman
33917142Sjkhstatic void
340152398Sdwmalonefindchrconst(char **str, const char **val)
34112798Swpaul{
34212798Swpaul	char *p;
343152398Sdwmalone	char *tmp;
34412798Swpaul	int size;
34512798Swpaul
34612798Swpaul	p = *str;
34712798Swpaul	do {
34817142Sjkh		p++;
34912798Swpaul	} while (*p && *p != '\'');
35012798Swpaul	if (*p == 0) {
35112798Swpaul		error("unterminated string constant");
35212798Swpaul	}
35312798Swpaul	p++;
354223922Sdelphij	size = p - *str + 1;
355223922Sdelphij	if (size != 4) {
35612798Swpaul		error("empty char string");
35712798Swpaul	}
358223922Sdelphij	tmp = xmalloc(size);
359223922Sdelphij	(void) strlcpy(tmp, *str, size);
360152398Sdwmalone	*val = tmp;
36112798Swpaul	*str = p;
36212798Swpaul}
36312798Swpaul
36417142Sjkhstatic void
365152398Sdwmalonefindconst(char **str, const char **val)
3661897Swollman{
3671897Swollman	char *p;
368152398Sdwmalone	char *tmp;
3691897Swollman	int size;
3701897Swollman
3711897Swollman	p = *str;
3721897Swollman	if (*p == '0' && *(p + 1) == 'x') {
3731897Swollman		p++;
3741897Swollman		do {
3751897Swollman			p++;
3761897Swollman		} while (isxdigit(*p));
3771897Swollman	} else {
3781897Swollman		do {
3791897Swollman			p++;
3801897Swollman		} while (isdigit(*p));
3811897Swollman	}
382223922Sdelphij	size = p - *str + 1;
383223922Sdelphij	tmp = xmalloc(size);
384223922Sdelphij	(void) strlcpy(tmp, *str, size);
385152398Sdwmalone	*val = tmp;
3861897Swollman	*str = p;
3871897Swollman}
3881897Swollman
3891897Swollmanstatic token symbols[] = {
3901897Swollman			  {TOK_CONST, "const"},
3911897Swollman			  {TOK_UNION, "union"},
3921897Swollman			  {TOK_SWITCH, "switch"},
3931897Swollman			  {TOK_CASE, "case"},
3941897Swollman			  {TOK_DEFAULT, "default"},
3951897Swollman			  {TOK_STRUCT, "struct"},
3961897Swollman			  {TOK_TYPEDEF, "typedef"},
3971897Swollman			  {TOK_ENUM, "enum"},
3981897Swollman			  {TOK_OPAQUE, "opaque"},
3991897Swollman			  {TOK_BOOL, "bool"},
4001897Swollman			  {TOK_VOID, "void"},
4011897Swollman			  {TOK_CHAR, "char"},
4021897Swollman			  {TOK_INT, "int"},
4031897Swollman			  {TOK_UNSIGNED, "unsigned"},
4041897Swollman			  {TOK_SHORT, "short"},
4051897Swollman			  {TOK_LONG, "long"},
40612798Swpaul			  {TOK_HYPER, "hyper"},
4071897Swollman			  {TOK_FLOAT, "float"},
4081897Swollman			  {TOK_DOUBLE, "double"},
40912798Swpaul			  {TOK_QUAD, "quadruple"},
4101897Swollman			  {TOK_STRING, "string"},
4111897Swollman			  {TOK_PROGRAM, "program"},
4121897Swollman			  {TOK_VERSION, "version"},
4131897Swollman			  {TOK_EOF, "??????"},
4141897Swollman};
4151897Swollman
41617142Sjkhstatic void
417152398Sdwmalonefindkind(char **mark, token *tokp)
4181897Swollman{
4191897Swollman	int len;
4201897Swollman	token *s;
421152398Sdwmalone	char *str, *tmp;
4221897Swollman
4231897Swollman	str = *mark;
4241897Swollman	for (s = symbols; s->kind != TOK_EOF; s++) {
4251897Swollman		len = strlen(s->str);
4261897Swollman		if (strncmp(str, s->str, len) == 0) {
4271897Swollman			if (!isalnum(str[len]) && str[len] != '_') {
4281897Swollman				tokp->kind = s->kind;
4291897Swollman				tokp->str = s->str;
4301897Swollman				*mark = str + len;
4311897Swollman				return;
4321897Swollman			}
4331897Swollman		}
4341897Swollman	}
4351897Swollman	tokp->kind = TOK_IDENT;
4361897Swollman	for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
437152398Sdwmalone	tmp = xmalloc(len + 1);
438223922Sdelphij	(void) strlcpy(tmp, str, len + 1);
439152398Sdwmalone	tokp->str = tmp;
4401897Swollman	*mark = str + len;
4411897Swollman}
4421897Swollman
44317142Sjkhstatic int
444152398Sdwmalonecppline(char *line)
4451897Swollman{
4461897Swollman	return (line == curline && *line == '#');
4471897Swollman}
4481897Swollman
44917142Sjkhstatic int
450152398Sdwmalonedirective(char *line)
4511897Swollman{
4521897Swollman	return (line == curline && *line == '%');
4531897Swollman}
4541897Swollman
45517142Sjkhstatic void
456152398Sdwmaloneprintdirective(char *line)
4571897Swollman{
4581897Swollman	f_print(fout, "%s", line + 1);
4591897Swollman}
4601897Swollman
46117142Sjkhstatic void
462152398Sdwmalonedocppline(char *line, int *lineno, const char **fname)
4631897Swollman{
4641897Swollman	char *file;
4651897Swollman	int num;
4661897Swollman	char *p;
4671897Swollman
4681897Swollman	line++;
4691897Swollman	while (isspace(*line)) {
4701897Swollman		line++;
4711897Swollman	}
4721897Swollman	num = atoi(line);
4731897Swollman	while (isdigit(*line)) {
4741897Swollman		line++;
4751897Swollman	}
4761897Swollman	while (isspace(*line)) {
4771897Swollman		line++;
4781897Swollman	}
4791897Swollman	if (*line != '"') {
4801897Swollman		error("preprocessor error");
4811897Swollman	}
4821897Swollman	line++;
483100441Scharnier	p = file = xmalloc(strlen(line) + 1);
4841897Swollman	while (*line && *line != '"') {
4851897Swollman		*p++ = *line++;
4861897Swollman	}
4871897Swollman	if (*line == 0) {
4881897Swollman		error("preprocessor error");
4891897Swollman	}
4901897Swollman	*p = 0;
4911897Swollman	if (*file == 0) {
4921897Swollman		*fname = NULL;
4931897Swollman	} else {
4941897Swollman		*fname = file;
4951897Swollman	}
4961897Swollman	*lineno = num - 1;
4971897Swollman}
498