#include "rc.h"#include "exec.h"#include "io.h"#include "fns.h"struct here *here, **ehere;int ser = 0;char tmp[]="/tmp/here0000.0000";char hex[]="0123456789abcdef"; void psubst(io*, char*);void pstrs(io*, word*); voidhexnum(char *p, int n){ *p++=hex[(n>>12)&0xF]; *p++=hex[(n>>8)&0xF]; *p++=hex[(n>>4)&0xF]; *p = hex[n&0xF];} tree*heredoc(tree *tag){ struct here *h = new(struct here); if(tag->type!=WORD) yyerror("Bad here tag"); h->next = 0; if(here) *ehere = h; else here = h; ehere=&h->next; h->tag = tag; hexnum(&tmp[9], getpid()); hexnum(&tmp[14], ser++); h->name = strdup(tmp); return token(tmp, WORD);}/* * bug: lines longer than NLINE get split -- this can cause spurious * missubstitution, or a misrecognized EOF marker. */#define NLINE 4096 voidreadhere(void){ struct here *h, *nexth; io *f; char *s, *tag; int n, subst; char line[NLINE+1]; Rune r; for(h = here;h;h = nexth){ subst=!h->tag->quoted; tag = h->tag->str; n = Creat(h->name); if(n<0) yyerror("can't create here document"); f = openfd(n); s = line; pprompt(); while((n = rutf(s, &r, runq->cmdfd))!=EOF){ if(r=='\n' || s>=&line[NLINE-UTFmax-1]){ if(r == '\n') s--; s[n]='\0'; if(tag && strcmp(line, tag)==0) break; if(subst) psubst(f, line); else pstr(f, line); s = line; if(r=='\n'){ pprompt(); pchr(f, r); } } else s += n; } flush(f); closeio(f); cleanhere(h->name); nexth = h->next; efree((char *)h); } here = 0; doprompt = 1;} voidpsubst(io *f, char *s){ int savec, n; char *t, *u; word *star; while(*s){ if(*s!='$') pchr(f, *s++); /* we've already got good runes */ else{ t=++s; if(*t=='$') pchr(f, *t++); else{ while(*t && idchr(*t)) t++; savec=*t; *t='\0'; n = 0; for(u = s;*u && '0'<=*u && *u<='9';u++) n = n*10+*u-'0'; if(n && *u=='\0'){ star = vlook("*")->val; if(star && 1<=n && n<=count(star)){ while(--n) star = star->next; pstr(f, star->word); } } else pstrs(f, vlook((char *)s)->val); *t = savec; if(savec=='^') t++; } s = t; } }} voidpstrs(io *f, word *a){ if(a){ while(a->next && a->next->word){ pstr(f, a->word); pchr(f, ' '); a = a->next; } pstr(f, a->word); }}
#include "rc.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
struct here *here, **ehere;
int ser = 0;
char tmp[]="/tmp/here0000.0000";
char hex[]="0123456789abcdef";
void psubst(io*, char*);
void pstrs(io*, word*);
void
hexnum(char *p, int n)
{
*p++=hex[(n>>12)&0xF];
*p++=hex[(n>>8)&0xF];
*p++=hex[(n>>4)&0xF];
*p = hex[n&0xF];
}
tree*
heredoc(tree *tag)
{
struct here *h = new(struct here);
if(tag->type!=WORD)
yyerror("Bad here tag");
h->next = 0;
if(here)
*ehere = h;
else
here = h;
ehere=&h->next;
h->tag = tag;
hexnum(&tmp[9], getpid());
hexnum(&tmp[14], ser++);
h->name = strdup(tmp);
return token(tmp, WORD);
}
/*
* bug: lines longer than NLINE get split -- this can cause spurious
* missubstitution, or a misrecognized EOF marker.
*/
#define NLINE 4096
void
readhere(void)
{
struct here *h, *nexth;
io *f;
char *s, *tag;
int n, subst;
char line[NLINE+1];
Rune r;
for(h = here;h;h = nexth){
subst=!h->tag->quoted;
tag = h->tag->str;
n = Creat(h->name);
if(n<0)
yyerror("can't create here document");
f = openfd(n);
s = line;
pprompt();
while((n = rutf(s, &r, runq->cmdfd))!=EOF){
if(r=='\n' || s>=&line[NLINE-UTFmax-1]){
if(r == '\n')
s--;
s[n]='\0';
if(tag && strcmp(line, tag)==0) break;
if(subst)
psubst(f, line);
else
pstr(f, line);
s = line;
if(r=='\n'){
pprompt();
pchr(f, r);
}
}
else s += n;
}
flush(f);
closeio(f);
cleanhere(h->name);
nexth = h->next;
efree((char *)h);
}
here = 0;
doprompt = 1;
}
void
psubst(io *f, char *s)
{
int savec, n;
char *t, *u;
word *star;
while(*s){
if(*s!='$')
pchr(f, *s++); /* we've already got good runes */
else{
t=++s;
if(*t=='$')
pchr(f, *t++);
else{
while(*t && idchr(*t)) t++;
savec=*t;
*t='\0';
n = 0;
for(u = s;*u && '0'<=*u && *u<='9';u++) n = n*10+*u-'0';
if(n && *u=='\0'){
star = vlook("*")->val;
if(star && 1<=n && n<=count(star)){
while(--n) star = star->next;
pstr(f, star->word);
}
}
else
pstrs(f, vlook((char *)s)->val);
*t = savec;
if(savec=='^')
t++;
}
s = t;
}
}
}
void
pstrs(io *f, word *a)
{
if(a){
while(a->next && a->next->word){
pstr(f, a->word);
pchr(f, ' ');
a = a->next;
}
pstr(f, a->word);
}
}