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_WS 1
55 : #define C_ALPH 2
56 : #define C_NUM 3
57 : #define C_EOF 4
58 : #define C_XX 5
59 :
60 : enum state
61 : {
62 : START = 0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4,
63 : CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1,
64 : CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1,
65 : S_SELF = MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR,
66 : S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME
67 : };
68 :
69 : int tottok;
70 : int tokkind[256];
71 : struct fsm
72 : {
73 : int state; /* if in this state */
74 : uchar ch[4]; /* and see one of these characters */
75 : int nextstate; /* enter this state if +ve */
76 : };
77 :
78 : /*const*/ struct fsm fsm[] = {
79 : /* start state */
80 : {START, {C_XX}, ACT(UNCLASS, S_SELF)},
81 : {START, {' ', '\t', '\v'}, WS1},
82 : {START, {C_NUM}, NUM1},
83 : {START, {'.'}, NUM3},
84 : {START, {C_ALPH}, ID1},
85 : {START, {'L'}, ST1},
86 : {START, {'"'}, ST2},
87 : {START, {'\''}, CC1},
88 : {START, {'/'}, COM1},
89 : {START, {EOFC}, S_EOF},
90 : {START, {'\n'}, S_NL},
91 : {START, {'-'}, MINUS1},
92 : {START, {'+'}, PLUS1},
93 : {START, {'<'}, LT1},
94 : {START, {'>'}, GT1},
95 : {START, {'='}, ASG1},
96 : {START, {'!'}, NOT1},
97 : {START, {'&'}, AND1},
98 : {START, {'|'}, OR1},
99 : {START, {'#'}, SHARP1},
100 : {START, {'%'}, PCT1},
101 : {START, {'['}, ACT(SBRA, S_SELF)},
102 : {START, {']'}, ACT(SKET, S_SELF)},
103 : {START, {'('}, ACT(LP, S_SELF)},
104 : {START, {')'}, ACT(RP, S_SELF)},
105 : {START, {'*'}, STAR1},
106 : {START, {','}, ACT(COMMA, S_SELF)},
107 : {START, {'?'}, ACT(QUEST, S_SELF)},
108 : {START, {':'}, ACT(COLON, S_SELF)},
109 : {START, {';'}, ACT(SEMIC, S_SELF)},
110 : {START, {'{'}, ACT(CBRA, S_SELF)},
111 : {START, {'}'}, ACT(CKET, S_SELF)},
112 : {START, {'~'}, ACT(TILDE, S_SELF)},
113 : {START, {'^'}, CIRC1},
114 :
115 : /* saw a digit */
116 : {NUM1, {C_XX}, ACT(NUMBER, S_SELFB)},
117 : {NUM1, {C_NUM, C_ALPH, '.'}, NUM1},
118 : {NUM1, {'E', 'e'}, NUM2},
119 : {NUM1, {'_'}, ACT(NUMBER, S_SELFB)},
120 :
121 : /* saw possible start of exponent, digits-e */
122 : {NUM2, {C_XX}, ACT(NUMBER, S_SELFB)},
123 : {NUM2, {'+', '-'}, NUM1},
124 : {NUM2, {C_NUM, C_ALPH}, NUM1},
125 : {NUM2, {'_'}, ACT(NUMBER, S_SELFB)},
126 :
127 : /* saw a '.', which could be a number or an operator */
128 : {NUM3, {C_XX}, ACT(DOT, S_SELFB)},
129 : {NUM3, {'.'}, DOTS1},
130 : {NUM3, {C_NUM}, NUM1},
131 :
132 : {DOTS1, {C_XX}, ACT(UNCLASS, S_SELFB)},
133 : {DOTS1, {C_NUM}, NUM1},
134 : {DOTS1, {'.'}, ACT(ELLIPS, S_SELF)},
135 :
136 : /* saw a letter or _ */
137 : {ID1, {C_XX}, ACT(NAME, S_NAME)},
138 : {ID1, {C_ALPH, C_NUM}, ID1},
139 :
140 : /* saw L (start of wide string?) */
141 : {ST1, {C_XX}, ACT(NAME, S_NAME)},
142 : {ST1, {C_ALPH, C_NUM}, ID1},
143 : {ST1, {'"'}, ST2},
144 : {ST1, {'\''}, CC1},
145 :
146 : /* saw " beginning string */
147 : {ST2, {C_XX}, ST2},
148 : {ST2, {'"'}, ACT(STRING, S_SELF)},
149 : {ST2, {'\\'}, ST3},
150 : {ST2, {'\n'}, S_STNL},
151 : {ST2, {EOFC}, S_EOFSTR},
152 :
153 : /* saw \ in string */
154 : {ST3, {C_XX}, ST2},
155 : {ST3, {'\n'}, S_STNL},
156 : {ST3, {EOFC}, S_EOFSTR},
157 :
158 : /* saw ' beginning character const */
159 : {CC1, {C_XX}, CC1},
160 : {CC1, {'\''}, ACT(CCON, S_SELF)},
161 : {CC1, {'\\'}, CC2},
162 : {CC1, {'\n'}, S_STNL},
163 : {CC1, {EOFC}, S_EOFSTR},
164 :
165 : /* saw \ in ccon */
166 : {CC2, {C_XX}, CC1},
167 : {CC2, {'\n'}, S_STNL},
168 : {CC2, {EOFC}, S_EOFSTR},
169 :
170 : /* saw /, perhaps start of comment */
171 : {COM1, {C_XX}, ACT(SLASH, S_SELFB)},
172 : {COM1, {'='}, ACT(ASSLASH, S_SELF)},
173 : {COM1, {'*'}, COM2},
174 : {COM1, {'/'}, COM4},
175 :
176 : /* saw / followed by *, start of comment */
177 : {COM2, {C_XX}, COM2},
178 : {COM2, {'\n'}, S_COMNL},
179 : {COM2, {'*'}, COM3},
180 : {COM2, {EOFC}, S_EOFCOM},
181 :
182 : /* saw the * possibly ending a comment */
183 : {COM3, {C_XX}, COM2},
184 : {COM3, {'\n'}, S_COMNL},
185 : {COM3, {'*'}, COM3},
186 : {COM3, {'/'}, S_COMMENT},
187 :
188 : /* // comment */
189 : {COM4, {C_XX}, COM4},
190 : {COM4, {'\n'}, S_NL},
191 : {COM4, {EOFC}, S_EOFCOM},
192 :
193 : /* saw white space, eat it up */
194 : {WS1, {C_XX}, S_WS},
195 : {WS1, {'\t', '\v', ' '}, WS1},
196 :
197 : /* saw -, check --, -=, -> */
198 : {MINUS1, {C_XX}, ACT(MINUS, S_SELFB)},
199 : {MINUS1, {'-'}, ACT(MMINUS, S_SELF)},
200 : {MINUS1, {'='}, ACT(ASMINUS, S_SELF)},
201 : {MINUS1, {'>'}, ACT(ARROW, S_SELF)},
202 :
203 : /* saw +, check ++, += */
204 : {PLUS1, {C_XX}, ACT(PLUS, S_SELFB)},
205 : {PLUS1, {'+'}, ACT(PPLUS, S_SELF)},
206 : {PLUS1, {'='}, ACT(ASPLUS, S_SELF)},
207 :
208 : /* saw <, check <<, <<=, <= */
209 : {LT1, {C_XX}, ACT(LT, S_SELFB)},
210 : {LT1, {'<'}, LT2},
211 : {LT1, {'='}, ACT(LEQ, S_SELF)},
212 : {LT2, {C_XX}, ACT(LSH, S_SELFB)},
213 : {LT2, {'='}, ACT(ASLSH, S_SELF)},
214 :
215 : /* saw >, check >>, >>=, >= */
216 : {GT1, {C_XX}, ACT(GT, S_SELFB)},
217 : {GT1, {'>'}, GT2},
218 : {GT1, {'='}, ACT(GEQ, S_SELF)},
219 : {GT2, {C_XX}, ACT(RSH, S_SELFB)},
220 : {GT2, {'='}, ACT(ASRSH, S_SELF)},
221 :
222 : /* = */
223 : {ASG1, {C_XX}, ACT(ASGN, S_SELFB)},
224 : {ASG1, {'='}, ACT(EQ, S_SELF)},
225 :
226 : /* ! */
227 : {NOT1, {C_XX}, ACT(NOT, S_SELFB)},
228 : {NOT1, {'='}, ACT(NEQ, S_SELF)},
229 :
230 : /* & */
231 : {AND1, {C_XX}, ACT(AND, S_SELFB)},
232 : {AND1, {'&'}, ACT(LAND, S_SELF)},
233 : {AND1, {'='}, ACT(ASAND, S_SELF)},
234 :
235 : /* | */
236 : {OR1, {C_XX}, ACT(OR, S_SELFB)},
237 : {OR1, {'|'}, ACT(LOR, S_SELF)},
238 : {OR1, {'='}, ACT(ASOR, S_SELF)},
239 :
240 : /* # */
241 : {SHARP1, {C_XX}, ACT(SHARP, S_SELFB)},
242 : {SHARP1, {'#'}, ACT(DSHARP, S_SELF)},
243 :
244 : /* % */
245 : {PCT1, {C_XX}, ACT(PCT, S_SELFB)},
246 : {PCT1, {'='}, ACT(ASPCT, S_SELF)},
247 :
248 : /* * */
249 : {STAR1, {C_XX}, ACT(STAR, S_SELFB)},
250 : {STAR1, {'='}, ACT(ASSTAR, S_SELF)},
251 :
252 : /* ^ */
253 : {CIRC1, {C_XX}, ACT(CIRC, S_SELFB)},
254 : {CIRC1, {'='}, ACT(ASCIRC, S_SELF)},
255 :
256 : {-1, "", 0}
257 : };
258 :
259 : /* first index is char, second is state */
260 : /* increase #states to power of 2 to encourage use of shift */
261 : short bigfsm[256][MAXSTATE];
262 :
263 : void
264 75 : expandlex(void)
265 : {
266 : /* const */ struct fsm *fp;
267 : int i, j, nstate;
268 :
269 9225 : for (fp = fsm; fp->state >= 0; fp++)
270 : {
271 19125 : for (i = 0; fp->ch[i]; i++)
272 : {
273 9975 : nstate = fp->nextstate;
274 9975 : if (nstate >= S_SELF)
275 5625 : nstate = ~nstate;
276 9975 : switch (fp->ch[i])
277 : {
278 :
279 : case C_XX: /* random characters */
280 578250 : for (j = 0; j < 256; j++)
281 576000 : bigfsm[j][fp->state] = (short) nstate;
282 2250 : continue;
283 : case C_ALPH:
284 96375 : for (j = 0; j < 256; j++)
285 96000 : if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
286 76500 : || j == '_')
287 19875 : bigfsm[j][fp->state] = (short) nstate;
288 375 : continue;
289 : case C_NUM:
290 5775 : for (j = '0'; j <= '9'; j++)
291 5250 : bigfsm[j][fp->state] = (short) nstate;
292 525 : continue;
293 : default:
294 6825 : bigfsm[fp->ch[i]][fp->state] = (short) nstate;
295 : }
296 : }
297 : }
298 :
299 : /*
300 : * install special cases for ? (trigraphs), \ (splicing), runes, and
301 : * EOB
302 : */
303 2475 : for (i = 0; i < MAXSTATE; i++)
304 : {
305 614400 : for (j = 0; j < 0xFF; j++)
306 612000 : if (j == '?' || j == '\\' || j == '\n' || j == '\r')
307 : {
308 9600 : if (bigfsm[j][i] > 0)
309 1575 : bigfsm[j][i] = ~bigfsm[j][i];
310 9600 : bigfsm[j][i] &= ~QBSBIT;
311 : }
312 2400 : bigfsm[EOB][i] = ~S_EOB;
313 2400 : if (bigfsm[EOFC][i] >= 0)
314 225 : bigfsm[EOFC][i] = ~S_EOF;
315 : }
316 75 : }
317 :
318 : void
319 75 : fixlex(void)
320 : {
321 : /* do C++ comments? */
322 75 : if ((Cplusplus == 0) || (Cflag != 0))
323 0 : bigfsm['/'][COM1] = bigfsm['x'][COM1];
324 75 : }
325 :
326 : /*
327 : * fill in a row of tokens from input, terminated by NL or END
328 : * First token is put at trp->lp.
329 : * Reset is non-zero when the input buffer can be "rewound."
330 : * The value is a flag indicating that possible macros have
331 : * been seen in the row.
332 : */
333 : int
334 70386 : gettokens(Tokenrow * trp, int reset)
335 : {
336 : register int c, state, oldstate;
337 : register uchar *ip;
338 : register Token *tp, *maxp;
339 : int runelen;
340 70386 : Source *s = cursource;
341 70386 : int nmac = 0;
342 :
343 70386 : tp = trp->lp;
344 70386 : ip = s->inp;
345 70386 : if (reset)
346 : {
347 70382 : s->lineinc = 0;
348 70382 : if (ip >= s->inl)
349 : { /* nothing in buffer */
350 462 : s->inl = s->inb;
351 462 : fillbuf(s);
352 462 : ip = s->inp = s->inb;
353 : }
354 : else
355 69920 : if (ip >= s->inb + (3 * INS / 4))
356 : {
357 166 : memmove(s->inb, ip, 4 + s->inl - ip);
358 166 : s->inl = s->inb + (s->inl - ip);
359 166 : ip = s->inp = s->inb;
360 : }
361 : }
362 70386 : maxp = &trp->bp[trp->max];
363 70386 : runelen = 1;
364 : for (;;)
365 : {
366 : continue2:
367 1737150 : if (tp >= maxp)
368 : {
369 20823 : trp->lp = tp;
370 20823 : tp = growtokenrow(trp);
371 20823 : maxp = &trp->bp[trp->max];
372 : }
373 1737150 : tp->type = UNCLASS;
374 1737150 : tp->t = ip;
375 1737150 : tp->wslen = 0;
376 1737150 : tp->flag = 0;
377 1737150 : state = START;
378 : for (;;)
379 : {
380 8080889 : oldstate = state;
381 :
382 8080889 : c = *ip;
383 :
384 8080889 : if ((state = bigfsm[c][state]) >= 0)
385 : {
386 5605130 : ip += runelen;
387 5605130 : runelen = 1;
388 5605130 : continue;
389 : }
390 2475759 : state = ~state;
391 : reswitch:
392 2550229 : switch (state & 0177)
393 : {
394 : case S_SELF:
395 761167 : ip += runelen;
396 761167 : runelen = 1;
397 : case S_SELFB:
398 955363 : tp->type = (unsigned char) GETACT(state);
399 955363 : tp->len = ip - tp->t;
400 955363 : tp++;
401 955363 : goto continue2;
402 :
403 : case S_NAME: /* like S_SELFB but with nmac check */
404 711401 : tp->type = NAME;
405 711401 : tp->len = ip - tp->t;
406 711401 : nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
407 711401 : tp++;
408 711401 : goto continue2;
409 :
410 : case S_WS:
411 579974 : tp->wslen = ip - tp->t;
412 579974 : tp->t = ip;
413 579974 : state = START;
414 579974 : continue;
415 :
416 : default:
417 208077 : if ((state & QBSBIT) == 0)
418 : {
419 2353 : ip += runelen;
420 2353 : runelen = 1;
421 2353 : continue;
422 : }
423 205724 : state &= ~QBSBIT;
424 205724 : s->inp = ip;
425 :
426 205724 : if (c == '\n')
427 : {
428 66204 : while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
429 :
430 66204 : if (s->inp[1] == '\r')
431 : {
432 0 : memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2);
433 0 : s->inl -= 1;
434 : }
435 :
436 66204 : goto reswitch;
437 : }
438 :
439 139520 : if (c == '\r')
440 : {
441 0 : while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
442 :
443 0 : if (s->inp[1] == '\n')
444 : {
445 0 : memmove(s->inp, s->inp + 1, s->inl - s->inp + 1);
446 0 : s->inl -= 1;
447 : }
448 : else
449 0 : *s->inp = '\n';
450 :
451 0 : state = oldstate;
452 0 : continue;
453 : }
454 :
455 139520 : if (c == '?')
456 : { /* check trigraph */
457 1 : if (trigraph(s))
458 : {
459 0 : state = oldstate;
460 0 : continue;
461 : }
462 1 : goto reswitch;
463 : }
464 139519 : if (c == '\\')
465 : { /* line-folding */
466 139519 : if (foldline(s))
467 : {
468 131254 : s->lineinc++;
469 131254 : state = oldstate;
470 131254 : continue;
471 : }
472 8265 : goto reswitch;
473 : }
474 0 : error(WARNING, "Lexical botch in cpp");
475 0 : ip += runelen;
476 0 : runelen = 1;
477 0 : continue;
478 :
479 : case S_EOB:
480 22569 : s->inp = ip;
481 22569 : fillbuf(cursource);
482 22569 : state = oldstate;
483 22569 : continue;
484 :
485 : case S_EOF:
486 21301 : tp->type = END;
487 21301 : tp->len = 0;
488 21301 : s->inp = ip;
489 21301 : if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
490 0 : error(WARNING, "No newline at end of file");
491 21301 : trp->lp = tp + 1;
492 21301 : return nmac;
493 :
494 : case S_STNL:
495 0 : error(ERROR, "Unterminated string or char const");
496 : case S_NL:
497 49085 : tp->t = ip;
498 49085 : tp->type = NL;
499 49085 : tp->len = 1;
500 49085 : tp->wslen = 0;
501 49085 : s->lineinc++;
502 49085 : s->inp = ip + 1;
503 49085 : trp->lp = tp + 1;
504 49085 : return nmac;
505 :
506 : case S_EOFSTR:
507 0 : error(FATAL, "EOF in string or char constant");
508 0 : break;
509 :
510 : case S_COMNL:
511 2037 : s->lineinc++;
512 2037 : state = COM2;
513 2037 : ip += runelen;
514 2037 : runelen = 1;
515 2037 : continue;
516 :
517 : case S_EOFCOM:
518 0 : error(WARNING, "EOF inside comment");
519 0 : --ip;
520 : case S_COMMENT:
521 422 : if (!Cflag)
522 : {
523 422 : tp->t = ++ip;
524 422 : tp->t[-1] = ' ';
525 422 : tp->wslen = 1;
526 422 : state = START;
527 422 : continue;
528 : }
529 : else
530 : {
531 0 : runelen = 1;
532 0 : s->lineinc = 0;;
533 0 : tp->type = COMMENT;
534 0 : tp->flag |= XTWS;
535 : }
536 : }
537 0 : break;
538 6343739 : }
539 0 : ip += runelen;
540 0 : runelen = 1;
541 0 : tp->len = ip - tp->t;
542 0 : tp++;
543 0 : }
544 : }
545 :
546 : /* have seen ?; handle the trigraph it starts (if any) else 0 */
547 : int
548 1 : trigraph(Source * s)
549 : {
550 : uchar c;
551 :
552 1 : while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
553 : ;
554 1 : if (s->inp[1] != '?')
555 1 : return 0;
556 0 : c = 0;
557 0 : switch (s->inp[2])
558 : {
559 : case '=':
560 0 : c = '#';
561 0 : break;
562 : case '(':
563 0 : c = '[';
564 0 : break;
565 : case '/':
566 0 : c = '\\';
567 0 : break;
568 : case ')':
569 0 : c = ']';
570 0 : break;
571 : case '\'':
572 0 : c = '^';
573 0 : break;
574 : case '<':
575 0 : c = '{';
576 0 : break;
577 : case '!':
578 0 : c = '|';
579 0 : break;
580 : case '>':
581 0 : c = '}';
582 0 : break;
583 : case '-':
584 0 : c = '~';
585 0 : break;
586 : }
587 0 : if (c)
588 : {
589 0 : *s->inp = c;
590 0 : memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
591 0 : s->inl -= 2;
592 : }
593 0 : return c;
594 : }
595 :
596 : int
597 139519 : foldline(Source * s)
598 : {
599 139519 : int n = 1;
600 :
601 : /* skip pending wihite spaces */
602 279038 : while ((s->inp[n] == ' ') || (s->inp[n] == '\t'))
603 : {
604 0 : n++;
605 0 : if ((s->inp + n >= s->inl) && (fillbuf(s) == EOF))
606 0 : break;
607 : }
608 :
609 : /* refill buffer */
610 139519 : while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
611 :
612 : /* skip DOS line ends */
613 279038 : if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
614 270773 : ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
615 0 : n++;
616 :
617 139519 : if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
618 : {
619 131254 : memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
620 131254 : s->inl -= n + 1;
621 131254 : return 1;
622 : }
623 8265 : return 0;
624 : }
625 :
626 : int
627 23313 : fillbuf(Source * s)
628 : {
629 : int n;
630 :
631 23313 : if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
632 21578 : n = 0;
633 23313 : s->inl += n;
634 23313 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
635 23313 : if (n == 0)
636 : {
637 21578 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
638 21578 : return EOF;
639 : }
640 1735 : return 0;
641 : }
642 :
643 : /*
644 : * Push down to new source of characters.
645 : * If fd>0 and str==NULL, then from a file `name';
646 : * if fd==-1 and str, then from the string.
647 : */
648 : Source *
649 224074 : setsource(char *name, int path, int fd, char *str, int wrap)
650 : {
651 224074 : Source *s = new(Source);
652 : size_t len;
653 :
654 224074 : s->line = 1;
655 224074 : s->lineinc = 0;
656 224074 : s->fd = fd;
657 224074 : s->filename = name;
658 224074 : s->next = cursource;
659 224074 : s->ifdepth = 0;
660 224074 : s->pathdepth = path;
661 224074 : s->wrap = wrap;
662 :
663 224074 : cursource = s;
664 :
665 224074 : if (s->wrap)
666 0 : genwrap(0);
667 :
668 : /* slop at right for EOB */
669 224074 : if (str)
670 : {
671 223843 : len = strlen(str);
672 223843 : s->inb = domalloc(len + 4);
673 223843 : s->inp = s->inb;
674 223843 : strncpy((char *) s->inp, str, len);
675 : }
676 : else
677 : {
678 231 : s->inb = domalloc(INS + 4);
679 231 : s->inp = s->inb;
680 231 : len = 0;
681 : }
682 224074 : s->inl = s->inp + len;
683 224074 : s->inl[0] = s->inl[1] = EOB;
684 :
685 224074 : return s;
686 : }
687 :
688 : void
689 223999 : unsetsource(void)
690 : {
691 223999 : Source *s = cursource;
692 :
693 223999 : if (s->wrap)
694 0 : genwrap(1);
695 :
696 223999 : if (s->fd >= 0)
697 : {
698 156 : close(s->fd);
699 156 : dofree(s->inb);
700 : }
701 223999 : cursource = s->next;
702 223999 : dofree(s);
703 223999 : }
704 :
705 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|