Blame


1 f08fdedc 2003-11-23 devnull #include "rc.h"
2 f08fdedc 2003-11-23 devnull #include "exec.h"
3 f08fdedc 2003-11-23 devnull #include "io.h"
4 f08fdedc 2003-11-23 devnull #include "getflags.h"
5 f08fdedc 2003-11-23 devnull #include "fns.h"
6 f08fdedc 2003-11-23 devnull int getnext(void);
7 c8f53842 2007-03-26 devnull
8 c8f53842 2007-03-26 devnull int
9 c8f53842 2007-03-26 devnull wordchr(int c)
10 f08fdedc 2003-11-23 devnull {
11 f08fdedc 2003-11-23 devnull return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
12 f08fdedc 2003-11-23 devnull }
13 c8f53842 2007-03-26 devnull
14 c8f53842 2007-03-26 devnull int
15 c8f53842 2007-03-26 devnull idchr(int c)
16 f08fdedc 2003-11-23 devnull {
17 f08fdedc 2003-11-23 devnull /*
18 f08fdedc 2003-11-23 devnull * Formerly:
19 f08fdedc 2003-11-23 devnull * return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'
20 f08fdedc 2003-11-23 devnull * || c=='_' || c=='*';
21 f08fdedc 2003-11-23 devnull */
22 f08fdedc 2003-11-23 devnull return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
23 f08fdedc 2003-11-23 devnull }
24 c8f53842 2007-03-26 devnull int future = EOF;
25 c8f53842 2007-03-26 devnull int doprompt = 1;
26 f08fdedc 2003-11-23 devnull int inquote;
27 c8f53842 2007-03-26 devnull int incomm;
28 f08fdedc 2003-11-23 devnull /*
29 f08fdedc 2003-11-23 devnull * Look ahead in the input stream
30 f08fdedc 2003-11-23 devnull */
31 c8f53842 2007-03-26 devnull
32 c8f53842 2007-03-26 devnull int
33 c8f53842 2007-03-26 devnull nextc(void)
34 c8f53842 2007-03-26 devnull {
35 c8f53842 2007-03-26 devnull if(future==EOF)
36 c8f53842 2007-03-26 devnull future = getnext();
37 f08fdedc 2003-11-23 devnull return future;
38 f08fdedc 2003-11-23 devnull }
39 f08fdedc 2003-11-23 devnull /*
40 f08fdedc 2003-11-23 devnull * Consume the lookahead character.
41 f08fdedc 2003-11-23 devnull */
42 c8f53842 2007-03-26 devnull
43 c8f53842 2007-03-26 devnull int
44 c8f53842 2007-03-26 devnull advance(void)
45 c8f53842 2007-03-26 devnull {
46 c8f53842 2007-03-26 devnull int c = nextc();
47 c8f53842 2007-03-26 devnull lastc = future;
48 c8f53842 2007-03-26 devnull future = EOF;
49 f08fdedc 2003-11-23 devnull return c;
50 f08fdedc 2003-11-23 devnull }
51 f08fdedc 2003-11-23 devnull /*
52 f08fdedc 2003-11-23 devnull * read a character from the input stream
53 f08fdedc 2003-11-23 devnull */
54 c8f53842 2007-03-26 devnull
55 c8f53842 2007-03-26 devnull int
56 c8f53842 2007-03-26 devnull getnext(void)
57 c8f53842 2007-03-26 devnull {
58 c8f53842 2007-03-26 devnull int c;
59 c8f53842 2007-03-26 devnull static int peekc = EOF;
60 f08fdedc 2003-11-23 devnull if(peekc!=EOF){
61 c8f53842 2007-03-26 devnull c = peekc;
62 c8f53842 2007-03-26 devnull peekc = EOF;
63 f08fdedc 2003-11-23 devnull return c;
64 f08fdedc 2003-11-23 devnull }
65 c8f53842 2007-03-26 devnull if(runq->eof)
66 c8f53842 2007-03-26 devnull return EOF;
67 c8f53842 2007-03-26 devnull if(doprompt)
68 c8f53842 2007-03-26 devnull pprompt();
69 c8f53842 2007-03-26 devnull c = rchr(runq->cmdfd);
70 f08fdedc 2003-11-23 devnull if(!inquote && c=='\\'){
71 c8f53842 2007-03-26 devnull c = rchr(runq->cmdfd);
72 c8f53842 2007-03-26 devnull if(c=='\n' && !incomm){ /* don't continue a comment */
73 c8f53842 2007-03-26 devnull doprompt = 1;
74 f08fdedc 2003-11-23 devnull c=' ';
75 f08fdedc 2003-11-23 devnull }
76 f08fdedc 2003-11-23 devnull else{
77 c8f53842 2007-03-26 devnull peekc = c;
78 f08fdedc 2003-11-23 devnull c='\\';
79 f08fdedc 2003-11-23 devnull }
80 f08fdedc 2003-11-23 devnull }
81 c8f53842 2007-03-26 devnull doprompt = doprompt || c=='\n' || c==EOF;
82 c8f53842 2007-03-26 devnull if(c==EOF)
83 c8f53842 2007-03-26 devnull runq->eof++;
84 f08fdedc 2003-11-23 devnull else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
85 f08fdedc 2003-11-23 devnull return c;
86 f08fdedc 2003-11-23 devnull }
87 c8f53842 2007-03-26 devnull
88 c8f53842 2007-03-26 devnull void
89 c8f53842 2007-03-26 devnull pprompt(void)
90 c8f53842 2007-03-26 devnull {
91 f08fdedc 2003-11-23 devnull var *prompt;
92 f08fdedc 2003-11-23 devnull if(runq->iflag){
93 f08fdedc 2003-11-23 devnull pstr(err, promptstr);
94 f08fdedc 2003-11-23 devnull flush(err);
95 c8f53842 2007-03-26 devnull prompt = vlook("prompt");
96 f08fdedc 2003-11-23 devnull if(prompt->val && prompt->val->next)
97 c8f53842 2007-03-26 devnull promptstr = prompt->val->next->word;
98 f08fdedc 2003-11-23 devnull else
99 f08fdedc 2003-11-23 devnull promptstr="\t";
100 f08fdedc 2003-11-23 devnull }
101 f08fdedc 2003-11-23 devnull runq->lineno++;
102 c8f53842 2007-03-26 devnull doprompt = 0;
103 f08fdedc 2003-11-23 devnull }
104 c8f53842 2007-03-26 devnull
105 c8f53842 2007-03-26 devnull void
106 c8f53842 2007-03-26 devnull skipwhite(void)
107 c8f53842 2007-03-26 devnull {
108 f08fdedc 2003-11-23 devnull int c;
109 f08fdedc 2003-11-23 devnull for(;;){
110 c8f53842 2007-03-26 devnull c = nextc();
111 c8f53842 2007-03-26 devnull /* Why did this used to be if(!inquote && c=='#') ?? */
112 c8f53842 2007-03-26 devnull if(c=='#'){
113 c8f53842 2007-03-26 devnull incomm = 1;
114 f08fdedc 2003-11-23 devnull for(;;){
115 c8f53842 2007-03-26 devnull c = nextc();
116 c8f53842 2007-03-26 devnull if(c=='\n' || c==EOF) {
117 c8f53842 2007-03-26 devnull incomm = 0;
118 c8f53842 2007-03-26 devnull break;
119 c8f53842 2007-03-26 devnull }
120 f08fdedc 2003-11-23 devnull advance();
121 f08fdedc 2003-11-23 devnull }
122 f08fdedc 2003-11-23 devnull }
123 c8f53842 2007-03-26 devnull if(c==' ' || c=='\t')
124 c8f53842 2007-03-26 devnull advance();
125 f08fdedc 2003-11-23 devnull else return;
126 f08fdedc 2003-11-23 devnull }
127 f08fdedc 2003-11-23 devnull }
128 c8f53842 2007-03-26 devnull
129 c8f53842 2007-03-26 devnull void
130 c8f53842 2007-03-26 devnull skipnl(void)
131 c8f53842 2007-03-26 devnull {
132 c8f53842 2007-03-26 devnull int c;
133 f08fdedc 2003-11-23 devnull for(;;){
134 f08fdedc 2003-11-23 devnull skipwhite();
135 c8f53842 2007-03-26 devnull c = nextc();
136 c8f53842 2007-03-26 devnull if(c!='\n')
137 c8f53842 2007-03-26 devnull return;
138 f08fdedc 2003-11-23 devnull advance();
139 f08fdedc 2003-11-23 devnull }
140 f08fdedc 2003-11-23 devnull }
141 c8f53842 2007-03-26 devnull
142 c8f53842 2007-03-26 devnull int
143 c8f53842 2007-03-26 devnull nextis(int c)
144 c8f53842 2007-03-26 devnull {
145 f08fdedc 2003-11-23 devnull if(nextc()==c){
146 f08fdedc 2003-11-23 devnull advance();
147 f08fdedc 2003-11-23 devnull return 1;
148 f08fdedc 2003-11-23 devnull }
149 f08fdedc 2003-11-23 devnull return 0;
150 f08fdedc 2003-11-23 devnull }
151 c8f53842 2007-03-26 devnull
152 c8f53842 2007-03-26 devnull char*
153 c8f53842 2007-03-26 devnull addtok(char *p, int val)
154 c8f53842 2007-03-26 devnull {
155 c8f53842 2007-03-26 devnull if(p==0)
156 c8f53842 2007-03-26 devnull return 0;
157 17157e4a 2006-03-20 devnull if(p==&tok[NTOK-1]){
158 c8f53842 2007-03-26 devnull *p = 0;
159 f08fdedc 2003-11-23 devnull yyerror("token buffer too short");
160 f08fdedc 2003-11-23 devnull return 0;
161 f08fdedc 2003-11-23 devnull }
162 f08fdedc 2003-11-23 devnull *p++=val;
163 f08fdedc 2003-11-23 devnull return p;
164 f08fdedc 2003-11-23 devnull }
165 c8f53842 2007-03-26 devnull
166 c8f53842 2007-03-26 devnull char*
167 c8f53842 2007-03-26 devnull addutf(char *p, int c)
168 c8f53842 2007-03-26 devnull {
169 c8f53842 2007-03-26 devnull p = addtok(p, c);
170 f08fdedc 2003-11-23 devnull if(twobyte(c)) /* 2-byte escape */
171 f08fdedc 2003-11-23 devnull return addtok(p, advance());
172 f08fdedc 2003-11-23 devnull if(threebyte(c)){ /* 3-byte escape */
173 c8f53842 2007-03-26 devnull p = addtok(p, advance());
174 f08fdedc 2003-11-23 devnull return addtok(p, advance());
175 f08fdedc 2003-11-23 devnull }
176 f08fdedc 2003-11-23 devnull return p;
177 f08fdedc 2003-11-23 devnull }
178 f08fdedc 2003-11-23 devnull int lastdol; /* was the last token read '$' or '$#' or '"'? */
179 f08fdedc 2003-11-23 devnull int lastword; /* was the last token read a word or compound word terminator? */
180 c8f53842 2007-03-26 devnull
181 c8f53842 2007-03-26 devnull int
182 c8f53842 2007-03-26 devnull yylex(void)
183 c8f53842 2007-03-26 devnull {
184 c8f53842 2007-03-26 devnull int c, d = nextc();
185 c8f53842 2007-03-26 devnull char *w = tok;
186 c8f53842 2007-03-26 devnull struct tree *t;
187 c8f53842 2007-03-26 devnull yylval.tree = 0;
188 f08fdedc 2003-11-23 devnull /*
189 f08fdedc 2003-11-23 devnull * Embarassing sneakiness: if the last token read was a quoted or unquoted
190 f08fdedc 2003-11-23 devnull * WORD then we alter the meaning of what follows. If the next character
191 f08fdedc 2003-11-23 devnull * is `(', we return SUB (a subscript paren) and consume the `('. Otherwise,
192 f08fdedc 2003-11-23 devnull * if the next character is the first character of a simple or compound word,
193 f08fdedc 2003-11-23 devnull * we insert a `^' before it.
194 f08fdedc 2003-11-23 devnull */
195 f08fdedc 2003-11-23 devnull if(lastword){
196 c8f53842 2007-03-26 devnull lastword = 0;
197 f08fdedc 2003-11-23 devnull if(d=='('){
198 f08fdedc 2003-11-23 devnull advance();
199 f08fdedc 2003-11-23 devnull strcpy(tok, "( [SUB]");
200 f08fdedc 2003-11-23 devnull return SUB;
201 f08fdedc 2003-11-23 devnull }
202 f08fdedc 2003-11-23 devnull if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
203 f08fdedc 2003-11-23 devnull strcpy(tok, "^");
204 f08fdedc 2003-11-23 devnull return '^';
205 f08fdedc 2003-11-23 devnull }
206 f08fdedc 2003-11-23 devnull }
207 c8f53842 2007-03-26 devnull inquote = 0;
208 f08fdedc 2003-11-23 devnull skipwhite();
209 c8f53842 2007-03-26 devnull switch(c = advance()){
210 f08fdedc 2003-11-23 devnull case EOF:
211 c8f53842 2007-03-26 devnull lastdol = 0;
212 f08fdedc 2003-11-23 devnull strcpy(tok, "EOF");
213 f08fdedc 2003-11-23 devnull return EOF;
214 f08fdedc 2003-11-23 devnull case '$':
215 c8f53842 2007-03-26 devnull lastdol = 1;
216 f08fdedc 2003-11-23 devnull if(nextis('#')){
217 f08fdedc 2003-11-23 devnull strcpy(tok, "$#");
218 f08fdedc 2003-11-23 devnull return COUNT;
219 f08fdedc 2003-11-23 devnull }
220 f08fdedc 2003-11-23 devnull if(nextis('"')){
221 f08fdedc 2003-11-23 devnull strcpy(tok, "$\"");
222 f08fdedc 2003-11-23 devnull return '"';
223 f08fdedc 2003-11-23 devnull }
224 f08fdedc 2003-11-23 devnull strcpy(tok, "$");
225 f08fdedc 2003-11-23 devnull return '$';
226 f08fdedc 2003-11-23 devnull case '&':
227 c8f53842 2007-03-26 devnull lastdol = 0;
228 f08fdedc 2003-11-23 devnull if(nextis('&')){
229 f08fdedc 2003-11-23 devnull skipnl();
230 f08fdedc 2003-11-23 devnull strcpy(tok, "&&");
231 f08fdedc 2003-11-23 devnull return ANDAND;
232 f08fdedc 2003-11-23 devnull }
233 f08fdedc 2003-11-23 devnull strcpy(tok, "&");
234 f08fdedc 2003-11-23 devnull return '&';
235 f08fdedc 2003-11-23 devnull case '|':
236 c8f53842 2007-03-26 devnull lastdol = 0;
237 f08fdedc 2003-11-23 devnull if(nextis(c)){
238 f08fdedc 2003-11-23 devnull skipnl();
239 f08fdedc 2003-11-23 devnull strcpy(tok, "||");
240 f08fdedc 2003-11-23 devnull return OROR;
241 f08fdedc 2003-11-23 devnull }
242 f08fdedc 2003-11-23 devnull case '<':
243 f08fdedc 2003-11-23 devnull case '>':
244 c8f53842 2007-03-26 devnull lastdol = 0;
245 f08fdedc 2003-11-23 devnull /*
246 f08fdedc 2003-11-23 devnull * funny redirection tokens:
247 f08fdedc 2003-11-23 devnull * redir: arrow | arrow '[' fd ']'
248 f08fdedc 2003-11-23 devnull * arrow: '<' | '<<' | '>' | '>>' | '|'
249 f08fdedc 2003-11-23 devnull * fd: digit | digit '=' | digit '=' digit
250 f08fdedc 2003-11-23 devnull * digit: '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
251 f08fdedc 2003-11-23 devnull * some possibilities are nonsensical and get a message.
252 f08fdedc 2003-11-23 devnull */
253 f08fdedc 2003-11-23 devnull *w++=c;
254 c8f53842 2007-03-26 devnull t = newtree();
255 f08fdedc 2003-11-23 devnull switch(c){
256 f08fdedc 2003-11-23 devnull case '|':
257 c8f53842 2007-03-26 devnull t->type = PIPE;
258 c8f53842 2007-03-26 devnull t->fd0 = 1;
259 c8f53842 2007-03-26 devnull t->fd1 = 0;
260 f08fdedc 2003-11-23 devnull break;
261 f08fdedc 2003-11-23 devnull case '>':
262 c8f53842 2007-03-26 devnull t->type = REDIR;
263 f08fdedc 2003-11-23 devnull if(nextis(c)){
264 c8f53842 2007-03-26 devnull t->rtype = APPEND;
265 f08fdedc 2003-11-23 devnull *w++=c;
266 f08fdedc 2003-11-23 devnull }
267 c8f53842 2007-03-26 devnull else t->rtype = WRITE;
268 c8f53842 2007-03-26 devnull t->fd0 = 1;
269 f08fdedc 2003-11-23 devnull break;
270 f08fdedc 2003-11-23 devnull case '<':
271 c8f53842 2007-03-26 devnull t->type = REDIR;
272 f08fdedc 2003-11-23 devnull if(nextis(c)){
273 c8f53842 2007-03-26 devnull t->rtype = HERE;
274 f08fdedc 2003-11-23 devnull *w++=c;
275 c8f53842 2007-03-26 devnull } else if (nextis('>')){
276 c8f53842 2007-03-26 devnull t->rtype = RDWR;
277 c8f53842 2007-03-26 devnull *w++=c;
278 c8f53842 2007-03-26 devnull } else t->rtype = READ;
279 c8f53842 2007-03-26 devnull t->fd0 = 0;
280 f08fdedc 2003-11-23 devnull break;
281 f08fdedc 2003-11-23 devnull }
282 f08fdedc 2003-11-23 devnull if(nextis('[')){
283 f08fdedc 2003-11-23 devnull *w++='[';
284 c8f53842 2007-03-26 devnull c = advance();
285 c8f53842 2007-03-26 devnull *w++=c;
286 f08fdedc 2003-11-23 devnull if(c<'0' || '9'<c){
287 f08fdedc 2003-11-23 devnull RedirErr:
288 c8f53842 2007-03-26 devnull *w = 0;
289 f08fdedc 2003-11-23 devnull yyerror(t->type==PIPE?"pipe syntax"
290 f08fdedc 2003-11-23 devnull :"redirection syntax");
291 f08fdedc 2003-11-23 devnull return EOF;
292 f08fdedc 2003-11-23 devnull }
293 c8f53842 2007-03-26 devnull t->fd0 = 0;
294 f08fdedc 2003-11-23 devnull do{
295 c8f53842 2007-03-26 devnull t->fd0 = t->fd0*10+c-'0';
296 f08fdedc 2003-11-23 devnull *w++=c;
297 c8f53842 2007-03-26 devnull c = advance();
298 f08fdedc 2003-11-23 devnull }while('0'<=c && c<='9');
299 f08fdedc 2003-11-23 devnull if(c=='='){
300 f08fdedc 2003-11-23 devnull *w++='=';
301 c8f53842 2007-03-26 devnull if(t->type==REDIR)
302 c8f53842 2007-03-26 devnull t->type = DUP;
303 c8f53842 2007-03-26 devnull c = advance();
304 f08fdedc 2003-11-23 devnull if('0'<=c && c<='9'){
305 c8f53842 2007-03-26 devnull t->rtype = DUPFD;
306 c8f53842 2007-03-26 devnull t->fd1 = t->fd0;
307 c8f53842 2007-03-26 devnull t->fd0 = 0;
308 f08fdedc 2003-11-23 devnull do{
309 c8f53842 2007-03-26 devnull t->fd0 = t->fd0*10+c-'0';
310 f08fdedc 2003-11-23 devnull *w++=c;
311 c8f53842 2007-03-26 devnull c = advance();
312 f08fdedc 2003-11-23 devnull }while('0'<=c && c<='9');
313 f08fdedc 2003-11-23 devnull }
314 f08fdedc 2003-11-23 devnull else{
315 c8f53842 2007-03-26 devnull if(t->type==PIPE)
316 c8f53842 2007-03-26 devnull goto RedirErr;
317 c8f53842 2007-03-26 devnull t->rtype = CLOSE;
318 f08fdedc 2003-11-23 devnull }
319 f08fdedc 2003-11-23 devnull }
320 f08fdedc 2003-11-23 devnull if(c!=']'
321 f08fdedc 2003-11-23 devnull || t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
322 f08fdedc 2003-11-23 devnull goto RedirErr;
323 f08fdedc 2003-11-23 devnull *w++=']';
324 f08fdedc 2003-11-23 devnull }
325 f08fdedc 2003-11-23 devnull *w='\0';
326 c8f53842 2007-03-26 devnull yylval.tree = t;
327 c8f53842 2007-03-26 devnull if(t->type==PIPE)
328 c8f53842 2007-03-26 devnull skipnl();
329 f08fdedc 2003-11-23 devnull return t->type;
330 f08fdedc 2003-11-23 devnull case '\'':
331 c8f53842 2007-03-26 devnull lastdol = 0;
332 c8f53842 2007-03-26 devnull lastword = 1;
333 c8f53842 2007-03-26 devnull inquote = 1;
334 f08fdedc 2003-11-23 devnull for(;;){
335 c8f53842 2007-03-26 devnull c = advance();
336 c8f53842 2007-03-26 devnull if(c==EOF)
337 c8f53842 2007-03-26 devnull break;
338 f08fdedc 2003-11-23 devnull if(c=='\''){
339 f08fdedc 2003-11-23 devnull if(nextc()!='\'')
340 f08fdedc 2003-11-23 devnull break;
341 f08fdedc 2003-11-23 devnull advance();
342 f08fdedc 2003-11-23 devnull }
343 c8f53842 2007-03-26 devnull w = addutf(w, c);
344 f08fdedc 2003-11-23 devnull }
345 c8f53842 2007-03-26 devnull if(w!=0)
346 c8f53842 2007-03-26 devnull *w='\0';
347 c8f53842 2007-03-26 devnull t = token(tok, WORD);
348 c8f53842 2007-03-26 devnull t->quoted = 1;
349 c8f53842 2007-03-26 devnull yylval.tree = t;
350 f08fdedc 2003-11-23 devnull return t->type;
351 f08fdedc 2003-11-23 devnull }
352 f08fdedc 2003-11-23 devnull if(!wordchr(c)){
353 c8f53842 2007-03-26 devnull lastdol = 0;
354 c8f53842 2007-03-26 devnull tok[0] = c;
355 f08fdedc 2003-11-23 devnull tok[1]='\0';
356 f08fdedc 2003-11-23 devnull return c;
357 f08fdedc 2003-11-23 devnull }
358 f08fdedc 2003-11-23 devnull for(;;){
359 f08fdedc 2003-11-23 devnull /* next line should have (char)c==GLOB, but ken's compiler is broken */
360 f08fdedc 2003-11-23 devnull if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB)
361 c8f53842 2007-03-26 devnull w = addtok(w, GLOB);
362 c8f53842 2007-03-26 devnull w = addutf(w, c);
363 c8f53842 2007-03-26 devnull c = nextc();
364 f08fdedc 2003-11-23 devnull if(lastdol?!idchr(c):!wordchr(c)) break;
365 f08fdedc 2003-11-23 devnull advance();
366 f08fdedc 2003-11-23 devnull }
367 f08fdedc 2003-11-23 devnull
368 c8f53842 2007-03-26 devnull lastword = 1;
369 c8f53842 2007-03-26 devnull lastdol = 0;
370 c8f53842 2007-03-26 devnull if(w!=0)
371 c8f53842 2007-03-26 devnull *w='\0';
372 c8f53842 2007-03-26 devnull t = klook(tok);
373 c8f53842 2007-03-26 devnull if(t->type!=WORD)
374 c8f53842 2007-03-26 devnull lastword = 0;
375 c8f53842 2007-03-26 devnull t->quoted = 0;
376 c8f53842 2007-03-26 devnull yylval.tree = t;
377 f08fdedc 2003-11-23 devnull return t->type;
378 f08fdedc 2003-11-23 devnull }