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 53 : expandlex(void)
263 : {
264 : /* const */ struct fsm *fp;
265 : int i, j, nstate;
266 :
267 6519 : for (fp = fsm; fp->state >= 0; fp++)
268 : {
269 13515 : for (i = 0; fp->ch[i]; i++)
270 : {
271 7049 : nstate = fp->nextstate;
272 7049 : if (nstate >= S_SELF)
273 3975 : nstate = ~nstate;
274 7049 : switch (fp->ch[i])
275 : {
276 :
277 : case C_XX: /* random characters */
278 408630 : for (j = 0; j < 256; j++)
279 407040 : bigfsm[j][fp->state] = (short) nstate;
280 1590 : continue;
281 : case C_ALPH:
282 68105 : for (j = 0; j < 256; j++)
283 67840 : if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
284 54060 : || j == '_')
285 14045 : bigfsm[j][fp->state] = (short) nstate;
286 265 : continue;
287 : case C_NUM:
288 4081 : for (j = '0'; j <= '9'; j++)
289 3710 : bigfsm[j][fp->state] = (short) nstate;
290 371 : continue;
291 : default:
292 4823 : 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 1749 : for (i = 0; i < MAXSTATE; i++)
302 : {
303 434176 : for (j = 0; j < 0xFF; j++)
304 432480 : if (j == '?' || j == '\\' || j == '\n' || j == '\r')
305 : {
306 6784 : if (bigfsm[j][i] > 0)
307 1113 : bigfsm[j][i] = ~bigfsm[j][i];
308 6784 : bigfsm[j][i] &= ~QBSBIT;
309 : }
310 1696 : bigfsm[EOB][i] = ~S_EOB;
311 1696 : if (bigfsm[EOFC][i] >= 0)
312 159 : bigfsm[EOFC][i] = ~S_EOF;
313 : }
314 53 : }
315 :
316 : void
317 53 : fixlex(void)
318 : {
319 : /* do C++ comments? */
320 53 : if ((Cplusplus == 0) || (Cflag != 0))
321 0 : bigfsm['/'][COM1] = bigfsm['x'][COM1];
322 53 : }
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 56800 : gettokens(Tokenrow * trp, int reset)
333 : {
334 : int c, state, oldstate;
335 : uchar *ip;
336 : Token *tp, *maxp;
337 : int runelen;
338 56800 : Source *s = cursource;
339 56800 : int nmac = 0;
340 :
341 56800 : tp = trp->lp;
342 56800 : ip = s->inp;
343 56800 : if (reset)
344 : {
345 56800 : s->lineinc = 0;
346 56800 : if (ip >= s->inl)
347 : { /* nothing in buffer */
348 386 : s->inl = s->inb;
349 386 : fillbuf(s);
350 386 : ip = s->inp = s->inb;
351 : }
352 : else
353 56414 : if (ip >= s->inb + (3 * INS / 4))
354 : {
355 67 : memmove(s->inb, ip, 4 + s->inl - ip);
356 67 : s->inl = s->inb + (s->inl - ip);
357 67 : ip = s->inp = s->inb;
358 : }
359 : }
360 56800 : maxp = &trp->bp[trp->max];
361 56800 : runelen = 1;
362 : for (;;)
363 : {
364 : continue2:
365 1115563 : if (tp >= maxp)
366 : {
367 24848 : trp->lp = tp;
368 24848 : tp = growtokenrow(trp);
369 24848 : maxp = &trp->bp[trp->max];
370 : }
371 1115563 : tp->type = UNCLASS;
372 1115563 : tp->t = ip;
373 1115563 : tp->wslen = 0;
374 1115563 : tp->flag = 0;
375 1115563 : state = START;
376 : for (;;)
377 : {
378 5372711 : oldstate = state;
379 :
380 5372711 : c = *ip;
381 :
382 5372711 : if ((state = bigfsm[c][state]) >= 0)
383 : {
384 3826691 : ip += runelen;
385 3826691 : runelen = 1;
386 3826691 : continue;
387 : }
388 1546020 : state = ~state;
389 : reswitch:
390 1603507 : switch (state & 0177)
391 : {
392 : case S_SELF:
393 445321 : ip += runelen;
394 445321 : runelen = 1;
395 : /*fall-through*/
396 : case S_SELFB:
397 598459 : tp->type = (unsigned char) GETACT(state);
398 598459 : tp->len = ip - tp->t;
399 598459 : tp++;
400 598459 : goto continue2;
401 :
402 : case S_NAME: /* like S_SELFB but with nmac check */
403 460304 : tp->type = NAME;
404 460304 : tp->len = ip - tp->t;
405 460304 : nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
406 460304 : tp++;
407 460304 : goto continue2;
408 :
409 : case S_WS:
410 332952 : tp->wslen = ip - tp->t;
411 332952 : tp->t = ip;
412 332952 : state = START;
413 332952 : continue;
414 :
415 : default:
416 133287 : if ((state & QBSBIT) == 0)
417 : {
418 1638 : ip += runelen;
419 1638 : runelen = 1;
420 1638 : continue;
421 : }
422 131649 : state &= ~QBSBIT;
423 131649 : s->inp = ip;
424 :
425 131649 : if (c == '\n')
426 : {
427 51106 : while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
428 :
429 51106 : 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 51106 : goto reswitch;
436 : }
437 :
438 80543 : 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 80543 : if (c == '?')
455 : { /* check trigraph */
456 1 : if (trigraph(s))
457 : {
458 0 : state = oldstate;
459 0 : continue;
460 : }
461 1 : goto reswitch;
462 : }
463 80542 : if (c == '\\')
464 : { /* line-folding */
465 80542 : if (foldline(s))
466 : {
467 74162 : s->lineinc++;
468 74162 : state = oldstate;
469 74162 : continue;
470 : }
471 6380 : 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 19686 : s->inp = ip;
480 19686 : fillbuf(cursource);
481 19686 : state = oldstate;
482 19686 : continue;
483 :
484 : case S_EOF:
485 18966 : tp->type = END;
486 18966 : tp->len = 0;
487 18966 : s->inp = ip;
488 18966 : if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
489 0 : error(WARNING, "No newline at end of file");
490 18966 : trp->lp = tp + 1;
491 18966 : return nmac;
492 :
493 : case S_STNL:
494 0 : error(ERROR, "Unterminated string or char const");
495 : case S_NL:
496 37834 : tp->t = ip;
497 37834 : tp->type = NL;
498 37834 : tp->len = 1;
499 37834 : tp->wslen = 0;
500 37834 : s->lineinc++;
501 37834 : s->inp = ip + 1;
502 37834 : trp->lp = tp + 1;
503 37834 : 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 1752 : s->lineinc++;
511 1752 : state = COM2;
512 1752 : ip += runelen;
513 1752 : runelen = 1;
514 1752 : continue;
515 :
516 : case S_EOFCOM:
517 0 : error(WARNING, "EOF inside comment");
518 0 : --ip;
519 : case S_COMMENT:
520 267 : if (!Cflag)
521 : {
522 267 : tp->t = ++ip;
523 267 : tp->t[-1] = ' ';
524 267 : tp->wslen = 1;
525 267 : state = START;
526 267 : 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 4257148 : }
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 1 : trigraph(Source * s)
548 : {
549 : uchar c;
550 :
551 1 : while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
552 : ;
553 1 : if (s->inp[1] != '?')
554 1 : 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 80542 : foldline(Source * s)
597 : {
598 80542 : int n = 1;
599 :
600 : /* skip pending wihite spaces */
601 161084 : 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 80542 : while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
610 :
611 : /* skip DOS line ends */
612 161084 : if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
613 154704 : ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
614 0 : n++;
615 :
616 80542 : if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
617 : {
618 74162 : memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
619 74162 : s->inl -= n + 1;
620 74162 : return 1;
621 : }
622 6380 : return 0;
623 : }
624 :
625 : int
626 20306 : fillbuf(Source * s)
627 : {
628 : int n;
629 :
630 20306 : if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
631 19193 : n = 0;
632 20306 : s->inl += n;
633 20306 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
634 20306 : if (n == 0)
635 : {
636 19193 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
637 19193 : return EOF;
638 : }
639 1113 : 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 216954 : setsource(char *name, int path, int fd, char *str, int wrap)
649 : {
650 216954 : Source *s = new(Source);
651 : size_t len;
652 :
653 216954 : s->line = 1;
654 216954 : s->lineinc = 0;
655 216954 : s->fd = fd;
656 216954 : s->filename = name;
657 216954 : s->next = cursource;
658 216954 : s->ifdepth = 0;
659 216954 : s->pathdepth = path;
660 216954 : s->wrap = wrap;
661 :
662 216954 : cursource = s;
663 :
664 216954 : if (s->wrap)
665 0 : genwrap(0);
666 :
667 : /* slop at right for EOB */
668 216954 : if (str)
669 : {
670 216761 : len = strlen(str);
671 216761 : s->inb = domalloc(len + 4);
672 216761 : s->inp = s->inb;
673 216761 : strncpy((char *) s->inp, str, len);
674 : }
675 : else
676 : {
677 193 : s->inb = domalloc(INS + 4);
678 193 : s->inp = s->inb;
679 193 : len = 0;
680 : }
681 216954 : s->inl = s->inp + len;
682 216954 : s->inl[0] = s->inl[1] = EOB;
683 :
684 216954 : return s;
685 : }
686 :
687 : void
688 216901 : unsetsource(void)
689 : {
690 216901 : Source *s = cursource;
691 :
692 216901 : if (s->wrap)
693 0 : genwrap(1);
694 :
695 216901 : if (s->fd >= 0)
696 : {
697 140 : close(s->fd);
698 140 : dofree(s->inb);
699 : }
700 216901 : cursource = s->next;
701 216901 : dofree(s);
702 216901 : }
703 :
704 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|