1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/* heredoc.c -- in-line files (here documents) ($Revision: 1.1.1.1 $) */
#include "es.h"
#include "gc.h"
#include "input.h"
#include "syntax.h"
typedef struct Here Here;
struct Here {
Here *next;
Tree *marker;
};
static Here *hereq;
/* getherevar -- read a variable from a here doc */
extern Tree *getherevar(void) {
int c;
char *s;
Buffer *buf = openbuffer(0);
while (!dnw[c = GETC()])
buf = bufputc(buf, c);
s = sealcountedbuffer(buf);
if (buf->len == 0) {
yyerror("null variable name in here document");
return NULL;
}
if (c != '^')
UNGETC(c);
return flatten(mk(nVar, mk(nWord, s)), " ");
}
/* snarfheredoc -- read a heredoc until the eof marker */
extern Tree *snarfheredoc(const char *eof, Boolean quoted) {
Tree *tree, **tailp;
Buffer *buf;
unsigned char *s;
assert(quoted || strchr(eof, '$') == NULL); /* can never be typed (whew!) */
if (strchr(eof, '\n') != NULL) {
yyerror("here document eof-marker contains a newline");
return NULL;
}
disablehistory = TRUE;
for (tree = NULL, tailp = &tree, buf = openbuffer(0);;) {
int c;
print_prompt2();
for (s = (unsigned char *) eof; (c = GETC()) == *s; s++)
;
if (*s == '\0' && (c == '\n' || c == EOF)) {
if (buf->current == 0 && tree != NULL)
freebuffer(buf);
else
*tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL);
break;
}
if (s != (unsigned char *) eof)
buf = bufncat(buf, eof, s - (unsigned char *) eof);
for (;; c = GETC()) {
if (c == EOF) {
yyerror("incomplete here document");
freebuffer(buf);
disablehistory = FALSE;
return NULL;
}
if (c == '$' && !quoted && (c = GETC()) != '$') {
Tree *var;
UNGETC(c);
if (buf->current == 0)
freebuffer(buf);
else {
*tailp = treecons(mk(nQword, sealcountedbuffer(buf)), NULL);
tailp = &(*tailp)->CDR;
}
var = getherevar();
if (var == NULL) {
freebuffer(buf);
disablehistory = FALSE;
return NULL;
}
*tailp = treecons(var, NULL);
tailp = &(*tailp)->CDR;
buf = openbuffer(0);
continue;
}
buf = bufputc(buf, c);
if (c == '\n')
break;
}
}
disablehistory = FALSE;
return tree->CDR == NULL ? tree->CAR : tree;
}
/* readheredocs -- read all the heredocs at the end of a line (or fail if at end of file) */
extern Boolean readheredocs(Boolean endfile) {
for (; hereq != NULL; hereq = hereq->next) {
Tree *marker, *eof;
if (endfile) {
yyerror("end of file with pending here documents");
return FALSE;
}
marker = hereq->marker;
eof = marker->CAR;
marker->CAR = snarfheredoc(eof->u[0].s, eof->kind == nQword);
if (marker->CAR == NULL)
return FALSE;
}
return TRUE;
}
/* queueheredoc -- add a heredoc to the queue to process at the end of the line */
extern Boolean queueheredoc(Tree *t) {
Tree *eof;
Here *here;
assert(hereq == NULL || hereq->marker->kind == nList);
assert(t->kind == nList);
assert(t->CAR->kind == nWord);
#if !REISER_CPP
assert(streq(t->CAR->u[0].s, "%heredoc"));
#endif
t->CAR->u[0].s = "%here";
assert(t->CDR->kind == nList);
eof = t->CDR->CDR;
assert(eof->kind == nList);
if (eof->CAR->kind != nWord && eof->CAR->kind != nQword) {
yyerror("here document eof-marker not a single literal word");
return FALSE;
}
here = gcalloc(sizeof (Here), NULL);
here->next = hereq;
here->marker = eof;
hereq = here;
return TRUE;
}
extern void emptyherequeue(void) {
hereq = NULL;
disablehistory = FALSE;
}
|