1*26f19e83Sjasper /* $OpenBSD: rpc_scan.c,v 1.19 2016/01/15 10:14:32 jasper Exp $ */
2df930be7Sderaadt /* $NetBSD: rpc_scan.c,v 1.4 1995/06/11 21:50:02 pk Exp $ */
3cb7760d1Smillert
4df930be7Sderaadt /*
5cb7760d1Smillert * Copyright (c) 2010, Oracle America, Inc.
6df930be7Sderaadt *
7cb7760d1Smillert * Redistribution and use in source and binary forms, with or without
8cb7760d1Smillert * modification, are permitted provided that the following conditions are
9cb7760d1Smillert * met:
10df930be7Sderaadt *
11cb7760d1Smillert * * Redistributions of source code must retain the above copyright
12cb7760d1Smillert * notice, this list of conditions and the following disclaimer.
13cb7760d1Smillert * * Redistributions in binary form must reproduce the above
14cb7760d1Smillert * copyright notice, this list of conditions and the following
15cb7760d1Smillert * disclaimer in the documentation and/or other materials
16cb7760d1Smillert * provided with the distribution.
17cb7760d1Smillert * * Neither the name of the "Oracle America, Inc." nor the names of its
18cb7760d1Smillert * contributors may be used to endorse or promote products derived
19cb7760d1Smillert * from this software without specific prior written permission.
20df930be7Sderaadt *
21cb7760d1Smillert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22cb7760d1Smillert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23cb7760d1Smillert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24cb7760d1Smillert * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25cb7760d1Smillert * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26cb7760d1Smillert * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27cb7760d1Smillert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28cb7760d1Smillert * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29cb7760d1Smillert * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30cb7760d1Smillert * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31cb7760d1Smillert * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32cb7760d1Smillert * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33df930be7Sderaadt */
34df930be7Sderaadt
35df930be7Sderaadt /*
36df930be7Sderaadt * rpc_scan.c, Scanner for the RPC protocol compiler
37df930be7Sderaadt */
38df930be7Sderaadt #include <stdlib.h>
39df930be7Sderaadt #include <stdio.h>
40df930be7Sderaadt #include <ctype.h>
41df930be7Sderaadt #include <string.h>
42df930be7Sderaadt #include "rpc_scan.h"
43df930be7Sderaadt #include "rpc_parse.h"
44df930be7Sderaadt #include "rpc_util.h"
45df930be7Sderaadt
46d0159584Sderaadt static void unget_token(token *tokp);
47d0159584Sderaadt static void findstrconst(char **, char **);
48d0159584Sderaadt static void findchrconst(char **, char **);
49d0159584Sderaadt static void findconst(char **, char **);
50d0159584Sderaadt static void findkind(char **, token *);
51d0159584Sderaadt static int cppline(char *);
52d0159584Sderaadt static int directive(char *);
53d0159584Sderaadt static void printdirective(char *);
54d0159584Sderaadt static void docppline(char *, int *, char **);
55df930be7Sderaadt
56df930be7Sderaadt #define startcomment(where) (where[0] == '/' && where[1] == '*')
57df930be7Sderaadt #define endcomment(where) (where[-1] == '*' && where[0] == '/')
58df930be7Sderaadt
59df930be7Sderaadt static int pushed = 0; /* is a token pushed */
60df930be7Sderaadt static token lasttok; /* last token, if pushed */
61df930be7Sderaadt
62df930be7Sderaadt /*
63df930be7Sderaadt * scan expecting 1 given token
64df930be7Sderaadt */
65df930be7Sderaadt void
scan(expect,tokp)66df930be7Sderaadt scan(expect, tokp)
67df930be7Sderaadt tok_kind expect;
68df930be7Sderaadt token *tokp;
69df930be7Sderaadt {
70df930be7Sderaadt get_token(tokp);
71d15c0992Sderaadt if (tokp->kind != expect)
72df930be7Sderaadt expected1(expect);
73df930be7Sderaadt }
74df930be7Sderaadt
75df930be7Sderaadt /*
76df930be7Sderaadt * scan expecting any of the 2 given tokens
77df930be7Sderaadt */
78df930be7Sderaadt void
scan2(expect1,expect2,tokp)79df930be7Sderaadt scan2(expect1, expect2, tokp)
80df930be7Sderaadt tok_kind expect1;
81df930be7Sderaadt tok_kind expect2;
82df930be7Sderaadt token *tokp;
83df930be7Sderaadt {
84df930be7Sderaadt get_token(tokp);
85d15c0992Sderaadt if (tokp->kind != expect1 && tokp->kind != expect2)
86df930be7Sderaadt expected2(expect1, expect2);
87df930be7Sderaadt }
88df930be7Sderaadt
89df930be7Sderaadt /*
90df930be7Sderaadt * scan expecting any of the 3 given token
91df930be7Sderaadt */
92df930be7Sderaadt void
scan3(expect1,expect2,expect3,tokp)93df930be7Sderaadt scan3(expect1, expect2, expect3, tokp)
94df930be7Sderaadt tok_kind expect1;
95df930be7Sderaadt tok_kind expect2;
96df930be7Sderaadt tok_kind expect3;
97df930be7Sderaadt token *tokp;
98df930be7Sderaadt {
99df930be7Sderaadt get_token(tokp);
100d15c0992Sderaadt if (tokp->kind != expect1 && tokp->kind != expect2 &&
101d15c0992Sderaadt tokp->kind != expect3)
102df930be7Sderaadt expected3(expect1, expect2, expect3);
103df930be7Sderaadt }
104df930be7Sderaadt
105df930be7Sderaadt /*
106df930be7Sderaadt * scan expecting a constant, possibly symbolic
107df930be7Sderaadt */
108df930be7Sderaadt void
scan_num(tokp)109df930be7Sderaadt scan_num(tokp)
110df930be7Sderaadt token *tokp;
111df930be7Sderaadt {
112df930be7Sderaadt get_token(tokp);
113df930be7Sderaadt switch (tokp->kind) {
114df930be7Sderaadt case TOK_IDENT:
115df930be7Sderaadt break;
116df930be7Sderaadt default:
117df930be7Sderaadt error("constant or identifier expected");
118df930be7Sderaadt }
119df930be7Sderaadt }
120df930be7Sderaadt
121df930be7Sderaadt /*
122df930be7Sderaadt * Peek at the next token
123df930be7Sderaadt */
124df930be7Sderaadt void
peek(tokp)125df930be7Sderaadt peek(tokp)
126df930be7Sderaadt token *tokp;
127df930be7Sderaadt {
128df930be7Sderaadt get_token(tokp);
129df930be7Sderaadt unget_token(tokp);
130df930be7Sderaadt }
131df930be7Sderaadt
132df930be7Sderaadt /*
133df930be7Sderaadt * Peek at the next token and scan it if it matches what you expect
134df930be7Sderaadt */
135df930be7Sderaadt int
peekscan(expect,tokp)136df930be7Sderaadt peekscan(expect, tokp)
137df930be7Sderaadt tok_kind expect;
138df930be7Sderaadt token *tokp;
139df930be7Sderaadt {
140df930be7Sderaadt peek(tokp);
141df930be7Sderaadt if (tokp->kind == expect) {
142df930be7Sderaadt get_token(tokp);
143df930be7Sderaadt return (1);
144df930be7Sderaadt }
145df930be7Sderaadt return (0);
146df930be7Sderaadt }
147df930be7Sderaadt
148df930be7Sderaadt /*
149df930be7Sderaadt * Get the next token, printing out any directive that are encountered.
150df930be7Sderaadt */
151df930be7Sderaadt void
get_token(tokp)152df930be7Sderaadt get_token(tokp)
153df930be7Sderaadt token *tokp;
154df930be7Sderaadt {
155df930be7Sderaadt int commenting;
156df930be7Sderaadt
157df930be7Sderaadt if (pushed) {
158df930be7Sderaadt pushed = 0;
159df930be7Sderaadt *tokp = lasttok;
160df930be7Sderaadt return;
161df930be7Sderaadt }
162df930be7Sderaadt commenting = 0;
163df930be7Sderaadt for (;;) {
164df930be7Sderaadt if (*where == 0) {
165df930be7Sderaadt for (;;) {
166df930be7Sderaadt if (!fgets(curline, MAXLINESIZE, fin)) {
167df930be7Sderaadt tokp->kind = TOK_EOF;
168df930be7Sderaadt *where = 0;
169df930be7Sderaadt return;
170df930be7Sderaadt }
171df930be7Sderaadt linenum++;
172df930be7Sderaadt if (commenting) {
173df930be7Sderaadt break;
174df930be7Sderaadt } else if (cppline(curline)) {
175df930be7Sderaadt docppline(curline, &linenum,
176df930be7Sderaadt &infilename);
177df930be7Sderaadt } else if (directive(curline)) {
178df930be7Sderaadt printdirective(curline);
179df930be7Sderaadt } else {
180df930be7Sderaadt break;
181df930be7Sderaadt }
182df930be7Sderaadt }
183df930be7Sderaadt where = curline;
184f69332c7Sderaadt } else if (isspace((unsigned char)*where)) {
185f69332c7Sderaadt while (isspace((unsigned char)*where)) {
186df930be7Sderaadt where++; /* eat */
187df930be7Sderaadt }
188df930be7Sderaadt } else if (commenting) {
189df930be7Sderaadt for (where++; *where; where++) {
190df930be7Sderaadt if (endcomment(where)) {
191df930be7Sderaadt where++;
192df930be7Sderaadt commenting--;
193df930be7Sderaadt break;
194df930be7Sderaadt }
195df930be7Sderaadt }
196df930be7Sderaadt } else if (startcomment(where)) {
197df930be7Sderaadt where += 2;
198df930be7Sderaadt commenting++;
199df930be7Sderaadt } else {
200df930be7Sderaadt break;
201df930be7Sderaadt }
202df930be7Sderaadt }
203df930be7Sderaadt
204df930be7Sderaadt /*
205df930be7Sderaadt * 'where' is not whitespace, comment or directive Must be a token!
206df930be7Sderaadt */
207df930be7Sderaadt switch (*where) {
208df930be7Sderaadt case ':':
209df930be7Sderaadt tokp->kind = TOK_COLON;
210df930be7Sderaadt where++;
211df930be7Sderaadt break;
212df930be7Sderaadt case ';':
213df930be7Sderaadt tokp->kind = TOK_SEMICOLON;
214df930be7Sderaadt where++;
215df930be7Sderaadt break;
216df930be7Sderaadt case ',':
217df930be7Sderaadt tokp->kind = TOK_COMMA;
218df930be7Sderaadt where++;
219df930be7Sderaadt break;
220df930be7Sderaadt case '=':
221df930be7Sderaadt tokp->kind = TOK_EQUAL;
222df930be7Sderaadt where++;
223df930be7Sderaadt break;
224df930be7Sderaadt case '*':
225df930be7Sderaadt tokp->kind = TOK_STAR;
226df930be7Sderaadt where++;
227df930be7Sderaadt break;
228df930be7Sderaadt case '[':
229df930be7Sderaadt tokp->kind = TOK_LBRACKET;
230df930be7Sderaadt where++;
231df930be7Sderaadt break;
232df930be7Sderaadt case ']':
233df930be7Sderaadt tokp->kind = TOK_RBRACKET;
234df930be7Sderaadt where++;
235df930be7Sderaadt break;
236df930be7Sderaadt case '{':
237df930be7Sderaadt tokp->kind = TOK_LBRACE;
238df930be7Sderaadt where++;
239df930be7Sderaadt break;
240df930be7Sderaadt case '}':
241df930be7Sderaadt tokp->kind = TOK_RBRACE;
242df930be7Sderaadt where++;
243df930be7Sderaadt break;
244df930be7Sderaadt case '(':
245df930be7Sderaadt tokp->kind = TOK_LPAREN;
246df930be7Sderaadt where++;
247df930be7Sderaadt break;
248df930be7Sderaadt case ')':
249df930be7Sderaadt tokp->kind = TOK_RPAREN;
250df930be7Sderaadt where++;
251df930be7Sderaadt break;
252df930be7Sderaadt case '<':
253df930be7Sderaadt tokp->kind = TOK_LANGLE;
254df930be7Sderaadt where++;
255df930be7Sderaadt break;
256df930be7Sderaadt case '>':
257df930be7Sderaadt tokp->kind = TOK_RANGLE;
258df930be7Sderaadt where++;
259df930be7Sderaadt break;
260df930be7Sderaadt
261df930be7Sderaadt case '"':
262df930be7Sderaadt tokp->kind = TOK_STRCONST;
263df930be7Sderaadt findstrconst(&where, &tokp->str);
264df930be7Sderaadt break;
265df930be7Sderaadt case '\'':
266df930be7Sderaadt tokp->kind = TOK_CHARCONST;
267df930be7Sderaadt findchrconst(&where, &tokp->str);
268df930be7Sderaadt break;
269df930be7Sderaadt
270df930be7Sderaadt case '-':
271df930be7Sderaadt case '0':
272df930be7Sderaadt case '1':
273df930be7Sderaadt case '2':
274df930be7Sderaadt case '3':
275df930be7Sderaadt case '4':
276df930be7Sderaadt case '5':
277df930be7Sderaadt case '6':
278df930be7Sderaadt case '7':
279df930be7Sderaadt case '8':
280df930be7Sderaadt case '9':
281df930be7Sderaadt tokp->kind = TOK_IDENT;
282df930be7Sderaadt findconst(&where, &tokp->str);
283df930be7Sderaadt break;
284df930be7Sderaadt
285df930be7Sderaadt default:
286f69332c7Sderaadt if (!(isalpha((unsigned char)*where) || *where == '_')) {
28743acbd26Sderaadt char buf[100], chs[20];
288df930be7Sderaadt
289f69332c7Sderaadt if (isprint((unsigned char)*where)) {
29043acbd26Sderaadt snprintf(chs, sizeof chs, "%c", *where);
291df930be7Sderaadt } else {
29243acbd26Sderaadt snprintf(chs, sizeof chs, "%d", *where);
293df930be7Sderaadt }
29443acbd26Sderaadt
29543acbd26Sderaadt snprintf(buf, sizeof buf,
29643acbd26Sderaadt "illegal character in file: %s", chs);
297df930be7Sderaadt error(buf);
298df930be7Sderaadt }
299df930be7Sderaadt findkind(&where, tokp);
300df930be7Sderaadt break;
301df930be7Sderaadt }
302df930be7Sderaadt }
303df930be7Sderaadt
304d0159584Sderaadt static void
unget_token(tokp)305df930be7Sderaadt unget_token(tokp)
306df930be7Sderaadt token *tokp;
307df930be7Sderaadt {
308df930be7Sderaadt lasttok = *tokp;
309df930be7Sderaadt pushed = 1;
310df930be7Sderaadt }
311df930be7Sderaadt
312d0159584Sderaadt static void
findstrconst(str,val)313df930be7Sderaadt findstrconst(str, val)
314df930be7Sderaadt char **str;
315df930be7Sderaadt char **val;
316df930be7Sderaadt {
317df930be7Sderaadt char *p;
318df930be7Sderaadt int size;
319df930be7Sderaadt
320df930be7Sderaadt p = *str;
321df930be7Sderaadt do {
322d0159584Sderaadt p++;
323df930be7Sderaadt } while (*p && *p != '"');
324df930be7Sderaadt if (*p == 0) {
325df930be7Sderaadt error("unterminated string constant");
326df930be7Sderaadt }
327df930be7Sderaadt p++;
328df930be7Sderaadt size = p - *str;
329cfff592fSderaadt *val = malloc(size + 1);
330d0159584Sderaadt if (val == NULL)
331d0159584Sderaadt error("alloc failed");
332df930be7Sderaadt (void) strncpy(*val, *str, size);
333df930be7Sderaadt (*val)[size] = 0;
334df930be7Sderaadt *str = p;
335df930be7Sderaadt }
336df930be7Sderaadt
337d0159584Sderaadt static void
findchrconst(str,val)338df930be7Sderaadt findchrconst(str, val)
339df930be7Sderaadt char **str;
340df930be7Sderaadt char **val;
341df930be7Sderaadt {
342df930be7Sderaadt char *p;
343df930be7Sderaadt int size;
344df930be7Sderaadt
345df930be7Sderaadt p = *str;
346df930be7Sderaadt do {
347d0159584Sderaadt p++;
348df930be7Sderaadt } while (*p && *p != '\'');
349df930be7Sderaadt if (*p == 0) {
350df930be7Sderaadt error("unterminated string constant");
351df930be7Sderaadt }
352df930be7Sderaadt p++;
353df930be7Sderaadt size = p - *str;
354df930be7Sderaadt if (size != 3) {
355df930be7Sderaadt error("empty char string");
356df930be7Sderaadt }
357cfff592fSderaadt *val = malloc(size + 1);
358d0159584Sderaadt if (val == NULL)
359d0159584Sderaadt error("alloc failed");
360df930be7Sderaadt (void) strncpy(*val, *str, size);
361df930be7Sderaadt (*val)[size] = 0;
362df930be7Sderaadt *str = p;
363df930be7Sderaadt }
364df930be7Sderaadt
365d0159584Sderaadt static void
findconst(str,val)366df930be7Sderaadt findconst(str, val)
367df930be7Sderaadt char **str;
368df930be7Sderaadt char **val;
369df930be7Sderaadt {
370df930be7Sderaadt char *p;
371df930be7Sderaadt int size;
372df930be7Sderaadt
373df930be7Sderaadt p = *str;
374df930be7Sderaadt if (*p == '0' && *(p + 1) == 'x') {
375df930be7Sderaadt p++;
376df930be7Sderaadt do {
377df930be7Sderaadt p++;
378f69332c7Sderaadt } while (isxdigit((unsigned char)*p));
379df930be7Sderaadt } else {
380df930be7Sderaadt do {
381df930be7Sderaadt p++;
382f69332c7Sderaadt } while (isdigit((unsigned char)*p));
383df930be7Sderaadt }
384df930be7Sderaadt size = p - *str;
385cfff592fSderaadt *val = malloc(size + 1);
386d0159584Sderaadt if (val == NULL)
387d0159584Sderaadt error("alloc failed");
388df930be7Sderaadt (void) strncpy(*val, *str, size);
389df930be7Sderaadt (*val)[size] = 0;
390df930be7Sderaadt *str = p;
391df930be7Sderaadt }
392df930be7Sderaadt
393df930be7Sderaadt static token symbols[] = {
394df930be7Sderaadt {TOK_CONST, "const"},
395df930be7Sderaadt {TOK_UNION, "union"},
396df930be7Sderaadt {TOK_SWITCH, "switch"},
397df930be7Sderaadt {TOK_CASE, "case"},
398df930be7Sderaadt {TOK_DEFAULT, "default"},
399df930be7Sderaadt {TOK_STRUCT, "struct"},
400df930be7Sderaadt {TOK_TYPEDEF, "typedef"},
401df930be7Sderaadt {TOK_ENUM, "enum"},
402df930be7Sderaadt {TOK_OPAQUE, "opaque"},
403df930be7Sderaadt {TOK_BOOL, "bool"},
404df930be7Sderaadt {TOK_VOID, "void"},
405df930be7Sderaadt {TOK_CHAR, "char"},
406df930be7Sderaadt {TOK_INT, "int"},
407df930be7Sderaadt {TOK_UNSIGNED, "unsigned"},
408df930be7Sderaadt {TOK_SHORT, "short"},
409df930be7Sderaadt {TOK_LONG, "long"},
410*26f19e83Sjasper {TOK_HYPER, "hyper"},
411df930be7Sderaadt {TOK_FLOAT, "float"},
412df930be7Sderaadt {TOK_DOUBLE, "double"},
413*26f19e83Sjasper {TOK_QUAD, "quadruple"},
414df930be7Sderaadt {TOK_STRING, "string"},
415df930be7Sderaadt {TOK_PROGRAM, "program"},
416df930be7Sderaadt {TOK_VERSION, "version"},
417df930be7Sderaadt {TOK_EOF, "??????"},
418df930be7Sderaadt };
419df930be7Sderaadt
420d0159584Sderaadt static void
findkind(mark,tokp)421df930be7Sderaadt findkind(mark, tokp)
422df930be7Sderaadt char **mark;
423df930be7Sderaadt token *tokp;
424df930be7Sderaadt {
425df930be7Sderaadt int len;
426df930be7Sderaadt token *s;
427df930be7Sderaadt char *str;
428df930be7Sderaadt
429df930be7Sderaadt str = *mark;
430df930be7Sderaadt for (s = symbols; s->kind != TOK_EOF; s++) {
431df930be7Sderaadt len = strlen(s->str);
432df930be7Sderaadt if (strncmp(str, s->str, len) == 0) {
433f69332c7Sderaadt if (!isalnum((unsigned char)str[len]) &&
434f69332c7Sderaadt str[len] != '_') {
435df930be7Sderaadt tokp->kind = s->kind;
436df930be7Sderaadt tokp->str = s->str;
437df930be7Sderaadt *mark = str + len;
438df930be7Sderaadt return;
439df930be7Sderaadt }
440df930be7Sderaadt }
441df930be7Sderaadt }
442df930be7Sderaadt tokp->kind = TOK_IDENT;
443f69332c7Sderaadt for (len = 0; isalnum((unsigned char)str[len]) || str[len] == '_';
444f69332c7Sderaadt len++)
445f69332c7Sderaadt ;
446cfff592fSderaadt tokp->str = malloc(len + 1);
447d0159584Sderaadt if (tokp->str == NULL)
448d0159584Sderaadt error("alloc failed");
449df930be7Sderaadt (void) strncpy(tokp->str, str, len);
450df930be7Sderaadt tokp->str[len] = 0;
451df930be7Sderaadt *mark = str + len;
452df930be7Sderaadt }
453df930be7Sderaadt
454d0159584Sderaadt static int
cppline(line)455df930be7Sderaadt cppline(line)
456df930be7Sderaadt char *line;
457df930be7Sderaadt {
458df930be7Sderaadt return (line == curline && *line == '#');
459df930be7Sderaadt }
460df930be7Sderaadt
461d0159584Sderaadt static int
directive(line)462df930be7Sderaadt directive(line)
463df930be7Sderaadt char *line;
464df930be7Sderaadt {
465df930be7Sderaadt return (line == curline && *line == '%');
466df930be7Sderaadt }
467df930be7Sderaadt
468d0159584Sderaadt static void
printdirective(line)469df930be7Sderaadt printdirective(line)
470df930be7Sderaadt char *line;
471df930be7Sderaadt {
4724a61a1b9Sderaadt fprintf(fout, "%s", line + 1);
473df930be7Sderaadt }
474df930be7Sderaadt
475d0159584Sderaadt static void
docppline(line,lineno,fname)476df930be7Sderaadt docppline(line, lineno, fname)
477df930be7Sderaadt char *line;
478df930be7Sderaadt int *lineno;
479df930be7Sderaadt char **fname;
480df930be7Sderaadt {
481df930be7Sderaadt char *file;
482df930be7Sderaadt int num;
483df930be7Sderaadt char *p;
484df930be7Sderaadt
485df930be7Sderaadt line++;
486f69332c7Sderaadt while (isspace((unsigned char)*line)) {
487df930be7Sderaadt line++;
488df930be7Sderaadt }
489df930be7Sderaadt num = atoi(line);
490f69332c7Sderaadt while (isdigit((unsigned char)*line)) {
491df930be7Sderaadt line++;
492df930be7Sderaadt }
493f69332c7Sderaadt while (isspace((unsigned char)*line)) {
494df930be7Sderaadt line++;
495df930be7Sderaadt }
496df930be7Sderaadt if (*line != '"') {
497df930be7Sderaadt error("preprocessor error");
498df930be7Sderaadt }
499df930be7Sderaadt line++;
500cfff592fSderaadt p = file = malloc(strlen(line) + 1);
501d0159584Sderaadt if (p == NULL)
502d0159584Sderaadt error("alloc failed");
503df930be7Sderaadt while (*line && *line != '"') {
504df930be7Sderaadt *p++ = *line++;
505df930be7Sderaadt }
506df930be7Sderaadt if (*line == 0) {
507df930be7Sderaadt error("preprocessor error");
508df930be7Sderaadt }
509df930be7Sderaadt *p = 0;
510df930be7Sderaadt if (*file == 0) {
511df930be7Sderaadt *fname = NULL;
512ff5f36e4Sdhill free(file);
513df930be7Sderaadt } else {
514df930be7Sderaadt *fname = file;
515df930be7Sderaadt }
516df930be7Sderaadt *lineno = num - 1;
517df930be7Sderaadt }
518