aboutsummaryrefslogtreecommitdiff
path: root/sys/cmd/rc/here.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cmd/rc/here.c')
-rw-r--r--sys/cmd/rc/here.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/sys/cmd/rc/here.c b/sys/cmd/rc/here.c
new file mode 100644
index 0000000..17c6245
--- /dev/null
+++ b/sys/cmd/rc/here.c
@@ -0,0 +1,150 @@
+#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 c, subst;
+ char line[NLINE+1];
+ for(h = here;h;h = nexth){
+ subst=!h->tag->quoted;
+ tag = h->tag->str;
+ c = Creat(h->name);
+ if(c<0)
+ yyerror("can't create here document");
+ f = openfd(c);
+ s = line;
+ pprompt();
+ while((c = rchr(runq->cmdfd))!=EOF){
+ if(c=='\n' || s==&line[NLINE]){
+ *s='\0';
+ if(tag && strcmp(line, tag)==0) break;
+ if(subst)
+ psubst(f, line);
+ else pstr(f, line);
+ s = line;
+ if(c=='\n'){
+ pprompt();
+ pchr(f, c);
+ }
+ else *s++=c;
+ }
+ else *s++=c;
+ }
+ flush(f);
+ closeio(f);
+ cleanhere(h->name);
+ nexth = h->next;
+ efree((char *)h);
+ }
+ here = 0;
+ doprompt = 1;
+}
+
+void
+psubst(io *f, char *s)
+{
+ char *t, *u;
+ int savec, n;
+ word *star;
+ while(*s){
+ if(*s!='$'){
+ if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){
+ pchr(f, *s++);
+ if(*s=='\0')
+ break;
+ }
+ else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){
+ pchr(f, *s++);
+ if(*s=='\0')
+ break;
+ pchr(f, *s++);
+ if(*s=='\0')
+ break;
+ }
+ pchr(f, *s++);
+ }
+ 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(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);
+ }
+}