shithub: riscv

ref: 855cf4326f5a07d7142c2d8918f5fa856d912b85
dir: /sys/src/cmd/rc/here.c/

View raw version
#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*, uchar*);
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;

	if(tag->type!=WORD){
		yyerror("Bad here tag");
		return nil;
	}
	h = new(struct here);
	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 = estrdup(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, (uchar *)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, uchar *s)
{
	int savec, n;
	uchar *t, *u;
	word *star;
	while(*s){
		if(*s!='$'){
			if(0xa0 <= *s && *s <= 0xf5){
				pchr(f, *s++);
				if(*s=='\0')
					break;
			}
			else if(0xf6 <= *s && *s <= 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((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);
	}
}