summaryrefslogtreecommitdiff
path: root/utils/rcsh/here.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /utils/rcsh/here.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'utils/rcsh/here.c')
-rw-r--r--utils/rcsh/here.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/utils/rcsh/here.c b/utils/rcsh/here.c
new file mode 100644
index 00000000..bd1f79cc
--- /dev/null
+++ b/utils/rcsh/here.c
@@ -0,0 +1,145 @@
+#include "rc.h"
+#include "y.tab.h"
+
+Here *here, **ehere;
+int ser;
+
+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)
+{
+ Here *h=new(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)
+{
+ 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=create(h->name, 1, 0666);
+ 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(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;
+ free(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);
+ }
+}