1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1986-2009 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
19 ***********************************************************************/
25 * preprocessor stacked input stream support
32 * convert path to native representation
36 #include "../../lib/libast/path/pathnative.c" /* drop in 2002 */
38 /* Modified by gisburn 2006-08-18 for OpenSolaris ksh93-integration */
39 #include "../../libast/common/path/pathnative.c"
43 native(register const char* s
)
46 register struct ppfile
* xp
;
55 if (!np
&& !(np
= sfstropen()) || !qp
&& !(qp
= sfstropen()))
61 n
= pathnative(s
, sfstrrsrv(np
, m
), m
);
63 sfstrseek(np
, n
, SEEK_CUR
);
64 s
= (const char*)sfstruse(np
);
81 if (!(xp
= ppsetfile(sfstruse(qp
))))
87 * push stream onto input stack
88 * used by the PUSH_type macros
92 pppush(register int t
, register char* s
, register char* p
, int n
)
94 register struct ppinstk
* cur
;
97 cur
->line
= error_info
.line
;
98 cur
->file
= error_info
.file
;
102 if (pp
.option
& NATIVE
)
104 cur
->flags
|= IN_newline
;
106 cur
->hide
= ++pp
.hide
;
109 if ((pp
.mode
& (DUMP
|INIT
)) == DUMP
)
111 cur
->index
= newof(0, struct ppindex
, 1, 0);
112 if (pp
.lastindex
) pp
.lastindex
->next
= cur
->index
;
113 else pp
.firstindex
= cur
->index
;
114 pp
.lastindex
= cur
->index
;
115 cur
->index
->file
= pp
.original
;
116 cur
->index
->begin
= ppoffset();
121 if (!(pp
.mode
& DUMP
))
123 if (!cur
->prev
->prev
&& !(pp
.state
& COMPILE
) && isatty(0))
124 cur
->flags
|= IN_flush
;
128 switch (pp
.member
->archive
->type
& (TYPE_BUFFER
|TYPE_CHECKPOINT
))
132 cur
->buflen
= pp
.member
->size
;
134 p
= (cur
->buffer
= oldof(0, char, 0, pp
.member
->size
+ PPBAKSIZ
+ 1)) + PPBAKSIZ
;
135 if (sfseek(pp
.member
->archive
->info
.sp
, pp
.member
->offset
, SEEK_SET
) != pp
.member
->offset
)
136 error(3, "%s: archive seek error", pp
.member
->archive
->name
);
137 if (sfread(pp
.member
->archive
->info
.sp
, p
, pp
.member
->size
) != pp
.member
->size
)
138 error(3, "%s: archive read error", pp
.member
->archive
->name
);
143 case TYPE_CHECKPOINT
|TYPE_BUFFER
:
144 cur
->buflen
= pp
.member
->size
;
146 p
= cur
->buffer
= pp
.member
->archive
->info
.buffer
+ pp
.member
->offset
;
147 cur
->flags
|= IN_static
;
151 case TYPE_CHECKPOINT
:
152 p
= cur
->buffer
= "";
153 cur
->flags
|= IN_static
;
157 cur
->flags
|= IN_eof
|IN_newline
;
163 if (lseek(cur
->fd
, 0L, SEEK_END
) > 0 && !lseek(cur
->fd
, 0L, SEEK_SET
))
164 cur
->flags
|= IN_regular
;
167 if (!(pp
.option
& NOPROTO
) && !(pp
.test
& TEST_noproto
) && ((pp
.state
& (COMPATIBILITY
|TRANSITION
)) == COMPATIBILITY
|| (pp
.option
& PLUSPLUS
) || (pp
.mode
& EXTERNALIZE
)) && (cur
->buffer
= pppopen(NiL
, cur
->fd
, NiL
, NiL
, NiL
, NiL
, (PROTO_HEADER
|PROTO_RETAIN
)|(((pp
.mode
& EXTERNALIZE
) || (pp
.option
& PROTOTYPED
)) ? PROTO_FORCE
: PROTO_PASS
)|((pp
.mode
& EXTERNALIZE
) ? PROTO_EXTERNALIZE
: 0)|((pp
.mode
& MARKC
) ? PROTO_PLUSPLUS
: 0))))
169 *(p
= cur
->buffer
- 1) = 0;
170 cur
->buffer
-= PPBAKSIZ
;
171 cur
->flags
|= IN_prototype
;
176 *(p
= (cur
->buffer
= oldof(0, char, 0, PPBUFSIZ
+ PPBAKSIZ
+ 1)) + PPBAKSIZ
) = 0;
178 if (pp
.incref
&& !(pp
.mode
& INIT
))
179 (*pp
.incref
)(error_info
.file
, s
, error_info
.line
- 1, PP_SYNC_PUSH
);
180 if (pp
.macref
|| (pp
.option
& IGNORELINE
))
181 cur
->flags
|= IN_ignoreline
;
182 cur
->prefix
= pp
.prefix
;
188 cur
->control
= pp
.control
;
190 cur
->vendor
= pp
.vendor
;
191 if (cur
->type
!= IN_RESCAN
)
193 if (cur
->type
== IN_INIT
)
194 pp
.mode
|= MARKHOSTED
;
198 if (pp
.state
& HIDDEN
)
202 if (!(pp
.state
& NOTEXT
) && pplastout() != '\n')
206 if (pp
.mode
& HOSTED
) cur
->flags
|= IN_hosted
;
207 else cur
->flags
&= ~IN_hosted
;
208 if (pp
.mode
& (INIT
|MARKHOSTED
))
211 pp
.flags
|= PP_hosted
;
216 if (!(pp
.mode
& (INIT
|MARKHOSTED
)))
219 pp
.flags
&= ~PP_hosted
;
222 if (pp
.state
& JOINING
) pp
.state
|= HIDDEN
|SYNCLINE
;
226 (*pp
.linesync
)(error_info
.line
, error_info
.file
);
227 #if ARCHIVE && CHECKPOINT
235 if (!(cur
->prev
->flags
& IN_c
))
237 debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp
.in
), pptokchr(*pp
.in
->nextchr
), pp
.in
->nextchr
));
238 PUSH_BUFFER("C", "extern \"C\" {\n", 1);
242 else if (cur
->prev
->flags
& IN_c
)
244 debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp
.in
), pptokchr(*pp
.in
->nextchr
), pp
.in
->nextchr
));
245 PUSH_BUFFER("C", "extern \"C++\" {\n", 1);
250 cur
->buffer
= p
= strdup(p
);
260 error(PANIC
, "use PUSH_<%d>(...) instead of pppush(IN_<%d>, ...)", cur
->type
, cur
->type
);
264 debug((-7, "PUSH in=%s next=%s", ppinstr(pp
.in
), pptokchr(*pp
.in
->nextchr
)));
268 * external buffer push
272 ppinput(char* b
, char* f
, int n
)
274 PUSH_BUFFER(f
, b
, n
);
278 * return expanded value of buffer p
282 ppexpand(register char* p
)
290 struct ppmacstk
* nextmacp
;
293 debug((-7, "before expand: %s", p
));
294 if (ppmactop
= pp
.mactop
)
296 nextmacp
= pp
.macp
->next
;
297 nextframe(pp
.macp
, pp
.mactop
);
299 restore
= pp
.state
& (COLLECTING
|DISABLE
|STRIP
);
300 pp
.state
&= ~restore
;
301 pp
.mode
&= ~MARKMACRO
;
304 pp
.in
->flags
|= IN_expand
;
307 pp
.token
= p
= oldof(0, char, 0, n
);
313 if ((pp
.token
= pp
.toknxt
) > m
)
316 p
= newof(p
, char, n
+= MAXTOKEN
, 0);
317 m
= p
+ n
- MAXTOKEN
;
320 if (pp
.mode
& MARKMACRO
)
322 pp
.mode
&= ~MARKMACRO
;
327 else if (pp
.in
== cur
)
332 pp
.macp
->next
= nextmacp
;
333 debug((-7, "after expand: %s", p
));
342 #define LOAD_FUNCTION (1<<0)
343 #define LOAD_MULTILINE (1<<1)
344 #define LOAD_NOEXPAND (1<<2)
345 #define LOAD_PREDICATE (1<<3)
346 #define LOAD_READONLY (1<<4)
347 #define LOAD_VARIADIC (1<<5)
350 * macro definition dump
354 dump(const char* name
, char* v
, void* handle
)
356 register struct ppmacro
* mac
;
357 register struct ppsymbol
* sym
= (struct ppsymbol
*)v
;
362 if ((mac
= sym
->macro
) && !(sym
->flags
& (SYM_BUILTIN
|SYM_PREDEFINED
)))
364 ppprintf("%s", sym
->name
);
367 if (sym
->flags
& SYM_FUNCTION
) flags
|= LOAD_FUNCTION
;
368 if (sym
->flags
& SYM_MULTILINE
) flags
|= LOAD_MULTILINE
;
369 if (sym
->flags
& SYM_NOEXPAND
) flags
|= LOAD_NOEXPAND
;
370 if (sym
->flags
& SYM_PREDICATE
) flags
|= LOAD_PREDICATE
;
371 if (sym
->flags
& SYM_READONLY
) flags
|= LOAD_READONLY
;
372 if (sym
->flags
& SYM_VARIADIC
) flags
|= LOAD_VARIADIC
;
374 if (sym
->flags
& SYM_FUNCTION
)
376 ppprintf("%d", mac
->arity
);
380 ppprintf("%s", mac
->formals
);
384 ppprintf("%s", mac
->value
);
391 * dump macro definitions for quick loading via ppload()
397 register struct ppindex
* ip
;
398 unsigned long macro_offset
;
399 unsigned long index_offset
;
402 * NOTE: we assume '\0' does not occur in valid preprocessed output
408 * output global flags
411 macro_offset
= ppoffset();
415 * output macro definitions
418 hashwalk(pp
.symtab
, 0, dump
, NiL
);
422 * output include file index
425 index_offset
= ppoffset();
429 ppprintf("%s", ip
->file
->name
);
431 if (ip
->file
->guard
!= INC_CLEAR
&& ip
->file
->guard
!= INC_IGNORE
&& ip
->file
->guard
!= INC_TEST
)
432 ppprintf("%s", ip
->file
->guard
->name
);
434 ppprintf("%lu", ip
->begin
);
436 ppprintf("%lu", ip
->end
);
443 * output offset directory
446 ppprintf("%010lu", macro_offset
);
448 ppprintf("%010lu", index_offset
);
454 * load text and macro definitions from a previous ppdump()
455 * s is the string argument from the pragma (including quotes)
459 ppload(register char* s
)
468 unsigned long macro_offset
;
469 unsigned long index_offset
;
470 unsigned long file_offset
;
471 unsigned long file_size
;
472 unsigned long keep_begin
;
473 unsigned long keep_end
;
474 unsigned long skip_end
;
475 unsigned long next_begin
;
476 unsigned long next_end
;
478 struct ppsymbol
* sym
;
484 if (!(pp
.state
& STANDALONE
))
485 error(3, "checkpoint load in standalone mode only");
489 sp
= pp
.member
->archive
->info
.sp
;
490 file_offset
= pp
.member
->offset
;
491 file_size
= pp
.member
->size
;
492 if (sfseek(sp
, file_offset
+ 22, SEEK_SET
) != file_offset
+ 22 || !(s
= sfgetr(sp
, '\n', 1)))
493 error(3, "checkpoint magic error");
498 if (pp
.in
->type
!= IN_FILE
)
499 error(3, "checkpoint load from files only");
500 if (pp
.in
->flags
& IN_prototype
)
501 pp
.in
->fd
= pppdrop(pp
.in
->buffer
+ PPBAKSIZ
);
505 if (!(sp
= sfnew(NiL
, NiL
, SF_UNBOUND
, pp
.in
->fd
, SF_READ
)))
506 error(3, "checkpoint read error");
507 file_size
= sfseek(sp
, 0L, SEEK_END
);
511 file_size
= pp
.in
->buflen
;
512 if (!(sp
= sfnew(NiL
, pp
.in
->buffer
+ ((pp
.in
->flags
& IN_static
) ? 0 : PPBAKSIZ
), file_size
, -1, SF_READ
|SF_STRING
)))
513 error(3, "checkpoint read error");
516 if (!streq(s
, pp
.checkpoint
))
517 error(3, "checkpoint version %s does not match %s", s
, pp
.checkpoint
);
520 * get the macro and index offsets
523 p
= file_offset
+ file_size
- 22;
524 if ((n
= sfseek(sp
, p
, SEEK_SET
)) != p
)
525 error(3, "checkpoint directory seek error");
526 if (!(t
= sfreserve(sp
, 22, 0)))
527 error(3, "checkpoint directory read error");
528 macro_offset
= file_offset
+ strtol(t
, &t
, 10);
529 index_offset
= file_offset
+ strtol(t
+ 1, NiL
, 10);
532 * read the include index
535 if (sfseek(sp
, index_offset
, SEEK_SET
) != index_offset
)
536 error(3, "checkpoint index seek error");
537 if (!(s
= sfreserve(sp
, n
- index_offset
, 0)))
538 error(3, "checkpoint index read error");
539 if (sfset(sp
, 0, 0) & SF_STRING
)
541 else if (!(b
= ip
= memdup(s
, n
- index_offset
)))
542 error(3, "checkpoint index alloc error");
545 * loop on the index and copy the non-ignored chunks to the output
549 p
= PPBUFSIZ
- (pp
.outp
- pp
.outbuf
);
559 next_begin
= strtol(b
, &t
, 10);
560 next_end
= strtol(t
+ 1, &t
, 10);
561 if (pp
.test
& 0x0200) error(2, "%s: %s p=%lu next=<%lu,%lu> keep=<%lu,%lu> skip=<-,%lu> guard=%s", keyname(X_CHECKPOINT
), fp
->name
, p
, next_begin
, next_end
, keep_begin
, keep_end
, skip_end
, fp
->guard
== INC_CLEAR
? "[CLEAR]" : fp
->guard
== INC_TEST
? "[TEST]" : fp
->guard
== INC_IGNORE
? "[IGNORE]" : fp
->guard
->name
);
563 if (next_begin
>= skip_end
)
565 if (!ppmultiple(fp
, INC_TEST
))
567 if (pp
.test
& 0x0100) error(2, "%s: %s IGNORE", keyname(X_CHECKPOINT
), fp
->name
);
568 if (!keep_begin
&& skip_end
< next_begin
)
569 keep_begin
= skip_end
;
573 if (sfseek(sp
, file_offset
+ keep_begin
, SEEK_SET
) != file_offset
+ keep_begin
)
574 error(3, "checkpoint data seek error");
575 n
= next_begin
- keep_begin
;
576 if (pp
.test
& 0x0100) error(2, "%s: copy <%lu,%lu> n=%lu p=%lu", keyname(X_CHECKPOINT
), keep_begin
, next_begin
- 1, n
, p
);
579 if (sfread(sp
, pp
.outp
, p
) != p
)
580 error(3, "checkpoint data read error");
588 if (sfread(sp
, pp
.outp
, n
) != n
)
589 error(3, "checkpoint data read error");
594 if (keep_end
<= next_end
)
599 else if (!keep_begin
)
603 keep_begin
= skip_end
;
606 else keep_begin
= next_begin
;
607 if (keep_end
< next_end
)
611 if (*g
&& fp
->guard
!= INC_IGNORE
)
612 fp
->guard
= ppsymset(pp
.symtab
, g
);
617 keep_begin
= skip_end
> next_end
? skip_end
: next_end
;
618 next_begin
= next_end
= keep_end
;
622 if (pp
.test
& 0x0100) error(2, "%s: loop", keyname(X_CHECKPOINT
));
625 * read the compacted definitions
628 if (sfseek(sp
, macro_offset
, SEEK_SET
) != macro_offset
)
629 error(3, "checkpoint macro seek error");
630 if (!(s
= sfreserve(sp
, index_offset
- macro_offset
, 0)))
631 error(3, "checkpoint macro read error");
640 if (streq(s
, "OPTION")) /* ... */;
643 error(3, "%-.48s: unknown flags in checkpoint file", s
);
648 * unpack and enter the definitions
656 sym
= ppsymset(pp
.symtab
, b
);
659 if (m
& LOAD_FUNCTION
)
665 if (pp
.test
& 0x1000) error(2, "checkpoint SKIP %s=%s [%s]", sym
->name
, s
, sym
->macro
->value
);
672 if (m
& LOAD_FUNCTION
) sym
->flags
|= SYM_FUNCTION
;
673 if (m
& LOAD_MULTILINE
) sym
->flags
|= SYM_MULTILINE
;
674 if (m
& LOAD_NOEXPAND
) sym
->flags
|= SYM_NOEXPAND
;
675 if (m
& LOAD_PREDICATE
) sym
->flags
|= SYM_PREDICATE
;
676 if (m
& LOAD_READONLY
) sym
->flags
|= SYM_READONLY
;
677 if (m
& LOAD_VARIADIC
) sym
->flags
|= SYM_VARIADIC
;
678 mac
= sym
->macro
= newof(0, struct ppmacro
, 1, 0);
679 if (sym
->flags
& SYM_FUNCTION
)
681 for (n
= 0; *s
>= '0' && *s
<= '9'; n
= n
* 10 + *s
++ - '0');
682 if (*s
++) error(3, "%-.48: checkpoint macro arity botched", sym
->name
);
687 mac
->formals
= (char*)memcpy(oldof(0, char, 0, s
- b
), b
, s
- b
);
692 mac
->size
= s
- b
- 1;
693 mac
->value
= (char*)memcpy(oldof(0, char, 0, mac
->size
+ 1), b
, mac
->size
+ 1);
694 if (pp
.test
& 0x1000) error(2, "checkpoint LOAD %s=%s", sym
->name
, mac
->value
);
708 if (pp
.member
) pp
.member
= 0;
713 pp
.in
->flags
|= IN_eof
|IN_newline
;
714 pp
.in
->nextchr
= pp
.in
->buffer
+ PPBAKSIZ
;
715 *pp
.in
->nextchr
++ = 0;