xref: /netbsd-src/usr.bin/rpcgen/rpc_scan.c (revision 90a10bbb8a8567b5ff92d837ed65a5f8babd5045)
1*90a10bbbSdholland /*	$NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $	*/
28f0abce1Sglass /*
38f0abce1Sglass  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
48f0abce1Sglass  * unrestricted use provided that this legend is included on all tape
58f0abce1Sglass  * media and as a part of the software program in whole or part.  Users
68f0abce1Sglass  * may copy or modify Sun RPC without charge, but are not authorized
78f0abce1Sglass  * to license or distribute it to anyone else except as part of a product or
871a0fb45Spk  * program developed by the user or with the express written consent of
971a0fb45Spk  * Sun Microsystems, Inc.
108f0abce1Sglass  *
118f0abce1Sglass  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
128f0abce1Sglass  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
138f0abce1Sglass  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
148f0abce1Sglass  *
158f0abce1Sglass  * Sun RPC is provided with no support and without any obligation on the
168f0abce1Sglass  * part of Sun Microsystems, Inc. to assist in its use, correction,
178f0abce1Sglass  * modification or enhancement.
188f0abce1Sglass  *
198f0abce1Sglass  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
208f0abce1Sglass  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
218f0abce1Sglass  * OR ANY PART THEREOF.
228f0abce1Sglass  *
238f0abce1Sglass  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
248f0abce1Sglass  * or profits or other special, indirect and consequential damages, even if
258f0abce1Sglass  * Sun has been advised of the possibility of such damages.
268f0abce1Sglass  *
278f0abce1Sglass  * Sun Microsystems, Inc.
288f0abce1Sglass  * 2550 Garcia Avenue
298f0abce1Sglass  * Mountain View, California  94043
308f0abce1Sglass  */
3171a0fb45Spk 
32b2f78261Sjmc #if HAVE_NBTOOL_CONFIG_H
33b2f78261Sjmc #include "nbtool_config.h"
34b2f78261Sjmc #endif
35b2f78261Sjmc 
3693579481Schristos #include <sys/cdefs.h>
3776834aefStv #if defined(__RCSID) && !defined(lint)
3893579481Schristos #if 0
3971a0fb45Spk static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
4093579481Schristos #else
41*90a10bbbSdholland __RCSID("$NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $");
4293579481Schristos #endif
438f0abce1Sglass #endif
448f0abce1Sglass 
458f0abce1Sglass /*
468f0abce1Sglass  * rpc_scan.c, Scanner for the RPC protocol compiler
478f0abce1Sglass  * Copyright (C) 1987, Sun Microsystems, Inc.
488f0abce1Sglass  */
4971a0fb45Spk #include <stdlib.h>
508f0abce1Sglass #include <stdio.h>
518f0abce1Sglass #include <ctype.h>
5271a0fb45Spk #include <string.h>
538f0abce1Sglass #include "rpc_scan.h"
5471a0fb45Spk #include "rpc_parse.h"
558f0abce1Sglass #include "rpc_util.h"
568f0abce1Sglass 
578f0abce1Sglass #define startcomment(where) (where[0] == '/' && where[1] == '*')
588f0abce1Sglass #define endcomment(where) (where[-1] == '*' && where[0] == '/')
598f0abce1Sglass 
600213edf0Schristos static void unget_token(token *);
610213edf0Schristos static void findstrconst(char **, const char **);
620213edf0Schristos static void findchrconst(char **, const char **);
630213edf0Schristos static void findconst(char **, const char **);
640213edf0Schristos static void findkind(char **, token *);
650213edf0Schristos static int cppline(const char *);
660213edf0Schristos static int directive(const char *);
670213edf0Schristos static void printdirective(const char *);
680213edf0Schristos static void docppline(char *, int *, const char **);
6993579481Schristos 
708f0abce1Sglass static int pushed = 0;		/* is a token pushed */
718f0abce1Sglass static token lasttok;		/* last token, if pushed */
728f0abce1Sglass 
738f0abce1Sglass /*
748f0abce1Sglass  * scan expecting 1 given token
758f0abce1Sglass  */
768f0abce1Sglass void
scan(tok_kind expect,token * tokp)77e9067f11Sdholland scan(tok_kind expect, token *tokp)
788f0abce1Sglass {
798f0abce1Sglass 	get_token(tokp);
808f0abce1Sglass 	if (tokp->kind != expect) {
818f0abce1Sglass 		expected1(expect);
828f0abce1Sglass 	}
838f0abce1Sglass }
848f0abce1Sglass /*
8571a0fb45Spk  * scan expecting any of the 2 given tokens
868f0abce1Sglass  */
878f0abce1Sglass void
scan2(tok_kind expect1,tok_kind expect2,token * tokp)88e9067f11Sdholland scan2(tok_kind expect1, tok_kind expect2, token *tokp)
898f0abce1Sglass {
908f0abce1Sglass 	get_token(tokp);
918f0abce1Sglass 	if (tokp->kind != expect1 && tokp->kind != expect2) {
928f0abce1Sglass 		expected2(expect1, expect2);
938f0abce1Sglass 	}
948f0abce1Sglass }
958f0abce1Sglass /*
9671a0fb45Spk  * scan expecting any of the 3 given token
978f0abce1Sglass  */
988f0abce1Sglass void
scan3(tok_kind expect1,tok_kind expect2,tok_kind expect3,token * tokp)99e9067f11Sdholland scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
1008f0abce1Sglass {
1018f0abce1Sglass 	get_token(tokp);
1028f0abce1Sglass 	if (tokp->kind != expect1 && tokp->kind != expect2
1038f0abce1Sglass 	    && tokp->kind != expect3) {
1048f0abce1Sglass 		expected3(expect1, expect2, expect3);
1058f0abce1Sglass 	}
1068f0abce1Sglass }
1078f0abce1Sglass /*
1088f0abce1Sglass  * scan expecting a constant, possibly symbolic
1098f0abce1Sglass  */
1108f0abce1Sglass void
scan_num(token * tokp)111e9067f11Sdholland scan_num(token *tokp)
1128f0abce1Sglass {
1138f0abce1Sglass 	get_token(tokp);
1148f0abce1Sglass 	switch (tokp->kind) {
1158f0abce1Sglass 	case TOK_IDENT:
1168f0abce1Sglass 		break;
1178f0abce1Sglass 	default:
118ceecfabaSdholland 		error("Expected constant or identifier");
1198f0abce1Sglass 	}
1208f0abce1Sglass }
1218f0abce1Sglass /*
1228f0abce1Sglass  * Peek at the next token
1238f0abce1Sglass  */
1248f0abce1Sglass void
peek(token * tokp)125e9067f11Sdholland peek(token *tokp)
1268f0abce1Sglass {
1278f0abce1Sglass 	get_token(tokp);
1288f0abce1Sglass 	unget_token(tokp);
1298f0abce1Sglass }
1308f0abce1Sglass /*
1318f0abce1Sglass  * Peek at the next token and scan it if it matches what you expect
1328f0abce1Sglass  */
1338f0abce1Sglass int
peekscan(tok_kind expect,token * tokp)134e9067f11Sdholland peekscan(tok_kind expect, token *tokp)
1358f0abce1Sglass {
1368f0abce1Sglass 	peek(tokp);
1378f0abce1Sglass 	if (tokp->kind == expect) {
1388f0abce1Sglass 		get_token(tokp);
1398f0abce1Sglass 		return (1);
1408f0abce1Sglass 	}
1418f0abce1Sglass 	return (0);
1428f0abce1Sglass }
1438f0abce1Sglass /*
1448f0abce1Sglass  * Get the next token, printing out any directive that are encountered.
1458f0abce1Sglass  */
1468f0abce1Sglass void
get_token(token * tokp)147e9067f11Sdholland get_token(token *tokp)
1488f0abce1Sglass {
1498f0abce1Sglass 	int     commenting;
1508f0abce1Sglass 
1518f0abce1Sglass 	if (pushed) {
1528f0abce1Sglass 		pushed = 0;
1538f0abce1Sglass 		*tokp = lasttok;
1548f0abce1Sglass 		return;
1558f0abce1Sglass 	}
1568f0abce1Sglass 	commenting = 0;
1578f0abce1Sglass 	for (;;) {
1588f0abce1Sglass 		if (*where == 0) {
1598f0abce1Sglass 			for (;;) {
1608f0abce1Sglass 				if (!fgets(curline, MAXLINESIZE, fin)) {
1618f0abce1Sglass 					tokp->kind = TOK_EOF;
1628f0abce1Sglass 					*where = 0;
1638f0abce1Sglass 					return;
1648f0abce1Sglass 				}
1658f0abce1Sglass 				linenum++;
1668f0abce1Sglass 				if (commenting) {
1678f0abce1Sglass 					break;
16899071d1bSlukem 				} else
16999071d1bSlukem 					if (cppline(curline)) {
1708f0abce1Sglass 						docppline(curline, &linenum,
1718f0abce1Sglass 						    &infilename);
17299071d1bSlukem 					} else
17399071d1bSlukem 						if (directive(curline)) {
1748f0abce1Sglass 							printdirective(curline);
1758f0abce1Sglass 						} else {
1768f0abce1Sglass 							break;
1778f0abce1Sglass 						}
1788f0abce1Sglass 			}
1798f0abce1Sglass 			where = curline;
18099071d1bSlukem 		} else
181e4ac7024Schristos 			if (isspace((unsigned char)*where)) {
182e4ac7024Schristos 				while (isspace((unsigned char)*where)) {
1838f0abce1Sglass 					where++;	/* eat */
1848f0abce1Sglass 				}
18599071d1bSlukem 			} else
18699071d1bSlukem 				if (commenting) {
18771a0fb45Spk 					for (where++; *where; where++) {
1888f0abce1Sglass 						if (endcomment(where)) {
1898f0abce1Sglass 							where++;
1908f0abce1Sglass 							commenting--;
19171a0fb45Spk 							break;
19271a0fb45Spk 						}
1938f0abce1Sglass 					}
19499071d1bSlukem 				} else
19599071d1bSlukem 					if (startcomment(where)) {
1968f0abce1Sglass 						where += 2;
1978f0abce1Sglass 						commenting++;
1988f0abce1Sglass 					} else {
1998f0abce1Sglass 						break;
2008f0abce1Sglass 					}
2018f0abce1Sglass 	}
2028f0abce1Sglass 
2038f0abce1Sglass 	/*
2048f0abce1Sglass 	 * 'where' is not whitespace, comment or directive Must be a token!
2058f0abce1Sglass 	 */
2068f0abce1Sglass 	switch (*where) {
2078f0abce1Sglass 	case ':':
2088f0abce1Sglass 		tokp->kind = TOK_COLON;
2098f0abce1Sglass 		where++;
2108f0abce1Sglass 		break;
2118f0abce1Sglass 	case ';':
2128f0abce1Sglass 		tokp->kind = TOK_SEMICOLON;
2138f0abce1Sglass 		where++;
2148f0abce1Sglass 		break;
2158f0abce1Sglass 	case ',':
2168f0abce1Sglass 		tokp->kind = TOK_COMMA;
2178f0abce1Sglass 		where++;
2188f0abce1Sglass 		break;
2198f0abce1Sglass 	case '=':
2208f0abce1Sglass 		tokp->kind = TOK_EQUAL;
2218f0abce1Sglass 		where++;
2228f0abce1Sglass 		break;
2238f0abce1Sglass 	case '*':
2248f0abce1Sglass 		tokp->kind = TOK_STAR;
2258f0abce1Sglass 		where++;
2268f0abce1Sglass 		break;
2278f0abce1Sglass 	case '[':
2288f0abce1Sglass 		tokp->kind = TOK_LBRACKET;
2298f0abce1Sglass 		where++;
2308f0abce1Sglass 		break;
2318f0abce1Sglass 	case ']':
2328f0abce1Sglass 		tokp->kind = TOK_RBRACKET;
2338f0abce1Sglass 		where++;
2348f0abce1Sglass 		break;
2358f0abce1Sglass 	case '{':
2368f0abce1Sglass 		tokp->kind = TOK_LBRACE;
2378f0abce1Sglass 		where++;
2388f0abce1Sglass 		break;
2398f0abce1Sglass 	case '}':
2408f0abce1Sglass 		tokp->kind = TOK_RBRACE;
2418f0abce1Sglass 		where++;
2428f0abce1Sglass 		break;
2438f0abce1Sglass 	case '(':
2448f0abce1Sglass 		tokp->kind = TOK_LPAREN;
2458f0abce1Sglass 		where++;
2468f0abce1Sglass 		break;
2478f0abce1Sglass 	case ')':
2488f0abce1Sglass 		tokp->kind = TOK_RPAREN;
2498f0abce1Sglass 		where++;
2508f0abce1Sglass 		break;
2518f0abce1Sglass 	case '<':
2528f0abce1Sglass 		tokp->kind = TOK_LANGLE;
2538f0abce1Sglass 		where++;
2548f0abce1Sglass 		break;
2558f0abce1Sglass 	case '>':
2568f0abce1Sglass 		tokp->kind = TOK_RANGLE;
2578f0abce1Sglass 		where++;
2588f0abce1Sglass 		break;
2598f0abce1Sglass 
2608f0abce1Sglass 	case '"':
2618f0abce1Sglass 		tokp->kind = TOK_STRCONST;
2628f0abce1Sglass 		findstrconst(&where, &tokp->str);
2638f0abce1Sglass 		break;
26471a0fb45Spk 	case '\'':
26571a0fb45Spk 		tokp->kind = TOK_CHARCONST;
26671a0fb45Spk 		findchrconst(&where, &tokp->str);
26771a0fb45Spk 		break;
2688f0abce1Sglass 
2698f0abce1Sglass 	case '-':
2708f0abce1Sglass 	case '0':
2718f0abce1Sglass 	case '1':
2728f0abce1Sglass 	case '2':
2738f0abce1Sglass 	case '3':
2748f0abce1Sglass 	case '4':
2758f0abce1Sglass 	case '5':
2768f0abce1Sglass 	case '6':
2778f0abce1Sglass 	case '7':
2788f0abce1Sglass 	case '8':
2798f0abce1Sglass 	case '9':
2808f0abce1Sglass 		tokp->kind = TOK_IDENT;
2818f0abce1Sglass 		findconst(&where, &tokp->str);
2828f0abce1Sglass 		break;
2838f0abce1Sglass 
2848f0abce1Sglass 	default:
285e4ac7024Schristos 		if (!(isalpha((unsigned char)*where) || *where == '_')) {
286e4ac7024Schristos 			if (isprint((unsigned char)*where)) {
287*90a10bbbSdholland 				error("Illegal character '%c' in file", *where);
2888f0abce1Sglass 			} else {
289*90a10bbbSdholland 				error("Illegal character %d in file", *where);
2908f0abce1Sglass 			}
2918f0abce1Sglass 		}
2928f0abce1Sglass 		findkind(&where, tokp);
2938f0abce1Sglass 		break;
2948f0abce1Sglass 	}
2958f0abce1Sglass }
2968f0abce1Sglass 
29793579481Schristos static void
unget_token(token * tokp)298e9067f11Sdholland unget_token(token *tokp)
2998f0abce1Sglass {
3008f0abce1Sglass 	lasttok = *tokp;
3018f0abce1Sglass 	pushed = 1;
3028f0abce1Sglass }
3038f0abce1Sglass 
30493579481Schristos static void
findstrconst(char ** str,const char ** val)305e9067f11Sdholland findstrconst(char **str, const char **val)
3068f0abce1Sglass {
3078f0abce1Sglass 	char *p;
3088f0abce1Sglass 	int     size;
309e9067f11Sdholland 	char *tmp;
3108f0abce1Sglass 
3118f0abce1Sglass 	p = *str;
3128f0abce1Sglass 	do {
31393579481Schristos 		p++;
3148f0abce1Sglass 	} while (*p && *p != '"');
3158f0abce1Sglass 	if (*p == 0) {
316ceecfabaSdholland 		error("Unterminated string constant");
3178f0abce1Sglass 	}
3188f0abce1Sglass 	p++;
3198f0abce1Sglass 	size = p - *str;
320e9067f11Sdholland 	tmp = alloc(size + 1);
321e9067f11Sdholland 	(void) strncpy(tmp, *str, size);
322e9067f11Sdholland 	tmp[size] = 0;
323e9067f11Sdholland 	*val = tmp;
3248f0abce1Sglass 	*str = p;
3258f0abce1Sglass }
3268f0abce1Sglass 
32793579481Schristos static void
findchrconst(char ** str,const char ** val)328e9067f11Sdholland findchrconst(char **str, const char **val)
32971a0fb45Spk {
33071a0fb45Spk 	char *p;
33171a0fb45Spk 	int     size;
332e9067f11Sdholland 	char *tmp;
33371a0fb45Spk 
33471a0fb45Spk 	p = *str;
33571a0fb45Spk 	do {
33693579481Schristos 		p++;
33771a0fb45Spk 	} while (*p && *p != '\'');
33871a0fb45Spk 	if (*p == 0) {
339ceecfabaSdholland 		error("Unterminated string constant");
34071a0fb45Spk 	}
34171a0fb45Spk 	p++;
34271a0fb45Spk 	size = p - *str;
34371a0fb45Spk 	if (size != 3) {
344ceecfabaSdholland 		error("Empty character");
34571a0fb45Spk 	}
346e9067f11Sdholland 	tmp = alloc(size + 1);
347e9067f11Sdholland 	(void) strncpy(tmp, *str, size);
348e9067f11Sdholland 	tmp[size] = 0;
349e9067f11Sdholland 	*val = tmp;
35071a0fb45Spk 	*str = p;
35171a0fb45Spk }
35271a0fb45Spk 
35393579481Schristos static void
findconst(char ** str,const char ** val)354e9067f11Sdholland findconst(char **str, const char **val)
3558f0abce1Sglass {
3568f0abce1Sglass 	char *p;
3578f0abce1Sglass 	int     size;
358e9067f11Sdholland 	char *tmp;
3598f0abce1Sglass 
3608f0abce1Sglass 	p = *str;
3618f0abce1Sglass 	if (*p == '0' && *(p + 1) == 'x') {
3628f0abce1Sglass 		p++;
3638f0abce1Sglass 		do {
3648f0abce1Sglass 			p++;
365e4ac7024Schristos 		} while (isxdigit((unsigned char)*p));
3668f0abce1Sglass 	} else {
3678f0abce1Sglass 		do {
3688f0abce1Sglass 			p++;
369e4ac7024Schristos 		} while (isdigit((unsigned char)*p));
3708f0abce1Sglass 	}
3718f0abce1Sglass 	size = p - *str;
372e9067f11Sdholland 	tmp = alloc(size + 1);
373e9067f11Sdholland 	(void) strncpy(tmp, *str, size);
374e9067f11Sdholland 	tmp[size] = 0;
375e9067f11Sdholland 	*val = tmp;
3768f0abce1Sglass 	*str = p;
3778f0abce1Sglass }
3788f0abce1Sglass 
379e9067f11Sdholland static const token symbols[] = {
3808f0abce1Sglass 	{TOK_CONST, "const"},
3818f0abce1Sglass 	{TOK_UNION, "union"},
3828f0abce1Sglass 	{TOK_SWITCH, "switch"},
3838f0abce1Sglass 	{TOK_CASE, "case"},
3848f0abce1Sglass 	{TOK_DEFAULT, "default"},
3858f0abce1Sglass 	{TOK_STRUCT, "struct"},
3868f0abce1Sglass 	{TOK_TYPEDEF, "typedef"},
3878f0abce1Sglass 	{TOK_ENUM, "enum"},
3888f0abce1Sglass 	{TOK_OPAQUE, "opaque"},
3898f0abce1Sglass 	{TOK_BOOL, "bool"},
3908f0abce1Sglass 	{TOK_VOID, "void"},
3918f0abce1Sglass 	{TOK_CHAR, "char"},
3928f0abce1Sglass 	{TOK_INT, "int"},
3938f0abce1Sglass 	{TOK_UNSIGNED, "unsigned"},
3948f0abce1Sglass 	{TOK_SHORT, "short"},
3958f0abce1Sglass 	{TOK_LONG, "long"},
3963cad8d1dSginsbach 	{TOK_HYPER, "hyper"},
3978f0abce1Sglass 	{TOK_FLOAT, "float"},
3988f0abce1Sglass 	{TOK_DOUBLE, "double"},
3993cad8d1dSginsbach 	{TOK_QUAD, "quadruple"},
4008f0abce1Sglass 	{TOK_STRING, "string"},
4018f0abce1Sglass 	{TOK_PROGRAM, "program"},
4028f0abce1Sglass 	{TOK_VERSION, "version"},
4038f0abce1Sglass 	{TOK_EOF, "??????"},
4048f0abce1Sglass };
4058f0abce1Sglass 
40693579481Schristos static void
findkind(char ** mark,token * tokp)407e9067f11Sdholland findkind(char **mark, token *tokp)
4088f0abce1Sglass {
4098f0abce1Sglass 	int     len;
410e9067f11Sdholland 	const token *s;
4118f0abce1Sglass 	char *str;
412e9067f11Sdholland 	char *tmp;
4138f0abce1Sglass 
4148f0abce1Sglass 	str = *mark;
4158f0abce1Sglass 	for (s = symbols; s->kind != TOK_EOF; s++) {
4168f0abce1Sglass 		len = strlen(s->str);
4178f0abce1Sglass 		if (strncmp(str, s->str, len) == 0) {
418e4ac7024Schristos 			if (!isalnum((unsigned char)str[len]) &&
419e4ac7024Schristos 			    str[len] != '_') {
4208f0abce1Sglass 				tokp->kind = s->kind;
4218f0abce1Sglass 				tokp->str = s->str;
4228f0abce1Sglass 				*mark = str + len;
4238f0abce1Sglass 				return;
4248f0abce1Sglass 			}
4258f0abce1Sglass 		}
4268f0abce1Sglass 	}
4278f0abce1Sglass 	tokp->kind = TOK_IDENT;
428e4ac7024Schristos 	for (len = 0; isalnum((unsigned char)str[len]) ||
429e4ac7024Schristos 	    str[len] == '_'; len++);
430e9067f11Sdholland 	tmp = alloc(len + 1);
431e9067f11Sdholland 	(void) strncpy(tmp, str, len);
432e9067f11Sdholland 	tmp[len] = 0;
433e9067f11Sdholland 	tokp->str = tmp;
4348f0abce1Sglass 	*mark = str + len;
4358f0abce1Sglass }
4368f0abce1Sglass 
43793579481Schristos static int
cppline(const char * line)438e9067f11Sdholland cppline(const char *line)
4398f0abce1Sglass {
4408f0abce1Sglass 	return (line == curline && *line == '#');
4418f0abce1Sglass }
4428f0abce1Sglass 
44393579481Schristos static int
directive(const char * line)444e9067f11Sdholland directive(const char *line)
4458f0abce1Sglass {
4468f0abce1Sglass 	return (line == curline && *line == '%');
4478f0abce1Sglass }
4488f0abce1Sglass 
44993579481Schristos static void
printdirective(const char * line)450e9067f11Sdholland printdirective(const char *line)
4518f0abce1Sglass {
4528f0abce1Sglass 	f_print(fout, "%s", line + 1);
4538f0abce1Sglass }
4548f0abce1Sglass 
45593579481Schristos static void
docppline(char * line,int * lineno,const char ** fname)456e9067f11Sdholland docppline(char *line, int *lineno, const char **fname)
4578f0abce1Sglass {
4588f0abce1Sglass 	char   *file;
4598f0abce1Sglass 	int     num;
4608f0abce1Sglass 	char   *p;
4618f0abce1Sglass 
4628f0abce1Sglass 	line++;
463e4ac7024Schristos 	while (isspace((unsigned char)*line)) {
4648f0abce1Sglass 		line++;
4658f0abce1Sglass 	}
4668f0abce1Sglass 	num = atoi(line);
467e4ac7024Schristos 	while (isdigit((unsigned char)*line)) {
4688f0abce1Sglass 		line++;
4698f0abce1Sglass 	}
470e4ac7024Schristos 	while (isspace((unsigned char)*line)) {
4718f0abce1Sglass 		line++;
4728f0abce1Sglass 	}
4738f0abce1Sglass 	if (*line != '"') {
474ceecfabaSdholland 		error("Preprocessor error");
4758f0abce1Sglass 	}
4768f0abce1Sglass 	line++;
4778f0abce1Sglass 	p = file = alloc(strlen(line) + 1);
4788f0abce1Sglass 	while (*line && *line != '"') {
4798f0abce1Sglass 		*p++ = *line++;
4808f0abce1Sglass 	}
4818f0abce1Sglass 	if (*line == 0) {
482ceecfabaSdholland 		error("Preprocessor error");
4838f0abce1Sglass 	}
4848f0abce1Sglass 	*p = 0;
4858f0abce1Sglass 	if (*file == 0) {
4868f0abce1Sglass 		*fname = NULL;
4873e7dafb5Selad 		free(file);
4888f0abce1Sglass 	} else {
4898f0abce1Sglass 		*fname = file;
4908f0abce1Sglass 	}
4918f0abce1Sglass 	*lineno = num - 1;
4928f0abce1Sglass }
493