Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdio.h>
21 : #include <stdlib.h>
22 : #include <string.h>
23 : #if (defined(_WIN32) || defined(__IBMC__))
24 : #include <io.h>
25 : #else
26 : #include <unistd.h>
27 : #endif
28 : #include "cpp.h"
29 : /*
30 : * lexical FSM encoding
31 : * when in state state, and one of the characters
32 : * in ch arrives, enter nextstate.
33 : * States >= S_SELF are either final, or at least require special action.
34 : * In 'fsm' there is a line for each state X charset X nextstate.
35 : * List chars that overwrite previous entries later (e.g. C_ALPH
36 : * can be overridden by '_' by a later entry; and C_XX is the
37 : * the universal set, and should always be first.
38 : * States above S_SELF are represented in the big table as negative values.
39 : * S_SELF and S_SELFB encode the resulting token type in the upper bits.
40 : * These actions differ in that S_SELF doesn't have a lookahead char,
41 : * S_SELFB does.
42 : *
43 : * The encoding is blown out into a big table for time-efficiency.
44 : * Entries have
45 : * nextstate: 6 bits; ?\ marker: 1 bit; tokentype: 9 bits.
46 : */
47 :
48 : #define MAXSTATE 32
49 : #define ACT(tok,act) ((tok<<7)+act)
50 : #define QBSBIT 0100
51 : #define GETACT(st) ((st>>7)&0x1ff)
52 :
53 : /* character classes */
54 : #define C_ALPH 1
55 : #define C_NUM 2
56 : #define C_XX 3
57 :
58 : enum state
59 : {
60 : START = 0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4,
61 : CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1,
62 : CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1,
63 : S_SELF = MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR,
64 : S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME
65 : };
66 :
67 : int tottok;
68 : int tokkind[256];
69 : struct fsm
70 : {
71 : int state; /* if in this state */
72 : uchar ch[4]; /* and see one of these characters */
73 : int nextstate; /* enter this state if +ve */
74 : };
75 :
76 : /*const*/ struct fsm fsm[] = {
77 : /* start state */
78 : {START, {C_XX}, ACT(UNCLASS, S_SELF)},
79 : {START, {' ', '\t', '\v'}, WS1},
80 : {START, {C_NUM}, NUM1},
81 : {START, {'.'}, NUM3},
82 : {START, {C_ALPH}, ID1},
83 : {START, {'L'}, ST1},
84 : {START, {'"'}, ST2},
85 : {START, {'\''}, CC1},
86 : {START, {'/'}, COM1},
87 : {START, {EOFC}, S_EOF},
88 : {START, {'\n'}, S_NL},
89 : {START, {'-'}, MINUS1},
90 : {START, {'+'}, PLUS1},
91 : {START, {'<'}, LT1},
92 : {START, {'>'}, GT1},
93 : {START, {'='}, ASG1},
94 : {START, {'!'}, NOT1},
95 : {START, {'&'}, AND1},
96 : {START, {'|'}, OR1},
97 : {START, {'#'}, SHARP1},
98 : {START, {'%'}, PCT1},
99 : {START, {'['}, ACT(SBRA, S_SELF)},
100 : {START, {']'}, ACT(SKET, S_SELF)},
101 : {START, {'('}, ACT(LP, S_SELF)},
102 : {START, {')'}, ACT(RP, S_SELF)},
103 : {START, {'*'}, STAR1},
104 : {START, {','}, ACT(COMMA, S_SELF)},
105 : {START, {'?'}, ACT(QUEST, S_SELF)},
106 : {START, {':'}, ACT(COLON, S_SELF)},
107 : {START, {';'}, ACT(SEMIC, S_SELF)},
108 : {START, {'{'}, ACT(CBRA, S_SELF)},
109 : {START, {'}'}, ACT(CKET, S_SELF)},
110 : {START, {'~'}, ACT(TILDE, S_SELF)},
111 : {START, {'^'}, CIRC1},
112 :
113 : /* saw a digit */
114 : {NUM1, {C_XX}, ACT(NUMBER, S_SELFB)},
115 : {NUM1, {C_NUM, C_ALPH, '.'}, NUM1},
116 : {NUM1, {'E', 'e'}, NUM2},
117 : {NUM1, {'_'}, ACT(NUMBER, S_SELFB)},
118 :
119 : /* saw possible start of exponent, digits-e */
120 : {NUM2, {C_XX}, ACT(NUMBER, S_SELFB)},
121 : {NUM2, {'+', '-'}, NUM1},
122 : {NUM2, {C_NUM, C_ALPH}, NUM1},
123 : {NUM2, {'_'}, ACT(NUMBER, S_SELFB)},
124 :
125 : /* saw a '.', which could be a number or an operator */
126 : {NUM3, {C_XX}, ACT(DOT, S_SELFB)},
127 : {NUM3, {'.'}, DOTS1},
128 : {NUM3, {C_NUM}, NUM1},
129 :
130 : {DOTS1, {C_XX}, ACT(UNCLASS, S_SELFB)},
131 : {DOTS1, {C_NUM}, NUM1},
132 : {DOTS1, {'.'}, ACT(ELLIPS, S_SELF)},
133 :
134 : /* saw a letter or _ */
135 : {ID1, {C_XX}, ACT(NAME, S_NAME)},
136 : {ID1, {C_ALPH, C_NUM}, ID1},
137 :
138 : /* saw L (start of wide string?) */
139 : {ST1, {C_XX}, ACT(NAME, S_NAME)},
140 : {ST1, {C_ALPH, C_NUM}, ID1},
141 : {ST1, {'"'}, ST2},
142 : {ST1, {'\''}, CC1},
143 :
144 : /* saw " beginning string */
145 : {ST2, {C_XX}, ST2},
146 : {ST2, {'"'}, ACT(STRING, S_SELF)},
147 : {ST2, {'\\'}, ST3},
148 : {ST2, {'\n'}, S_STNL},
149 : {ST2, {EOFC}, S_EOFSTR},
150 :
151 : /* saw \ in string */
152 : {ST3, {C_XX}, ST2},
153 : {ST3, {'\n'}, S_STNL},
154 : {ST3, {EOFC}, S_EOFSTR},
155 :
156 : /* saw ' beginning character const */
157 : {CC1, {C_XX}, CC1},
158 : {CC1, {'\''}, ACT(CCON, S_SELF)},
159 : {CC1, {'\\'}, CC2},
160 : {CC1, {'\n'}, S_STNL},
161 : {CC1, {EOFC}, S_EOFSTR},
162 :
163 : /* saw \ in ccon */
164 : {CC2, {C_XX}, CC1},
165 : {CC2, {'\n'}, S_STNL},
166 : {CC2, {EOFC}, S_EOFSTR},
167 :
168 : /* saw /, perhaps start of comment */
169 : {COM1, {C_XX}, ACT(SLASH, S_SELFB)},
170 : {COM1, {'='}, ACT(ASSLASH, S_SELF)},
171 : {COM1, {'*'}, COM2},
172 : {COM1, {'/'}, COM4},
173 :
174 : /* saw / followed by *, start of comment */
175 : {COM2, {C_XX}, COM2},
176 : {COM2, {'\n'}, S_COMNL},
177 : {COM2, {'*'}, COM3},
178 : {COM2, {EOFC}, S_EOFCOM},
179 :
180 : /* saw the * possibly ending a comment */
181 : {COM3, {C_XX}, COM2},
182 : {COM3, {'\n'}, S_COMNL},
183 : {COM3, {'*'}, COM3},
184 : {COM3, {'/'}, S_COMMENT},
185 :
186 : /* // comment */
187 : {COM4, {C_XX}, COM4},
188 : {COM4, {'\n'}, S_NL},
189 : {COM4, {EOFC}, S_EOFCOM},
190 :
191 : /* saw white space, eat it up */
192 : {WS1, {C_XX}, S_WS},
193 : {WS1, {'\t', '\v', ' '}, WS1},
194 :
195 : /* saw -, check --, -=, -> */
196 : {MINUS1, {C_XX}, ACT(MINUS, S_SELFB)},
197 : {MINUS1, {'-'}, ACT(MMINUS, S_SELF)},
198 : {MINUS1, {'='}, ACT(ASMINUS, S_SELF)},
199 : {MINUS1, {'>'}, ACT(ARROW, S_SELF)},
200 :
201 : /* saw +, check ++, += */
202 : {PLUS1, {C_XX}, ACT(PLUS, S_SELFB)},
203 : {PLUS1, {'+'}, ACT(PPLUS, S_SELF)},
204 : {PLUS1, {'='}, ACT(ASPLUS, S_SELF)},
205 :
206 : /* saw <, check <<, <<=, <= */
207 : {LT1, {C_XX}, ACT(LT, S_SELFB)},
208 : {LT1, {'<'}, LT2},
209 : {LT1, {'='}, ACT(LEQ, S_SELF)},
210 : {LT2, {C_XX}, ACT(LSH, S_SELFB)},
211 : {LT2, {'='}, ACT(ASLSH, S_SELF)},
212 :
213 : /* saw >, check >>, >>=, >= */
214 : {GT1, {C_XX}, ACT(GT, S_SELFB)},
215 : {GT1, {'>'}, GT2},
216 : {GT1, {'='}, ACT(GEQ, S_SELF)},
217 : {GT2, {C_XX}, ACT(RSH, S_SELFB)},
218 : {GT2, {'='}, ACT(ASRSH, S_SELF)},
219 :
220 : /* = */
221 : {ASG1, {C_XX}, ACT(ASGN, S_SELFB)},
222 : {ASG1, {'='}, ACT(EQ, S_SELF)},
223 :
224 : /* ! */
225 : {NOT1, {C_XX}, ACT(NOT, S_SELFB)},
226 : {NOT1, {'='}, ACT(NEQ, S_SELF)},
227 :
228 : /* & */
229 : {AND1, {C_XX}, ACT(AND, S_SELFB)},
230 : {AND1, {'&'}, ACT(LAND, S_SELF)},
231 : {AND1, {'='}, ACT(ASAND, S_SELF)},
232 :
233 : /* | */
234 : {OR1, {C_XX}, ACT(OR, S_SELFB)},
235 : {OR1, {'|'}, ACT(LOR, S_SELF)},
236 : {OR1, {'='}, ACT(ASOR, S_SELF)},
237 :
238 : /* # */
239 : {SHARP1, {C_XX}, ACT(SHARP, S_SELFB)},
240 : {SHARP1, {'#'}, ACT(DSHARP, S_SELF)},
241 :
242 : /* % */
243 : {PCT1, {C_XX}, ACT(PCT, S_SELFB)},
244 : {PCT1, {'='}, ACT(ASPCT, S_SELF)},
245 :
246 : /* * */
247 : {STAR1, {C_XX}, ACT(STAR, S_SELFB)},
248 : {STAR1, {'='}, ACT(ASSTAR, S_SELF)},
249 :
250 : /* ^ */
251 : {CIRC1, {C_XX}, ACT(CIRC, S_SELFB)},
252 : {CIRC1, {'='}, ACT(ASCIRC, S_SELF)},
253 :
254 : {-1, "", 0}
255 : };
256 :
257 : /* first index is char, second is state */
258 : /* increase #states to power of 2 to encourage use of shift */
259 : short bigfsm[256][MAXSTATE];
260 :
261 : void
262 112 : expandlex(void)
263 : {
264 : /* const */ struct fsm *fp;
265 : int i, j, nstate;
266 :
267 13776 : for (fp = fsm; fp->state >= 0; fp++)
268 : {
269 28560 : for (i = 0; fp->ch[i]; i++)
270 : {
271 14896 : nstate = fp->nextstate;
272 14896 : if (nstate >= S_SELF)
273 8400 : nstate = ~nstate;
274 14896 : switch (fp->ch[i])
275 : {
276 :
277 : case C_XX: /* random characters */
278 863520 : for (j = 0; j < 256; j++)
279 860160 : bigfsm[j][fp->state] = (short) nstate;
280 3360 : continue;
281 : case C_ALPH:
282 143920 : for (j = 0; j < 256; j++)
283 143360 : if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
284 114240 : || j == '_')
285 29680 : bigfsm[j][fp->state] = (short) nstate;
286 560 : continue;
287 : case C_NUM:
288 8624 : for (j = '0'; j <= '9'; j++)
289 7840 : bigfsm[j][fp->state] = (short) nstate;
290 784 : continue;
291 : default:
292 10192 : bigfsm[fp->ch[i]][fp->state] = (short) nstate;
293 : }
294 : }
295 : }
296 :
297 : /*
298 : * install special cases for ? (trigraphs), \ (splicing), runes, and
299 : * EOB
300 : */
301 3696 : for (i = 0; i < MAXSTATE; i++)
302 : {
303 917504 : for (j = 0; j < 0xFF; j++)
304 913920 : if (j == '?' || j == '\\' || j == '\n' || j == '\r')
305 : {
306 14336 : if (bigfsm[j][i] > 0)
307 2352 : bigfsm[j][i] = ~bigfsm[j][i];
308 14336 : bigfsm[j][i] &= ~QBSBIT;
309 : }
310 3584 : bigfsm[EOB][i] = ~S_EOB;
311 3584 : if (bigfsm[EOFC][i] >= 0)
312 336 : bigfsm[EOFC][i] = ~S_EOF;
313 : }
314 112 : }
315 :
316 : void
317 112 : fixlex(void)
318 : {
319 : /* do C++ comments? */
320 112 : if ((Cplusplus == 0) || (Cflag != 0))
321 0 : bigfsm['/'][COM1] = bigfsm['x'][COM1];
322 112 : }
323 :
324 : /*
325 : * fill in a row of tokens from input, terminated by NL or END
326 : * First token is put at trp->lp.
327 : * Reset is non-zero when the input buffer can be "rewound."
328 : * The value is a flag indicating that possible macros have
329 : * been seen in the row.
330 : */
331 : int
332 117566 : gettokens(Tokenrow * trp, int reset)
333 : {
334 : int c, state, oldstate;
335 : uchar *ip;
336 : Token *tp, *maxp;
337 : int runelen;
338 117566 : Source *s = cursource;
339 117566 : int nmac = 0;
340 :
341 117566 : tp = trp->lp;
342 117566 : ip = s->inp;
343 117566 : if (reset)
344 : {
345 117566 : s->lineinc = 0;
346 117566 : if (ip >= s->inl)
347 : { /* nothing in buffer */
348 812 : s->inl = s->inb;
349 812 : fillbuf(s);
350 812 : ip = s->inp = s->inb;
351 : }
352 : else
353 116754 : if (ip >= s->inb + (3 * INS / 4))
354 : {
355 144 : memmove(s->inb, ip, 4 + s->inl - ip);
356 144 : s->inl = s->inb + (s->inl - ip);
357 144 : ip = s->inp = s->inb;
358 : }
359 : }
360 117566 : maxp = &trp->bp[trp->max];
361 117566 : runelen = 1;
362 : for (;;)
363 : {
364 : continue2:
365 2333010 : if (tp >= maxp)
366 : {
367 48776 : trp->lp = tp;
368 48776 : tp = growtokenrow(trp);
369 48776 : maxp = &trp->bp[trp->max];
370 : }
371 2333010 : tp->type = UNCLASS;
372 2333010 : tp->t = ip;
373 2333010 : tp->wslen = 0;
374 2333010 : tp->flag = 0;
375 2333010 : state = START;
376 : for (;;)
377 : {
378 11258696 : oldstate = state;
379 :
380 11258696 : c = *ip;
381 :
382 11258696 : if ((state = bigfsm[c][state]) >= 0)
383 : {
384 8022454 : ip += runelen;
385 8022454 : runelen = 1;
386 8022454 : continue;
387 : }
388 3236242 : state = ~state;
389 : reswitch:
390 3358790 : switch (state & 0177)
391 : {
392 : case S_SELF:
393 932670 : ip += runelen;
394 932670 : runelen = 1;
395 : /*fall-through*/
396 : case S_SELFB:
397 1251388 : tp->type = (unsigned char) GETACT(state);
398 1251388 : tp->len = ip - tp->t;
399 1251388 : tp++;
400 1251388 : goto continue2;
401 :
402 : case S_NAME: /* like S_SELFB but with nmac check */
403 964056 : tp->type = NAME;
404 964056 : tp->len = ip - tp->t;
405 964056 : nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
406 964056 : tp++;
407 964056 : goto continue2;
408 :
409 : case S_WS:
410 700570 : tp->wslen = ip - tp->t;
411 700570 : tp->t = ip;
412 700570 : state = START;
413 700570 : continue;
414 :
415 : default:
416 281888 : if ((state & QBSBIT) == 0)
417 : {
418 3470 : ip += runelen;
419 3470 : runelen = 1;
420 3470 : continue;
421 : }
422 278418 : state &= ~QBSBIT;
423 278418 : s->inp = ip;
424 :
425 278418 : if (c == '\n')
426 : {
427 109034 : while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
428 :
429 109034 : if (s->inp[1] == '\r')
430 : {
431 0 : memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2);
432 0 : s->inl -= 1;
433 : }
434 :
435 109034 : goto reswitch;
436 : }
437 :
438 169384 : if (c == '\r')
439 : {
440 0 : while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
441 :
442 0 : if (s->inp[1] == '\n')
443 : {
444 0 : memmove(s->inp, s->inp + 1, s->inl - s->inp + 1);
445 0 : s->inl -= 1;
446 : }
447 : else
448 0 : *s->inp = '\n';
449 :
450 0 : state = oldstate;
451 0 : continue;
452 : }
453 :
454 169384 : if (c == '?')
455 : { /* check trigraph */
456 2 : if (trigraph(s))
457 : {
458 0 : state = oldstate;
459 0 : continue;
460 : }
461 2 : goto reswitch;
462 : }
463 169382 : if (c == '\\')
464 : { /* line-folding */
465 169382 : if (foldline(s))
466 : {
467 155870 : s->lineinc++;
468 155870 : state = oldstate;
469 155870 : continue;
470 : }
471 13512 : goto reswitch;
472 : }
473 0 : error(WARNING, "Lexical botch in cpp");
474 0 : ip += runelen;
475 0 : runelen = 1;
476 0 : continue;
477 :
478 : case S_EOB:
479 39072 : s->inp = ip;
480 39072 : fillbuf(cursource);
481 39072 : state = oldstate;
482 39072 : continue;
483 :
484 : case S_EOF:
485 37660 : tp->type = END;
486 37660 : tp->len = 0;
487 37660 : s->inp = ip;
488 37660 : if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
489 0 : error(WARNING, "No newline at end of file");
490 37660 : trp->lp = tp + 1;
491 37660 : return nmac;
492 :
493 : case S_STNL:
494 0 : error(ERROR, "Unterminated string or char const");
495 : case S_NL:
496 79906 : tp->t = ip;
497 79906 : tp->type = NL;
498 79906 : tp->len = 1;
499 79906 : tp->wslen = 0;
500 79906 : s->lineinc++;
501 79906 : s->inp = ip + 1;
502 79906 : trp->lp = tp + 1;
503 79906 : return nmac;
504 :
505 : case S_EOFSTR:
506 0 : error(FATAL, "EOF in string or char constant");
507 0 : break;
508 :
509 : case S_COMNL:
510 3688 : s->lineinc++;
511 3688 : state = COM2;
512 3688 : ip += runelen;
513 3688 : runelen = 1;
514 3688 : continue;
515 :
516 : case S_EOFCOM:
517 0 : error(WARNING, "EOF inside comment");
518 0 : --ip;
519 : case S_COMMENT:
520 562 : if (!Cflag)
521 : {
522 562 : tp->t = ++ip;
523 562 : tp->t[-1] = ' ';
524 562 : tp->wslen = 1;
525 562 : state = START;
526 562 : continue;
527 : }
528 : else
529 : {
530 0 : runelen = 1;
531 0 : s->lineinc = 0;;
532 0 : tp->type = COMMENT;
533 0 : tp->flag |= XTWS;
534 : }
535 : }
536 0 : break;
537 8925686 : }
538 0 : ip += runelen;
539 0 : runelen = 1;
540 0 : tp->len = ip - tp->t;
541 0 : tp++;
542 0 : }
543 : }
544 :
545 : /* have seen ?; handle the trigraph it starts (if any) else 0 */
546 : int
547 2 : trigraph(Source * s)
548 : {
549 : uchar c;
550 :
551 2 : while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
552 : ;
553 2 : if (s->inp[1] != '?')
554 2 : return 0;
555 0 : c = 0;
556 0 : switch (s->inp[2])
557 : {
558 : case '=':
559 0 : c = '#';
560 0 : break;
561 : case '(':
562 0 : c = '[';
563 0 : break;
564 : case '/':
565 0 : c = '\\';
566 0 : break;
567 : case ')':
568 0 : c = ']';
569 0 : break;
570 : case '\'':
571 0 : c = '^';
572 0 : break;
573 : case '<':
574 0 : c = '{';
575 0 : break;
576 : case '!':
577 0 : c = '|';
578 0 : break;
579 : case '>':
580 0 : c = '}';
581 0 : break;
582 : case '-':
583 0 : c = '~';
584 0 : break;
585 : }
586 0 : if (c)
587 : {
588 0 : *s->inp = c;
589 0 : memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
590 0 : s->inl -= 2;
591 : }
592 0 : return c;
593 : }
594 :
595 : int
596 169382 : foldline(Source * s)
597 : {
598 169382 : int n = 1;
599 :
600 : /* skip pending wihite spaces */
601 338764 : while ((s->inp[n] == ' ') || (s->inp[n] == '\t'))
602 : {
603 0 : n++;
604 0 : if ((s->inp + n >= s->inl) && (fillbuf(s) == EOF))
605 0 : break;
606 : }
607 :
608 : /* refill buffer */
609 169382 : while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
610 :
611 : /* skip DOS line ends */
612 338764 : if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
613 325252 : ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
614 0 : n++;
615 :
616 169382 : if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
617 : {
618 155870 : memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
619 155870 : s->inl -= n + 1;
620 155870 : return 1;
621 : }
622 13512 : return 0;
623 : }
624 :
625 : int
626 40480 : fillbuf(Source * s)
627 : {
628 : int n;
629 :
630 40480 : if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
631 38140 : n = 0;
632 40480 : s->inl += n;
633 40480 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
634 40480 : if (n == 0)
635 : {
636 38140 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
637 38140 : return EOF;
638 : }
639 2340 : return 0;
640 : }
641 :
642 : /*
643 : * Push down to new source of characters.
644 : * If fd>0 and str==NULL, then from a file `name';
645 : * if fd==-1 and str, then from the string.
646 : */
647 : Source *
648 430970 : setsource(char *name, int path, int fd, char *str, int wrap)
649 : {
650 430970 : Source *s = new(Source);
651 : size_t len;
652 :
653 430970 : s->line = 1;
654 430970 : s->lineinc = 0;
655 430970 : s->fd = fd;
656 430970 : s->filename = name;
657 430970 : s->next = cursource;
658 430970 : s->ifdepth = 0;
659 430970 : s->pathdepth = path;
660 430970 : s->wrap = wrap;
661 :
662 430970 : cursource = s;
663 :
664 430970 : if (s->wrap)
665 0 : genwrap(0);
666 :
667 : /* slop at right for EOB */
668 430970 : if (str)
669 : {
670 430564 : len = strlen(str);
671 430564 : s->inb = domalloc(len + 4);
672 430564 : s->inp = s->inb;
673 430564 : strncpy((char *) s->inp, str, len);
674 : }
675 : else
676 : {
677 406 : s->inb = domalloc(INS + 4);
678 406 : s->inp = s->inb;
679 406 : len = 0;
680 : }
681 430970 : s->inl = s->inp + len;
682 430970 : s->inl[0] = s->inl[1] = EOB;
683 :
684 430970 : return s;
685 : }
686 :
687 : void
688 430858 : unsetsource(void)
689 : {
690 430858 : Source *s = cursource;
691 :
692 430858 : if (s->wrap)
693 0 : genwrap(1);
694 :
695 430858 : if (s->fd >= 0)
696 : {
697 294 : close(s->fd);
698 294 : dofree(s->inb);
699 : }
700 430858 : cursource = s->next;
701 430858 : dofree(s);
702 430858 : }
703 :
704 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|