xref: /inferno-os/utils/rcsh/here.c (revision b43c1ca5eb5fc65b93ae935a568432712797b049)
1 #include "rc.h"
2 #include "y.tab.h"
3 
4 Here	*here, **ehere;
5 int	ser;
6 
7 char	tmp[]="/tmp/here0000.0000";
8 char	hex[]="0123456789abcdef";
9 
10 void psubst(Io*, char*);
11 void pstrs(Io*, Word*);
12 
13 void hexnum(char *p, int n)
14 {
15 	*p++=hex[(n>>12)&0xF];
16 	*p++=hex[(n>>8)&0xF];
17 	*p++=hex[(n>>4)&0xF];
18 	*p=hex[n&0xF];
19 }
20 
21 Tree *
22 heredoc(Tree *tag)
23 {
24 	Here *h=new(Here);
25 
26 	if(tag->type!=WORD)
27 		yyerror("Bad here tag");
28 	h->next=0;
29 	if(here)
30 		*ehere=h;
31 	else
32 		here=h;
33 	ehere=&h->next;
34 	h->tag=tag;
35 	hexnum(&tmp[9], getpid());
36 	hexnum(&tmp[14], ser++);
37 	h->name=strdup(tmp);
38 	return token(tmp, WORD);
39 }
40 /*
41  * bug: lines longer than NLINE get split -- this can cause spurious
42  * missubstitution, or a misrecognized EOF marker.
43  */
44 #define	NLINE	4096
45 void
46 readhere(void)
47 {
48 	Here *h, *nexth;
49 	Io *f;
50 	char *s, *tag;
51 	int c, subst;
52 	char line[NLINE+1];
53 
54 	for(h=here;h;h=nexth){
55 		subst=!h->tag->quoted;
56 		tag=h->tag->str;
57 		c=create(h->name, 1, 0666);
58 		if(c<0) yyerror("can't create here document");
59 		f=openfd(c);
60 		s=line;
61 		pprompt();
62 		while((c=rchr(runq->cmdfd))!=EOF){
63 			if(c=='\n' || s==&line[NLINE]){
64 				*s='\0';
65 				if(strcmp(line, tag)==0) break;
66 				if(subst) psubst(f, line);
67 				else pstr(f, line);
68 				s=line;
69 				if(c=='\n'){
70 					pprompt();
71 					pchr(f, c);
72 				}
73 				else *s++=c;
74 			}
75 			else *s++=c;
76 		}
77 		flush(f);
78 		closeio(f);
79 		cleanhere(h->name);
80 		nexth=h->next;
81 		free(h);
82 	}
83 	here=0;
84 	doprompt=1;
85 }
86 
87 void
88 psubst(Io *f, char *s)
89 {
90 	char *t, *u;
91 	int savec, n;
92 	Word *star;
93 
94 	while(*s){
95 		if(*s!='$'){
96 			if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){
97 				pchr(f, *s++);
98 				if(*s=='\0') break;
99 			}
100 			else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){
101 				pchr(f, *s++);
102 				if(*s=='\0') break;
103 				pchr(f, *s++);
104 				if(*s=='\0') break;
105 			}
106 			pchr(f, *s++);
107 		}
108 		else{
109 			t=++s;
110 			if(*t=='$') pchr(f, *t++);
111 			else{
112 				while(*t && idchr(*t)) t++;
113 				savec=*t;
114 				*t='\0';
115 				n=0;
116 				for(u=s;*u && '0'<=*u && *u<='9';u++) n=n*10+*u-'0';
117 				if(n && *u=='\0'){
118 					star=vlook("*")->val;
119 					if(star && 1<=n && n<=count(star)){
120 						while(--n) star=star->next;
121 						pstr(f, star->word);
122 					}
123 				}
124 				else
125 					pstrs(f, vlook(s)->val);
126 				*t=savec;
127 				if(savec=='^') t++;
128 			}
129 			s=t;
130 		}
131 	}
132 }
133 
134 void
135 pstrs(Io *f, Word *a)
136 {
137 	if(a){
138 		while(a->next && a->next->word){
139 			pstr(f, a->word);
140 			pchr(f, ' ');
141 			a=a->next;
142 		}
143 		pstr(f, a->word);
144 	}
145 }
146