13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "io.h"
43e12c5d1SDavid du Colombier #include "fns.h"
5*8cc1c73aSDavid du Colombier
63e12c5d1SDavid du Colombier struct here *here, **ehere;
73e12c5d1SDavid du Colombier int ser = 0;
83e12c5d1SDavid du Colombier char tmp[] = "/tmp/here0000.0000";
93e12c5d1SDavid du Colombier char hex[] = "0123456789abcdef";
10276e7d6dSDavid du Colombier
11276e7d6dSDavid du Colombier void psubst(io*, uchar*);
123e12c5d1SDavid du Colombier void pstrs(io*, word*);
13dc5a79c1SDavid du Colombier
14dc5a79c1SDavid du Colombier void
hexnum(char * p,int n)15dc5a79c1SDavid du Colombier hexnum(char *p, int n)
163e12c5d1SDavid du Colombier {
173e12c5d1SDavid du Colombier *p++ = hex[(n>>12)&0xF];
183e12c5d1SDavid du Colombier *p++ = hex[(n>>8)&0xF];
193e12c5d1SDavid du Colombier *p++ = hex[(n>>4)&0xF];
203e12c5d1SDavid du Colombier *p = hex[n&0xF];
213e12c5d1SDavid du Colombier }
22dc5a79c1SDavid du Colombier
23dc5a79c1SDavid du Colombier tree*
heredoc(tree * tag)24dc5a79c1SDavid du Colombier heredoc(tree *tag)
253e12c5d1SDavid du Colombier {
263e12c5d1SDavid du Colombier struct here *h = new(struct here);
27*8cc1c73aSDavid du Colombier
28dc5a79c1SDavid du Colombier if(tag->type != WORD)
29dc5a79c1SDavid du Colombier yyerror("Bad here tag");
303e12c5d1SDavid du Colombier h->next = 0;
313e12c5d1SDavid du Colombier if(here)
323e12c5d1SDavid du Colombier *ehere = h;
333e12c5d1SDavid du Colombier else
343e12c5d1SDavid du Colombier here = h;
353e12c5d1SDavid du Colombier ehere = &h->next;
363e12c5d1SDavid du Colombier h->tag = tag;
373e12c5d1SDavid du Colombier hexnum(&tmp[9], getpid());
383e12c5d1SDavid du Colombier hexnum(&tmp[14], ser++);
393e12c5d1SDavid du Colombier h->name = strdup(tmp);
403e12c5d1SDavid du Colombier return token(tmp, WORD);
413e12c5d1SDavid du Colombier }
42*8cc1c73aSDavid du Colombier
433e12c5d1SDavid du Colombier /*
443e12c5d1SDavid du Colombier * bug: lines longer than NLINE get split -- this can cause spurious
453e12c5d1SDavid du Colombier * missubstitution, or a misrecognized EOF marker.
463e12c5d1SDavid du Colombier */
473e12c5d1SDavid du Colombier #define NLINE 4096
48dc5a79c1SDavid du Colombier
49dc5a79c1SDavid du Colombier void
readhere(void)50dc5a79c1SDavid du Colombier readhere(void)
51dc5a79c1SDavid du Colombier {
5299eb86a7SDavid du Colombier int c, subst;
53*8cc1c73aSDavid du Colombier char *s, *tag;
543e12c5d1SDavid du Colombier char line[NLINE+1];
55*8cc1c73aSDavid du Colombier io *f;
56*8cc1c73aSDavid du Colombier struct here *h, *nexth;
57*8cc1c73aSDavid du Colombier
583e12c5d1SDavid du Colombier for(h = here; h; h = nexth){
593e12c5d1SDavid du Colombier subst = !h->tag->quoted;
603e12c5d1SDavid du Colombier tag = h->tag->str;
613e12c5d1SDavid du Colombier c = Creat(h->name);
62dc5a79c1SDavid du Colombier if(c < 0)
63dc5a79c1SDavid du Colombier yyerror("can't create here document");
643e12c5d1SDavid du Colombier f = openfd(c);
653e12c5d1SDavid du Colombier s = line;
663e12c5d1SDavid du Colombier pprompt();
673e12c5d1SDavid du Colombier while((c = rchr(runq->cmdfd)) != EOF){
683e12c5d1SDavid du Colombier if(c == '\n' || s == &line[NLINE]){
693e12c5d1SDavid du Colombier *s = '\0';
70*8cc1c73aSDavid du Colombier if(tag && strcmp(line, tag) == 0)
71*8cc1c73aSDavid du Colombier break;
72dc5a79c1SDavid du Colombier if(subst)
73276e7d6dSDavid du Colombier psubst(f, (uchar *)line);
74276e7d6dSDavid du Colombier else
75276e7d6dSDavid du Colombier pstr(f, line);
763e12c5d1SDavid du Colombier s = line;
773e12c5d1SDavid du Colombier if(c == '\n'){
783e12c5d1SDavid du Colombier pprompt();
793e12c5d1SDavid du Colombier pchr(f, c);
80*8cc1c73aSDavid du Colombier }else
81*8cc1c73aSDavid du Colombier *s++ = c;
82*8cc1c73aSDavid du Colombier }else
83*8cc1c73aSDavid du Colombier *s++ = c;
843e12c5d1SDavid du Colombier }
853e12c5d1SDavid du Colombier flush(f);
863e12c5d1SDavid du Colombier closeio(f);
873e12c5d1SDavid du Colombier cleanhere(h->name);
883e12c5d1SDavid du Colombier nexth = h->next;
893e12c5d1SDavid du Colombier efree((char *)h);
903e12c5d1SDavid du Colombier }
913e12c5d1SDavid du Colombier here = 0;
923e12c5d1SDavid du Colombier doprompt = 1;
933e12c5d1SDavid du Colombier }
94dc5a79c1SDavid du Colombier
95dc5a79c1SDavid du Colombier void
psubst(io * f,uchar * s)96276e7d6dSDavid du Colombier psubst(io *f, uchar *s)
973e12c5d1SDavid du Colombier {
987dd7cddfSDavid du Colombier int savec, n;
99276e7d6dSDavid du Colombier uchar *t, *u;
100*8cc1c73aSDavid du Colombier Rune r;
1013e12c5d1SDavid du Colombier word *star;
102*8cc1c73aSDavid du Colombier
1033e12c5d1SDavid du Colombier while(*s){
104*8cc1c73aSDavid du Colombier if(*s != '$'){ /* copy plain text rune */
105*8cc1c73aSDavid du Colombier if(*s < Runeself)
1063e12c5d1SDavid du Colombier pchr(f, *s++);
1073e12c5d1SDavid du Colombier else{
108*8cc1c73aSDavid du Colombier n = chartorune(&r, (char *)s);
109*8cc1c73aSDavid du Colombier while(n-- > 0)
110*8cc1c73aSDavid du Colombier pchr(f, *s++);
111*8cc1c73aSDavid du Colombier }
112*8cc1c73aSDavid du Colombier }else{ /* $something -- perform substitution */
1133e12c5d1SDavid du Colombier t = ++s;
114dc5a79c1SDavid du Colombier if(*t == '$')
115dc5a79c1SDavid du Colombier pchr(f, *t++);
1163e12c5d1SDavid du Colombier else{
117*8cc1c73aSDavid du Colombier while(*t && idchr(*t))
118*8cc1c73aSDavid du Colombier t++;
1193e12c5d1SDavid du Colombier savec = *t;
1203e12c5d1SDavid du Colombier *t = '\0';
1213e12c5d1SDavid du Colombier n = 0;
122*8cc1c73aSDavid du Colombier for(u = s; *u && '0' <= *u && *u <= '9'; u++)
123*8cc1c73aSDavid du Colombier n = n*10 + *u - '0';
1243e12c5d1SDavid du Colombier if(n && *u == '\0'){
1253e12c5d1SDavid du Colombier star = vlook("*")->val;
1263e12c5d1SDavid du Colombier if(star && 1 <= n && n <= count(star)){
127*8cc1c73aSDavid du Colombier while(--n)
128*8cc1c73aSDavid du Colombier star = star->next;
1293e12c5d1SDavid du Colombier pstr(f, star->word);
1303e12c5d1SDavid du Colombier }
131*8cc1c73aSDavid du Colombier }else
132276e7d6dSDavid du Colombier pstrs(f, vlook((char *)s)->val);
1333e12c5d1SDavid du Colombier *t = savec;
134dc5a79c1SDavid du Colombier if(savec == '^')
135dc5a79c1SDavid du Colombier t++;
1363e12c5d1SDavid du Colombier }
1373e12c5d1SDavid du Colombier s = t;
1383e12c5d1SDavid du Colombier }
1393e12c5d1SDavid du Colombier }
1403e12c5d1SDavid du Colombier }
141dc5a79c1SDavid du Colombier
142dc5a79c1SDavid du Colombier void
pstrs(io * f,word * a)143dc5a79c1SDavid du Colombier pstrs(io *f, word *a)
1443e12c5d1SDavid du Colombier {
1453e12c5d1SDavid du Colombier if(a){
1463e12c5d1SDavid du Colombier while(a->next && a->next->word){
1473e12c5d1SDavid du Colombier pstr(f, a->word);
1483e12c5d1SDavid du Colombier pchr(f, ' ');
1493e12c5d1SDavid du Colombier a = a->next;
1503e12c5d1SDavid du Colombier }
1513e12c5d1SDavid du Colombier pstr(f, a->word);
1523e12c5d1SDavid du Colombier }
1533e12c5d1SDavid du Colombier }
154