/* heredoc.c: heredoc slurping is done here */
static bool dead
= FALSE
;
* read in a heredocument. A clever trick: skip over any partially matched end-of-file
* marker storing only the number of characters matched. If the whole marker is matched,
* return from readheredoc(). If only part of the marker is matched, copy that part into
* BUG: if the eof string contains a newline, the state can get confused, and the
* heredoc may continue past where it should. on the other hand, /bin/sh seems to
* never get out of its readheredoc() when the heredoc string contains a newline
static char *readheredoc(char *eof
) {
t
= buf
= nalloc(bufsize
= 512);
#define RESIZE(extra) { \
bufsize = bufsize * 2 + extra; \
nbuf = nalloc(bufsize); \
memcpy(nbuf, buf, (size_t) (t - buf)); \
bufend = &buf[bufsize]; \
for (s
= (unsigned char *) eof
; (c
= gchar()) == *s
; s
++)
if (*s
== '\0' && (c
== '\n' || c
== EOF
)) {
if (s
!= (unsigned char *) eof
) {
size_t len
= s
- (unsigned char *) eof
;
yyerror("heredoc incomplete");
/* parseheredoc -- turn a heredoc with variable references into a node chain */
static Node
*parseheredoc(char *s
) {
while ((c
= *s
++) != '\0' && c
!= '$')
node
= mk(nQword
, begin
, NULL
);
node
= mk(nQword
, "$", NULL
);
while (!dnw
[c
= *(unsigned char *) s
++]);
node
= mk(nFlat
, mk(nWord
, var
, NULL
));
result
= (result
== NULL
) ? node
: mk(nConcat
, result
, node
);
/* read in heredocs when yyparse hits a newline. called from yyparse */
extern int heredoc(int end
) {
if ((here
= hq
) != NULL
) {
yyerror("heredoc incomplete");
char *s
= readheredoc(here
->name
);
n
->u
[2].p
= here
->quoted
? mk(nQword
, s
, NULL
) : parseheredoc(s
);
} while ((here
= here
->n
) != NULL
);
/* queue pending heredocs into a queue. called from yyparse */
extern int qdoc(Node
*name
, Node
*n
) {
if (name
->type
!= nWord
&& name
->type
!= nQword
) {
yyerror("eof-marker not a single literal word");
for (prev
= &hq
; (new = *prev
) != NULL
; prev
= &new->n
)
new->name
= name
->u
[0].s
;
new->quoted
= (name
->type
== nQword
);