jehanne/sys/src/cmd/rc/here.c

177 lines
3.2 KiB
C

/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
/* Portions of this file are Copyright (C) 9front's team.
* See /doc/license/9front-mit for details about the licensing.
* See http://git.9front.org/plan9front/plan9front/HEAD/info.html for a list of authors.
*/
#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*, uint8_t*);
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, (uint8_t *)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, uint8_t *s)
{
int savec, n;
uint8_t *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(ENV_RCARGLIST)->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);
}
}