10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*9497SJordan.Brown@Sun.COM * Common Development and Distribution License (the "License").
6*9497SJordan.Brown@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
20132Srobinson */
21132Srobinson
22132Srobinson /*
23*9497SJordan.Brown@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988
300Sstevel@tonic-gate * The Regents of the University of California
310Sstevel@tonic-gate * All Rights Reserved
320Sstevel@tonic-gate *
330Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from
340Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its
350Sstevel@tonic-gate * contributors.
360Sstevel@tonic-gate */
370Sstevel@tonic-gate
380Sstevel@tonic-gate /*
39132Srobinson * rpc_scan.c, Scanner for the RPC protocol compiler
400Sstevel@tonic-gate */
410Sstevel@tonic-gate
420Sstevel@tonic-gate #include <sys/wait.h>
430Sstevel@tonic-gate #include <stdio.h>
440Sstevel@tonic-gate #include <ctype.h>
450Sstevel@tonic-gate #include <string.h>
46132Srobinson #include <strings.h>
470Sstevel@tonic-gate #include "rpc_scan.h"
480Sstevel@tonic-gate #include "rpc_parse.h"
490Sstevel@tonic-gate #include "rpc_util.h"
500Sstevel@tonic-gate
51132Srobinson #define startcomment(where) (where[0] == '/' && where[1] == '*')
52132Srobinson #define endcomment(where) (where[-1] == '*' && where[0] == '/')
530Sstevel@tonic-gate
540Sstevel@tonic-gate static int pushed = 0; /* is a token pushed */
550Sstevel@tonic-gate static token lasttok; /* last token, if pushed */
560Sstevel@tonic-gate
57132Srobinson static void unget_token(token *);
58132Srobinson static void findstrconst(char **, char **);
59132Srobinson static void findchrconst(char **, char **);
60132Srobinson static void findconst(char **, char **);
61132Srobinson static void findkind(char **, token *);
62132Srobinson static int cppline(char *);
63132Srobinson static int directive(char *);
64132Srobinson static void printdirective(char *);
65132Srobinson static void docppline(char *, int *, char **);
66132Srobinson
670Sstevel@tonic-gate /*
68132Srobinson * scan expecting 1 given token
690Sstevel@tonic-gate */
700Sstevel@tonic-gate void
scan(tok_kind expect,token * tokp)71132Srobinson scan(tok_kind expect, token *tokp)
720Sstevel@tonic-gate {
730Sstevel@tonic-gate get_token(tokp);
74132Srobinson if (tokp->kind != expect)
750Sstevel@tonic-gate expected1(expect);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
780Sstevel@tonic-gate /*
79132Srobinson * scan expecting any of the 2 given tokens
800Sstevel@tonic-gate */
810Sstevel@tonic-gate void
scan2(tok_kind expect1,tok_kind expect2,token * tokp)82132Srobinson scan2(tok_kind expect1, tok_kind expect2, token *tokp)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate get_token(tokp);
85132Srobinson if (tokp->kind != expect1 && tokp->kind != expect2)
860Sstevel@tonic-gate expected2(expect1, expect2);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate
890Sstevel@tonic-gate /*
90132Srobinson * scan expecting any of the 3 given token
910Sstevel@tonic-gate */
920Sstevel@tonic-gate void
scan3(tok_kind expect1,tok_kind expect2,tok_kind expect3,token * tokp)93132Srobinson scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
940Sstevel@tonic-gate {
950Sstevel@tonic-gate get_token(tokp);
96132Srobinson if (tokp->kind != expect1 && tokp->kind != expect2 &&
97*9497SJordan.Brown@Sun.COM tokp->kind != expect3)
980Sstevel@tonic-gate expected3(expect1, expect2, expect3);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate /*
102132Srobinson * scan expecting a constant, possibly symbolic
1030Sstevel@tonic-gate */
1040Sstevel@tonic-gate void
scan_num(token * tokp)105132Srobinson scan_num(token *tokp)
1060Sstevel@tonic-gate {
1070Sstevel@tonic-gate get_token(tokp);
1080Sstevel@tonic-gate switch (tokp->kind) {
1090Sstevel@tonic-gate case TOK_IDENT:
1100Sstevel@tonic-gate break;
1110Sstevel@tonic-gate default:
1120Sstevel@tonic-gate error("constant or identifier expected");
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate /*
117132Srobinson * Peek at the next token
1180Sstevel@tonic-gate */
1190Sstevel@tonic-gate void
peek(token * tokp)120132Srobinson peek(token *tokp)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate get_token(tokp);
1230Sstevel@tonic-gate unget_token(tokp);
1240Sstevel@tonic-gate }
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate /*
127132Srobinson * Peek at the next token and scan it if it matches what you expect
1280Sstevel@tonic-gate */
1290Sstevel@tonic-gate int
peekscan(tok_kind expect,token * tokp)130132Srobinson peekscan(tok_kind expect, token *tokp)
1310Sstevel@tonic-gate {
1320Sstevel@tonic-gate peek(tokp);
1330Sstevel@tonic-gate if (tokp->kind == expect) {
1340Sstevel@tonic-gate get_token(tokp);
1350Sstevel@tonic-gate return (1);
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate return (0);
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate
1400Sstevel@tonic-gate /*
141132Srobinson * Get the next token, printing out any directive that are encountered.
1420Sstevel@tonic-gate */
1430Sstevel@tonic-gate void
get_token(token * tokp)144132Srobinson get_token(token *tokp)
1450Sstevel@tonic-gate {
1460Sstevel@tonic-gate int commenting;
1470Sstevel@tonic-gate int stat = 0;
148132Srobinson
1490Sstevel@tonic-gate if (pushed) {
1500Sstevel@tonic-gate pushed = 0;
1510Sstevel@tonic-gate *tokp = lasttok;
1520Sstevel@tonic-gate return;
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate commenting = 0;
1550Sstevel@tonic-gate for (;;) {
1560Sstevel@tonic-gate if (*where == 0) {
1570Sstevel@tonic-gate for (;;) {
1580Sstevel@tonic-gate if (!fgets(curline, MAXLINESIZE, fin)) {
1590Sstevel@tonic-gate tokp->kind = TOK_EOF;
160132Srobinson /*
161132Srobinson * now check if cpp returned
162132Srobinson * non NULL value
163132Srobinson */
164132Srobinson (void) waitpid(childpid, &stat,
165*9497SJordan.Brown@Sun.COM WUNTRACED);
1660Sstevel@tonic-gate if (stat > 0) {
1670Sstevel@tonic-gate /* Set return value from rpcgen */
1680Sstevel@tonic-gate nonfatalerrors = stat >> 8;
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate *where = 0;
1710Sstevel@tonic-gate return;
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate linenum++;
1740Sstevel@tonic-gate if (commenting) {
1750Sstevel@tonic-gate break;
1760Sstevel@tonic-gate } else if (cppline(curline)) {
177132Srobinson docppline(curline, &linenum,
178*9497SJordan.Brown@Sun.COM &infilename);
1790Sstevel@tonic-gate } else if (directive(curline)) {
1800Sstevel@tonic-gate printdirective(curline);
1810Sstevel@tonic-gate } else {
1820Sstevel@tonic-gate break;
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate where = curline;
1860Sstevel@tonic-gate } else if (isspace(*where)) {
1870Sstevel@tonic-gate while (isspace(*where)) {
1880Sstevel@tonic-gate where++; /* eat */
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate } else if (commenting) {
1910Sstevel@tonic-gate for (where++; *where; where++) {
1920Sstevel@tonic-gate if (endcomment(where)) {
1930Sstevel@tonic-gate where++;
1940Sstevel@tonic-gate commenting--;
1950Sstevel@tonic-gate break;
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate } else if (startcomment(where)) {
1990Sstevel@tonic-gate where += 2;
2000Sstevel@tonic-gate commenting++;
2010Sstevel@tonic-gate } else {
2020Sstevel@tonic-gate break;
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate }
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate /*
207132Srobinson * 'where' is not whitespace, comment or directive Must be a token!
2080Sstevel@tonic-gate */
2090Sstevel@tonic-gate switch (*where) {
2100Sstevel@tonic-gate case ':':
2110Sstevel@tonic-gate tokp->kind = TOK_COLON;
2120Sstevel@tonic-gate where++;
2130Sstevel@tonic-gate break;
2140Sstevel@tonic-gate case ';':
2150Sstevel@tonic-gate tokp->kind = TOK_SEMICOLON;
2160Sstevel@tonic-gate where++;
2170Sstevel@tonic-gate break;
2180Sstevel@tonic-gate case ',':
2190Sstevel@tonic-gate tokp->kind = TOK_COMMA;
2200Sstevel@tonic-gate where++;
2210Sstevel@tonic-gate break;
2220Sstevel@tonic-gate case '=':
2230Sstevel@tonic-gate tokp->kind = TOK_EQUAL;
2240Sstevel@tonic-gate where++;
2250Sstevel@tonic-gate break;
2260Sstevel@tonic-gate case '*':
2270Sstevel@tonic-gate tokp->kind = TOK_STAR;
2280Sstevel@tonic-gate where++;
2290Sstevel@tonic-gate break;
2300Sstevel@tonic-gate case '[':
2310Sstevel@tonic-gate tokp->kind = TOK_LBRACKET;
2320Sstevel@tonic-gate where++;
2330Sstevel@tonic-gate break;
2340Sstevel@tonic-gate case ']':
2350Sstevel@tonic-gate tokp->kind = TOK_RBRACKET;
2360Sstevel@tonic-gate where++;
2370Sstevel@tonic-gate break;
2380Sstevel@tonic-gate case '{':
2390Sstevel@tonic-gate tokp->kind = TOK_LBRACE;
2400Sstevel@tonic-gate where++;
2410Sstevel@tonic-gate break;
2420Sstevel@tonic-gate case '}':
2430Sstevel@tonic-gate tokp->kind = TOK_RBRACE;
2440Sstevel@tonic-gate where++;
2450Sstevel@tonic-gate break;
2460Sstevel@tonic-gate case '(':
2470Sstevel@tonic-gate tokp->kind = TOK_LPAREN;
2480Sstevel@tonic-gate where++;
2490Sstevel@tonic-gate break;
2500Sstevel@tonic-gate case ')':
2510Sstevel@tonic-gate tokp->kind = TOK_RPAREN;
2520Sstevel@tonic-gate where++;
2530Sstevel@tonic-gate break;
2540Sstevel@tonic-gate case '<':
2550Sstevel@tonic-gate tokp->kind = TOK_LANGLE;
2560Sstevel@tonic-gate where++;
2570Sstevel@tonic-gate break;
2580Sstevel@tonic-gate case '>':
2590Sstevel@tonic-gate tokp->kind = TOK_RANGLE;
2600Sstevel@tonic-gate where++;
2610Sstevel@tonic-gate break;
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate case '"':
2640Sstevel@tonic-gate tokp->kind = TOK_STRCONST;
2650Sstevel@tonic-gate findstrconst(&where, &tokp->str);
2660Sstevel@tonic-gate break;
2670Sstevel@tonic-gate case '\'':
2680Sstevel@tonic-gate tokp->kind = TOK_CHARCONST;
2690Sstevel@tonic-gate findchrconst(&where, &tokp->str);
2700Sstevel@tonic-gate break;
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate case '-':
2730Sstevel@tonic-gate case '0':
2740Sstevel@tonic-gate case '1':
2750Sstevel@tonic-gate case '2':
2760Sstevel@tonic-gate case '3':
2770Sstevel@tonic-gate case '4':
2780Sstevel@tonic-gate case '5':
2790Sstevel@tonic-gate case '6':
2800Sstevel@tonic-gate case '7':
2810Sstevel@tonic-gate case '8':
2820Sstevel@tonic-gate case '9':
2830Sstevel@tonic-gate tokp->kind = TOK_IDENT;
2840Sstevel@tonic-gate findconst(&where, &tokp->str);
2850Sstevel@tonic-gate break;
2860Sstevel@tonic-gate
2870Sstevel@tonic-gate default:
2880Sstevel@tonic-gate if (!(isalpha(*where) || *where == '_')) {
2890Sstevel@tonic-gate char buf[100];
2900Sstevel@tonic-gate char *p;
291132Srobinson size_t blen;
2920Sstevel@tonic-gate
293132Srobinson (void) snprintf(buf, sizeof (buf),
294*9497SJordan.Brown@Sun.COM "illegal character in file: ");
295132Srobinson blen = strlen(buf);
296132Srobinson p = buf + blen;
2970Sstevel@tonic-gate if (isprint(*where)) {
298132Srobinson (void) snprintf(p, sizeof (buf) - blen,
299*9497SJordan.Brown@Sun.COM "%c", *where);
3000Sstevel@tonic-gate } else {
301132Srobinson (void) snprintf(p, sizeof (buf) - blen,
302*9497SJordan.Brown@Sun.COM "%d", *where);
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate error(buf);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate findkind(&where, tokp);
3070Sstevel@tonic-gate break;
3080Sstevel@tonic-gate }
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate
311132Srobinson static void
unget_token(token * tokp)312132Srobinson unget_token(token *tokp)
3130Sstevel@tonic-gate {
3140Sstevel@tonic-gate lasttok = *tokp;
3150Sstevel@tonic-gate pushed = 1;
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate
318132Srobinson static void
findstrconst(char ** str,char ** val)319132Srobinson findstrconst(char **str, char **val)
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate char *p;
3220Sstevel@tonic-gate int size;
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate p = *str;
3250Sstevel@tonic-gate do {
326132Srobinson p++;
3270Sstevel@tonic-gate } while (*p && *p != '"');
3280Sstevel@tonic-gate if (*p == 0) {
3290Sstevel@tonic-gate error("unterminated string constant");
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate p++;
3320Sstevel@tonic-gate size = p - *str;
333132Srobinson *val = malloc(size + 1);
3340Sstevel@tonic-gate (void) strncpy(*val, *str, size);
3350Sstevel@tonic-gate (*val)[size] = 0;
3360Sstevel@tonic-gate *str = p;
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate
339132Srobinson static void
findchrconst(char ** str,char ** val)340132Srobinson findchrconst(char **str, char **val)
3410Sstevel@tonic-gate {
3420Sstevel@tonic-gate char *p;
3430Sstevel@tonic-gate int size;
3440Sstevel@tonic-gate
3450Sstevel@tonic-gate p = *str;
3460Sstevel@tonic-gate do {
347132Srobinson p++;
3480Sstevel@tonic-gate } while (*p && *p != '\'');
349132Srobinson if (*p == 0)
3500Sstevel@tonic-gate error("unterminated string constant");
3510Sstevel@tonic-gate p++;
3520Sstevel@tonic-gate size = p - *str;
353132Srobinson if (size != 3)
3540Sstevel@tonic-gate error("empty char string");
355132Srobinson *val = malloc(size + 1);
3560Sstevel@tonic-gate (void) strncpy(*val, *str, size);
3570Sstevel@tonic-gate (*val)[size] = 0;
3580Sstevel@tonic-gate *str = p;
3590Sstevel@tonic-gate }
3600Sstevel@tonic-gate
361132Srobinson static void
findconst(char ** str,char ** val)362132Srobinson findconst(char **str, char **val)
3630Sstevel@tonic-gate {
3640Sstevel@tonic-gate char *p;
3650Sstevel@tonic-gate int size;
3660Sstevel@tonic-gate
3670Sstevel@tonic-gate p = *str;
3680Sstevel@tonic-gate if (*p == '0' && *(p + 1) == 'x') {
3690Sstevel@tonic-gate p++;
3700Sstevel@tonic-gate do {
3710Sstevel@tonic-gate p++;
3720Sstevel@tonic-gate } while (isxdigit(*p));
3730Sstevel@tonic-gate } else {
3740Sstevel@tonic-gate do {
3750Sstevel@tonic-gate p++;
3760Sstevel@tonic-gate } while (isdigit(*p));
3770Sstevel@tonic-gate }
3780Sstevel@tonic-gate size = p - *str;
379132Srobinson *val = malloc(size + 1);
3800Sstevel@tonic-gate (void) strncpy(*val, *str, size);
3810Sstevel@tonic-gate (*val)[size] = 0;
3820Sstevel@tonic-gate *str = p;
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate static token symbols[] = {
386132Srobinson {TOK_CONST, "const"},
387132Srobinson {TOK_UNION, "union"},
388132Srobinson {TOK_SWITCH, "switch"},
389132Srobinson {TOK_CASE, "case"},
390132Srobinson {TOK_DEFAULT, "default"},
391132Srobinson {TOK_STRUCT, "struct"},
392132Srobinson {TOK_TYPEDEF, "typedef"},
393132Srobinson {TOK_ENUM, "enum"},
394132Srobinson {TOK_OPAQUE, "opaque"},
395132Srobinson {TOK_BOOL, "bool"},
396132Srobinson {TOK_VOID, "void"},
397132Srobinson {TOK_ONEWAY, "oneway"},
398132Srobinson {TOK_CHAR, "char"},
399132Srobinson {TOK_INT, "int"},
400132Srobinson {TOK_UNSIGNED, "unsigned"},
401132Srobinson {TOK_SHORT, "short"},
402132Srobinson {TOK_LONG, "long"},
403132Srobinson {TOK_HYPER, "hyper"},
404132Srobinson {TOK_FLOAT, "float"},
405132Srobinson {TOK_DOUBLE, "double"},
406132Srobinson {TOK_QUAD, "quadruple"},
407132Srobinson {TOK_STRING, "string"},
408132Srobinson {TOK_PROGRAM, "program"},
409132Srobinson {TOK_VERSION, "version"},
410132Srobinson {TOK_EOF, "??????"},
4110Sstevel@tonic-gate };
4120Sstevel@tonic-gate
413132Srobinson static void
findkind(char ** mark,token * tokp)414132Srobinson findkind(char **mark, token *tokp)
4150Sstevel@tonic-gate {
4160Sstevel@tonic-gate int len;
4170Sstevel@tonic-gate token *s;
4180Sstevel@tonic-gate char *str;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate str = *mark;
4210Sstevel@tonic-gate for (s = symbols; s->kind != TOK_EOF; s++) {
4220Sstevel@tonic-gate len = strlen(s->str);
4230Sstevel@tonic-gate if (strncmp(str, s->str, len) == 0) {
4240Sstevel@tonic-gate if (!isalnum(str[len]) && str[len] != '_') {
4250Sstevel@tonic-gate tokp->kind = s->kind;
4260Sstevel@tonic-gate tokp->str = s->str;
4270Sstevel@tonic-gate *mark = str + len;
4280Sstevel@tonic-gate return;
4290Sstevel@tonic-gate }
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate }
4320Sstevel@tonic-gate tokp->kind = TOK_IDENT;
433*9497SJordan.Brown@Sun.COM for (len = 0; isalnum(str[len]) || str[len] == '_'; len++)
434*9497SJordan.Brown@Sun.COM /* LOOP */;
435132Srobinson tokp->str = malloc(len + 1);
4360Sstevel@tonic-gate (void) strncpy(tokp->str, str, len);
4370Sstevel@tonic-gate tokp->str[len] = 0;
4380Sstevel@tonic-gate *mark = str + len;
4390Sstevel@tonic-gate }
4400Sstevel@tonic-gate
441132Srobinson static int
cppline(char * line)442132Srobinson cppline(char *line)
4430Sstevel@tonic-gate {
4440Sstevel@tonic-gate return (line == curline && *line == '#');
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate
447132Srobinson static int
directive(char * line)448132Srobinson directive(char *line)
4490Sstevel@tonic-gate {
4500Sstevel@tonic-gate return (line == curline && *line == '%');
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate
453132Srobinson static void
printdirective(char * line)454132Srobinson printdirective(char *line)
4550Sstevel@tonic-gate {
4560Sstevel@tonic-gate f_print(fout, "%s", line + 1);
4570Sstevel@tonic-gate }
4580Sstevel@tonic-gate
459132Srobinson static void
docppline(char * line,int * lineno,char ** fname)460132Srobinson docppline(char *line, int *lineno, char **fname)
4610Sstevel@tonic-gate {
4620Sstevel@tonic-gate char *file;
4630Sstevel@tonic-gate int num;
4640Sstevel@tonic-gate char *p;
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate line++;
467132Srobinson while (isspace(*line))
4680Sstevel@tonic-gate line++;
4690Sstevel@tonic-gate num = atoi(line);
470132Srobinson while (isdigit(*line))
4710Sstevel@tonic-gate line++;
472132Srobinson while (isspace(*line))
4730Sstevel@tonic-gate line++;
474132Srobinson if (*line != '"')
4750Sstevel@tonic-gate error("preprocessor error");
4760Sstevel@tonic-gate line++;
477132Srobinson p = file = malloc(strlen(line) + 1);
478132Srobinson while (*line && *line != '"')
4790Sstevel@tonic-gate *p++ = *line++;
480132Srobinson if (*line == 0)
4810Sstevel@tonic-gate error("preprocessor error");
4820Sstevel@tonic-gate *p = 0;
483132Srobinson if (*file == 0)
4840Sstevel@tonic-gate *fname = NULL;
485132Srobinson else
4860Sstevel@tonic-gate *fname = file;
4870Sstevel@tonic-gate *lineno = num - 1;
4880Sstevel@tonic-gate }
489