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