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 0 : expandlex(void)
263 : {
264 : /* const */ struct fsm *fp;
265 : int i, j, nstate;
266 :
267 0 : for (fp = fsm; fp->state >= 0; fp++)
268 : {
269 0 : for (i = 0; fp->ch[i]; i++)
270 : {
271 0 : nstate = fp->nextstate;
272 0 : if (nstate >= S_SELF)
273 0 : nstate = ~nstate;
274 0 : switch (fp->ch[i])
275 : {
276 :
277 : case C_XX: /* random characters */
278 0 : for (j = 0; j < 256; j++)
279 0 : bigfsm[j][fp->state] = (short) nstate;
280 0 : continue;
281 : case C_ALPH:
282 0 : for (j = 0; j < 256; j++)
283 0 : if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z')
284 0 : || j == '_')
285 0 : bigfsm[j][fp->state] = (short) nstate;
286 0 : continue;
287 : case C_NUM:
288 0 : for (j = '0'; j <= '9'; j++)
289 0 : bigfsm[j][fp->state] = (short) nstate;
290 0 : continue;
291 : default:
292 0 : 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 0 : for (i = 0; i < MAXSTATE; i++)
302 : {
303 0 : for (j = 0; j < 0xFF; j++)
304 0 : if (j == '?' || j == '\\' || j == '\n' || j == '\r')
305 : {
306 0 : if (bigfsm[j][i] > 0)
307 0 : bigfsm[j][i] = ~bigfsm[j][i];
308 0 : bigfsm[j][i] &= ~QBSBIT;
309 : }
310 0 : bigfsm[EOB][i] = ~S_EOB;
311 0 : if (bigfsm[EOFC][i] >= 0)
312 0 : bigfsm[EOFC][i] = ~S_EOF;
313 : }
314 0 : }
315 :
316 : void
317 0 : fixlex(void)
318 : {
319 : /* do C++ comments? */
320 0 : if ((Cplusplus == 0) || (Cflag != 0))
321 0 : bigfsm['/'][COM1] = bigfsm['x'][COM1];
322 0 : }
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 0 : gettokens(Tokenrow * trp, int reset)
333 : {
334 : register int c, state, oldstate;
335 : register uchar *ip;
336 : register Token *tp, *maxp;
337 : int runelen;
338 0 : Source *s = cursource;
339 0 : int nmac = 0;
340 :
341 0 : tp = trp->lp;
342 0 : ip = s->inp;
343 0 : if (reset)
344 : {
345 0 : s->lineinc = 0;
346 0 : if (ip >= s->inl)
347 : { /* nothing in buffer */
348 0 : s->inl = s->inb;
349 0 : fillbuf(s);
350 0 : ip = s->inp = s->inb;
351 : }
352 : else
353 0 : if (ip >= s->inb + (3 * INS / 4))
354 : {
355 0 : memmove(s->inb, ip, 4 + s->inl - ip);
356 0 : s->inl = s->inb + (s->inl - ip);
357 0 : ip = s->inp = s->inb;
358 : }
359 : }
360 0 : maxp = &trp->bp[trp->max];
361 0 : runelen = 1;
362 : for (;;)
363 : {
364 : continue2:
365 0 : if (tp >= maxp)
366 : {
367 0 : trp->lp = tp;
368 0 : tp = growtokenrow(trp);
369 0 : maxp = &trp->bp[trp->max];
370 : }
371 0 : tp->type = UNCLASS;
372 0 : tp->t = ip;
373 0 : tp->wslen = 0;
374 0 : tp->flag = 0;
375 0 : state = START;
376 : for (;;)
377 : {
378 0 : oldstate = state;
379 :
380 0 : c = *ip;
381 :
382 0 : if ((state = bigfsm[c][state]) >= 0)
383 : {
384 0 : ip += runelen;
385 0 : runelen = 1;
386 0 : continue;
387 : }
388 0 : state = ~state;
389 : reswitch:
390 0 : switch (state & 0177)
391 : {
392 : case S_SELF:
393 0 : ip += runelen;
394 0 : runelen = 1;
395 : case S_SELFB:
396 0 : tp->type = (unsigned char) GETACT(state);
397 0 : tp->len = ip - tp->t;
398 0 : tp++;
399 0 : goto continue2;
400 :
401 : case S_NAME: /* like S_SELFB but with nmac check */
402 0 : tp->type = NAME;
403 0 : tp->len = ip - tp->t;
404 0 : nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0);
405 0 : tp++;
406 0 : goto continue2;
407 :
408 : case S_WS:
409 0 : tp->wslen = ip - tp->t;
410 0 : tp->t = ip;
411 0 : state = START;
412 0 : continue;
413 :
414 : default:
415 0 : if ((state & QBSBIT) == 0)
416 : {
417 0 : ip += runelen;
418 0 : runelen = 1;
419 0 : continue;
420 : }
421 0 : state &= ~QBSBIT;
422 0 : s->inp = ip;
423 :
424 0 : if (c == '\n')
425 : {
426 0 : while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
427 :
428 0 : if (s->inp[1] == '\r')
429 : {
430 0 : memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2);
431 0 : s->inl -= 1;
432 : }
433 :
434 0 : goto reswitch;
435 : }
436 :
437 0 : if (c == '\r')
438 : {
439 0 : while (s->inp + 1 >= s->inl && fillbuf(s) != EOF);
440 :
441 0 : if (s->inp[1] == '\n')
442 : {
443 0 : memmove(s->inp, s->inp + 1, s->inl - s->inp + 1);
444 0 : s->inl -= 1;
445 : }
446 : else
447 0 : *s->inp = '\n';
448 :
449 0 : state = oldstate;
450 0 : continue;
451 : }
452 :
453 0 : if (c == '?')
454 : { /* check trigraph */
455 0 : if (trigraph(s))
456 : {
457 0 : state = oldstate;
458 0 : continue;
459 : }
460 0 : goto reswitch;
461 : }
462 0 : if (c == '\\')
463 : { /* line-folding */
464 0 : if (foldline(s))
465 : {
466 0 : s->lineinc++;
467 0 : state = oldstate;
468 0 : continue;
469 : }
470 0 : goto reswitch;
471 : }
472 0 : error(WARNING, "Lexical botch in cpp");
473 0 : ip += runelen;
474 0 : runelen = 1;
475 0 : continue;
476 :
477 : case S_EOB:
478 0 : s->inp = ip;
479 0 : fillbuf(cursource);
480 0 : state = oldstate;
481 0 : continue;
482 :
483 : case S_EOF:
484 0 : tp->type = END;
485 0 : tp->len = 0;
486 0 : s->inp = ip;
487 0 : if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1)
488 0 : error(WARNING, "No newline at end of file");
489 0 : trp->lp = tp + 1;
490 0 : return nmac;
491 :
492 : case S_STNL:
493 0 : error(ERROR, "Unterminated string or char const");
494 : case S_NL:
495 0 : tp->t = ip;
496 0 : tp->type = NL;
497 0 : tp->len = 1;
498 0 : tp->wslen = 0;
499 0 : s->lineinc++;
500 0 : s->inp = ip + 1;
501 0 : trp->lp = tp + 1;
502 0 : return nmac;
503 :
504 : case S_EOFSTR:
505 0 : error(FATAL, "EOF in string or char constant");
506 0 : break;
507 :
508 : case S_COMNL:
509 0 : s->lineinc++;
510 0 : state = COM2;
511 0 : ip += runelen;
512 0 : runelen = 1;
513 0 : continue;
514 :
515 : case S_EOFCOM:
516 0 : error(WARNING, "EOF inside comment");
517 0 : --ip;
518 : case S_COMMENT:
519 0 : if (!Cflag)
520 : {
521 0 : tp->t = ++ip;
522 0 : tp->t[-1] = ' ';
523 0 : tp->wslen = 1;
524 0 : state = START;
525 0 : continue;
526 : }
527 : else
528 : {
529 0 : runelen = 1;
530 0 : s->lineinc = 0;;
531 0 : tp->type = COMMENT;
532 0 : tp->flag |= XTWS;
533 : }
534 : }
535 0 : break;
536 0 : }
537 0 : ip += runelen;
538 0 : runelen = 1;
539 0 : tp->len = ip - tp->t;
540 0 : tp++;
541 0 : }
542 : }
543 :
544 : /* have seen ?; handle the trigraph it starts (if any) else 0 */
545 : int
546 0 : trigraph(Source * s)
547 : {
548 : uchar c;
549 :
550 0 : while (s->inp + 2 >= s->inl && fillbuf(s) != EOF);
551 : ;
552 0 : if (s->inp[1] != '?')
553 0 : return 0;
554 0 : c = 0;
555 0 : switch (s->inp[2])
556 : {
557 : case '=':
558 0 : c = '#';
559 0 : break;
560 : case '(':
561 0 : c = '[';
562 0 : break;
563 : case '/':
564 0 : c = '\\';
565 0 : break;
566 : case ')':
567 0 : c = ']';
568 0 : break;
569 : case '\'':
570 0 : c = '^';
571 0 : break;
572 : case '<':
573 0 : c = '{';
574 0 : break;
575 : case '!':
576 0 : c = '|';
577 0 : break;
578 : case '>':
579 0 : c = '}';
580 0 : break;
581 : case '-':
582 0 : c = '~';
583 0 : break;
584 : }
585 0 : if (c)
586 : {
587 0 : *s->inp = c;
588 0 : memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2);
589 0 : s->inl -= 2;
590 : }
591 0 : return c;
592 : }
593 :
594 : int
595 0 : foldline(Source * s)
596 : {
597 0 : int n = 1;
598 :
599 : /* skip pending wihite spaces */
600 0 : while ((s->inp[n] == ' ') || (s->inp[n] == '\t'))
601 : {
602 0 : n++;
603 0 : if ((s->inp + n >= s->inl) && (fillbuf(s) == EOF))
604 0 : break;
605 : }
606 :
607 : /* refill buffer */
608 0 : while (s->inp + (n + 1) >= s->inl && fillbuf(s) != EOF);
609 :
610 : /* skip DOS line ends */
611 0 : if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) ||
612 0 : ((s->inp[n] == '\n') && (s->inp[n+1] == '\r')))
613 0 : n++;
614 :
615 0 : if ((s->inp[n] == '\n') || (s->inp[n] == '\r'))
616 : {
617 0 : memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2);
618 0 : s->inl -= n + 1;
619 0 : return 1;
620 : }
621 0 : return 0;
622 : }
623 :
624 : int
625 0 : fillbuf(Source * s)
626 : {
627 : int n;
628 :
629 0 : if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0)
630 0 : n = 0;
631 0 : s->inl += n;
632 0 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB;
633 0 : if (n == 0)
634 : {
635 0 : s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
636 0 : return EOF;
637 : }
638 0 : return 0;
639 : }
640 :
641 : /*
642 : * Push down to new source of characters.
643 : * If fd>0 and str==NULL, then from a file `name';
644 : * if fd==-1 and str, then from the string.
645 : */
646 : Source *
647 0 : setsource(char *name, int path, int fd, char *str, int wrap)
648 : {
649 0 : Source *s = new(Source);
650 : size_t len;
651 :
652 0 : s->line = 1;
653 0 : s->lineinc = 0;
654 0 : s->fd = fd;
655 0 : s->filename = name;
656 0 : s->next = cursource;
657 0 : s->ifdepth = 0;
658 0 : s->pathdepth = path;
659 0 : s->wrap = wrap;
660 :
661 0 : cursource = s;
662 :
663 0 : if (s->wrap)
664 0 : genwrap(0);
665 :
666 : /* slop at right for EOB */
667 0 : if (str)
668 : {
669 0 : len = strlen(str);
670 0 : s->inb = domalloc(len + 4);
671 0 : s->inp = s->inb;
672 0 : strncpy((char *) s->inp, str, len);
673 : }
674 : else
675 : {
676 0 : s->inb = domalloc(INS + 4);
677 0 : s->inp = s->inb;
678 0 : len = 0;
679 : }
680 0 : s->inl = s->inp + len;
681 0 : s->inl[0] = s->inl[1] = EOB;
682 :
683 0 : return s;
684 : }
685 :
686 : void
687 0 : unsetsource(void)
688 : {
689 0 : Source *s = cursource;
690 :
691 0 : if (s->wrap)
692 0 : genwrap(1);
693 :
694 0 : if (s->fd >= 0)
695 : {
696 0 : close(s->fd);
697 0 : dofree(s->inb);
698 : }
699 0 : cursource = s->next;
700 0 : dofree(s);
701 0 : }
702 :
703 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|