1 /* $OpenBSD: parse.c,v 1.15 2018/10/24 06:01:03 martijn Exp $ */
2 /* $NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd Exp $ */
3
4 /*-
5 * Copyright (c) 1980, 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/types.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <stdarg.h>
37
38 #include "csh.h"
39 #include "extern.h"
40
41 static void asyntax(struct wordent *, struct wordent *);
42 static void asyn0(struct wordent *, struct wordent *);
43 static void asyn3(struct wordent *, struct wordent *);
44 static struct wordent
45 *freenod(struct wordent *, struct wordent *);
46 static struct command
47 *syn0(struct wordent *, struct wordent *, int);
48 static struct command
49 *syn1(struct wordent *, struct wordent *, int);
50 static struct command
51 *syn1a(struct wordent *, struct wordent *, int);
52 static struct command
53 *syn1b(struct wordent *, struct wordent *, int);
54 static struct command
55 *syn2(struct wordent *, struct wordent *, int);
56 static struct command
57 *syn3(struct wordent *, struct wordent *, int);
58
59 #define ALEFT 21 /* max of 20 alias expansions */
60 #define HLEFT 11 /* max of 10 history expansions */
61 /*
62 * Perform aliasing on the word list lex
63 * Do a (very rudimentary) parse to separate into commands.
64 * If word 0 of a command has an alias, do it.
65 * Repeat a maximum of 20 times.
66 */
67 static int aleft;
68 extern int hleft;
69 void
alias(struct wordent * lex)70 alias(struct wordent *lex)
71 {
72 jmp_buf osetexit;
73
74 aleft = ALEFT;
75 hleft = HLEFT;
76 getexit(osetexit);
77 (void) setexit();
78 if (haderr) {
79 resexit(osetexit);
80 reset();
81 }
82 if (--aleft == 0)
83 stderror(ERR_ALIASLOOP);
84 asyntax(lex->next, lex);
85 resexit(osetexit);
86 }
87
88 static void
asyntax(struct wordent * p1,struct wordent * p2)89 asyntax(struct wordent *p1, struct wordent *p2)
90 {
91 while (p1 != p2)
92 if (any(";&\n", p1->word[0]))
93 p1 = p1->next;
94 else {
95 asyn0(p1, p2);
96 return;
97 }
98 }
99
100 static void
asyn0(struct wordent * p1,struct wordent * p2)101 asyn0(struct wordent *p1, struct wordent *p2)
102 {
103 struct wordent *p;
104 int l = 0;
105
106 for (p = p1; p != p2; p = p->next)
107 switch (p->word[0]) {
108
109 case '(':
110 l++;
111 continue;
112
113 case ')':
114 l--;
115 if (l < 0)
116 stderror(ERR_TOOMANYRP);
117 continue;
118
119 case '>':
120 if (p->next != p2 && eq(p->next->word, STRand))
121 p = p->next;
122 continue;
123
124 case '&':
125 case '|':
126 case ';':
127 case '\n':
128 if (l != 0)
129 continue;
130 asyn3(p1, p);
131 asyntax(p->next, p2);
132 return;
133 }
134 if (l == 0)
135 asyn3(p1, p2);
136 }
137
138 static void
asyn3(struct wordent * p1,struct wordent * p2)139 asyn3(struct wordent *p1, struct wordent *p2)
140 {
141 struct varent *ap;
142 struct wordent alout;
143 bool redid;
144
145 if (p1 == p2)
146 return;
147 if (p1->word[0] == '(') {
148 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
149 if (p2 == p1)
150 return;
151 if (p2 == p1->next)
152 return;
153 asyn0(p1->next, p2);
154 return;
155 }
156 ap = adrof1(p1->word, &aliases);
157 if (ap == 0)
158 return;
159 alhistp = p1->prev;
160 alhistt = p2;
161 alvec = ap->vec;
162 redid = lex(&alout);
163 alhistp = alhistt = 0;
164 alvec = 0;
165 if (seterr) {
166 freelex(&alout);
167 stderror(ERR_OLD);
168 }
169 if (p1->word[0] && eq(p1->word, alout.next->word)) {
170 Char *cp = alout.next->word;
171
172 alout.next->word = Strspl(STRQNULL, cp);
173 free(cp);
174 }
175 p1 = freenod(p1, redid ? p2 : p1->next);
176 if (alout.next != &alout) {
177 p1->next->prev = alout.prev->prev;
178 alout.prev->prev->next = p1->next;
179 alout.next->prev = p1;
180 p1->next = alout.next;
181 free(alout.prev->word);
182 free((alout.prev));
183 }
184 reset(); /* throw! */
185 }
186
187 static struct wordent *
freenod(struct wordent * p1,struct wordent * p2)188 freenod(struct wordent *p1, struct wordent *p2)
189 {
190 struct wordent *retp = p1->prev;
191
192 while (p1 != p2) {
193 free(p1->word);
194 p1 = p1->next;
195 free((p1->prev));
196 }
197 retp->next = p2;
198 p2->prev = retp;
199 return (retp);
200 }
201
202 #define PHERE 1
203 #define PIN 2
204 #define POUT 4
205 #define PERR 8
206
207 /*
208 * syntax
209 * empty
210 * syn0
211 */
212 struct command *
syntax(struct wordent * p1,struct wordent * p2,int flags)213 syntax(struct wordent *p1, struct wordent *p2, int flags)
214 {
215
216 while (p1 != p2)
217 if (any(";&\n", p1->word[0]))
218 p1 = p1->next;
219 else
220 return (syn0(p1, p2, flags));
221 return (0);
222 }
223
224 /*
225 * syn0
226 * syn1
227 * syn1 & syntax
228 */
229 static struct command *
syn0(struct wordent * p1,struct wordent * p2,int flags)230 syn0(struct wordent *p1, struct wordent *p2, int flags)
231 {
232 struct wordent *p;
233 struct command *t, *t1;
234 int l;
235
236 l = 0;
237 for (p = p1; p != p2; p = p->next)
238 switch (p->word[0]) {
239
240 case '(':
241 l++;
242 continue;
243
244 case ')':
245 l--;
246 if (l < 0)
247 seterror(ERR_TOOMANYRP);
248 continue;
249
250 case '|':
251 if (p->word[1] == '|')
252 continue;
253 /* fall into ... */
254
255 case '>':
256 if (p->next != p2 && eq(p->next->word, STRand))
257 p = p->next;
258 continue;
259
260 case '&':
261 if (l != 0)
262 break;
263 if (p->word[1] == '&')
264 continue;
265 t1 = syn1(p1, p, flags);
266 if (t1->t_dtyp == NODE_LIST ||
267 t1->t_dtyp == NODE_AND ||
268 t1->t_dtyp == NODE_OR) {
269 t = xcalloc(1, sizeof(*t));
270 t->t_dtyp = NODE_PAREN;
271 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
272 t->t_dspr = t1;
273 t1 = t;
274 }
275 else
276 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
277 t = xcalloc(1, sizeof(*t));
278 t->t_dtyp = NODE_LIST;
279 t->t_dflg = 0;
280 t->t_dcar = t1;
281 t->t_dcdr = syntax(p, p2, flags);
282 return (t);
283 }
284 if (l == 0)
285 return (syn1(p1, p2, flags));
286 seterror(ERR_TOOMANYLP);
287 return (0);
288 }
289
290 /*
291 * syn1
292 * syn1a
293 * syn1a ; syntax
294 */
295 static struct command *
syn1(struct wordent * p1,struct wordent * p2,int flags)296 syn1(struct wordent *p1, struct wordent *p2, int flags)
297 {
298 struct wordent *p;
299 struct command *t;
300 int l;
301
302 l = 0;
303 for (p = p1; p != p2; p = p->next)
304 switch (p->word[0]) {
305
306 case '(':
307 l++;
308 continue;
309
310 case ')':
311 l--;
312 continue;
313
314 case ';':
315 case '\n':
316 if (l != 0)
317 break;
318 t = xcalloc(1, sizeof(*t));
319 t->t_dtyp = NODE_LIST;
320 t->t_dcar = syn1a(p1, p, flags);
321 t->t_dcdr = syntax(p->next, p2, flags);
322 if (t->t_dcdr == 0)
323 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
324 return (t);
325 }
326 return (syn1a(p1, p2, flags));
327 }
328
329 /*
330 * syn1a
331 * syn1b
332 * syn1b || syn1a
333 */
334 static struct command *
syn1a(struct wordent * p1,struct wordent * p2,int flags)335 syn1a(struct wordent *p1, struct wordent *p2, int flags)
336 {
337 struct wordent *p;
338 struct command *t;
339 int l = 0;
340
341 for (p = p1; p != p2; p = p->next)
342 switch (p->word[0]) {
343
344 case '(':
345 l++;
346 continue;
347
348 case ')':
349 l--;
350 continue;
351
352 case '|':
353 if (p->word[1] != '|')
354 continue;
355 if (l == 0) {
356 t = xcalloc(1, sizeof(*t));
357 t->t_dtyp = NODE_OR;
358 t->t_dcar = syn1b(p1, p, flags);
359 t->t_dcdr = syn1a(p->next, p2, flags);
360 t->t_dflg = 0;
361 return (t);
362 }
363 continue;
364 }
365 return (syn1b(p1, p2, flags));
366 }
367
368 /*
369 * syn1b
370 * syn2
371 * syn2 && syn1b
372 */
373 static struct command *
syn1b(struct wordent * p1,struct wordent * p2,int flags)374 syn1b(struct wordent *p1, struct wordent *p2, int flags)
375 {
376 struct wordent *p;
377 struct command *t;
378 int l = 0;
379
380 for (p = p1; p != p2; p = p->next)
381 switch (p->word[0]) {
382
383 case '(':
384 l++;
385 continue;
386
387 case ')':
388 l--;
389 continue;
390
391 case '&':
392 if (p->word[1] == '&' && l == 0) {
393 t = xcalloc(1, sizeof(*t));
394 t->t_dtyp = NODE_AND;
395 t->t_dcar = syn2(p1, p, flags);
396 t->t_dcdr = syn1b(p->next, p2, flags);
397 t->t_dflg = 0;
398 return (t);
399 }
400 continue;
401 }
402 return (syn2(p1, p2, flags));
403 }
404
405 /*
406 * syn2
407 * syn3
408 * syn3 | syn2
409 * syn3 |& syn2
410 */
411 static struct command *
syn2(struct wordent * p1,struct wordent * p2,int flags)412 syn2(struct wordent *p1, struct wordent *p2, int flags)
413 {
414 struct wordent *p, *pn;
415 struct command *t;
416 int l = 0;
417 int f;
418
419 for (p = p1; p != p2; p = p->next)
420 switch (p->word[0]) {
421
422 case '(':
423 l++;
424 continue;
425
426 case ')':
427 l--;
428 continue;
429
430 case '|':
431 if (l != 0)
432 continue;
433 t = xcalloc(1, sizeof(*t));
434 f = flags | POUT;
435 pn = p->next;
436 if (pn != p2 && pn->word[0] == '&') {
437 f |= PERR;
438 t->t_dflg |= F_STDERR;
439 }
440 t->t_dtyp = NODE_PIPE;
441 t->t_dcar = syn3(p1, p, f);
442 if (pn != p2 && pn->word[0] == '&')
443 p = pn;
444 t->t_dcdr = syn2(p->next, p2, flags | PIN);
445 return (t);
446 }
447 return (syn3(p1, p2, flags));
448 }
449
450 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
451
452 /*
453 * syn3
454 * ( syn0 ) [ < in ] [ > out ]
455 * word word* [ < in ] [ > out ]
456 * KEYWORD ( word* ) word* [ < in ] [ > out ]
457 *
458 * KEYWORD = (@ exit foreach if set switch test while)
459 */
460 static struct command *
syn3(struct wordent * p1,struct wordent * p2,int flags)461 syn3(struct wordent *p1, struct wordent *p2, int flags)
462 {
463 struct wordent *p;
464 struct wordent *lp, *rp;
465 struct command *t;
466 int l;
467 Char **av;
468 int n, c;
469 bool specp = 0;
470
471 if (p1 != p2) {
472 p = p1;
473 again:
474 switch (srchx(p->word)) {
475
476 case T_ELSE:
477 p = p->next;
478 if (p != p2)
479 goto again;
480 break;
481
482 case T_EXIT:
483 case T_FOREACH:
484 case T_IF:
485 case T_LET:
486 case T_SET:
487 case T_SWITCH:
488 case T_WHILE:
489 specp = 1;
490 break;
491 }
492 }
493 n = 0;
494 l = 0;
495 for (p = p1; p != p2; p = p->next)
496 switch (p->word[0]) {
497
498 case '(':
499 if (specp)
500 n++;
501 l++;
502 continue;
503
504 case ')':
505 if (specp)
506 n++;
507 l--;
508 continue;
509
510 case '>':
511 case '<':
512 if (l != 0) {
513 if (specp)
514 n++;
515 continue;
516 }
517 if (p->next == p2)
518 continue;
519 if (any(RELPAR, p->next->word[0]))
520 continue;
521 n--;
522 continue;
523
524 default:
525 if (!specp && l != 0)
526 continue;
527 n++;
528 continue;
529 }
530 if (n < 0)
531 n = 0;
532 t = xcalloc(1, sizeof(*t));
533 av = xcalloc(n + 1, sizeof(*av));
534 t->t_dcom = av;
535 n = 0;
536 if (p2->word[0] == ')')
537 t->t_dflg = F_NOFORK;
538 lp = 0;
539 rp = 0;
540 l = 0;
541 for (p = p1; p != p2; p = p->next) {
542 c = p->word[0];
543 switch (c) {
544
545 case '(':
546 if (l == 0) {
547 if (lp != 0 && !specp)
548 seterror(ERR_BADPLP);
549 lp = p->next;
550 }
551 l++;
552 goto savep;
553
554 case ')':
555 l--;
556 if (l == 0)
557 rp = p;
558 goto savep;
559
560 case '>':
561 if (l != 0)
562 goto savep;
563 if (p->word[1] == '>')
564 t->t_dflg |= F_APPEND;
565 if (p->next != p2 && eq(p->next->word, STRand)) {
566 t->t_dflg |= F_STDERR, p = p->next;
567 if (flags & (POUT | PERR)) {
568 seterror(ERR_OUTRED);
569 continue;
570 }
571 }
572 if (p->next != p2 && eq(p->next->word, STRbang))
573 t->t_dflg |= F_OVERWRITE, p = p->next;
574 if (p->next == p2) {
575 seterror(ERR_MISRED);
576 continue;
577 }
578 p = p->next;
579 if (any(RELPAR, p->word[0])) {
580 seterror(ERR_MISRED);
581 continue;
582 }
583 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
584 seterror(ERR_OUTRED);
585 else
586 t->t_drit = Strsave(p->word);
587 continue;
588
589 case '<':
590 if (l != 0)
591 goto savep;
592 if (p->word[1] == '<')
593 t->t_dflg |= F_READ;
594 if (p->next == p2) {
595 seterror(ERR_MISRED);
596 continue;
597 }
598 p = p->next;
599 if (any(RELPAR, p->word[0])) {
600 seterror(ERR_MISRED);
601 continue;
602 }
603 if ((flags & PHERE) && (t->t_dflg & F_READ))
604 seterror(ERR_REDPAR);
605 else if ((flags & PIN) || t->t_dlef)
606 seterror(ERR_INRED);
607 else
608 t->t_dlef = Strsave(p->word);
609 continue;
610
611 savep:
612 if (!specp)
613 continue;
614 default:
615 if (l != 0 && !specp)
616 continue;
617 if (seterr == 0)
618 av[n] = Strsave(p->word);
619 n++;
620 continue;
621 }
622 }
623 if (lp != 0 && !specp) {
624 if (n != 0)
625 seterror(ERR_BADPLPS);
626 t->t_dtyp = NODE_PAREN;
627 t->t_dspr = syn0(lp, rp, PHERE);
628 }
629 else {
630 if (n == 0)
631 seterror(ERR_NULLCOM);
632 t->t_dtyp = NODE_COMMAND;
633 }
634 return (t);
635 }
636
637 void
freesyn(struct command * t)638 freesyn(struct command *t)
639 {
640 Char **v;
641
642 if (t == 0)
643 return;
644 switch (t->t_dtyp) {
645
646 case NODE_COMMAND:
647 for (v = t->t_dcom; *v; v++)
648 free(* v);
649 free((t->t_dcom));
650 free(t->t_dlef);
651 free(t->t_drit);
652 break;
653 case NODE_PAREN:
654 freesyn(t->t_dspr);
655 free(t->t_dlef);
656 free(t->t_drit);
657 break;
658
659 case NODE_AND:
660 case NODE_OR:
661 case NODE_PIPE:
662 case NODE_LIST:
663 freesyn(t->t_dcar), freesyn(t->t_dcdr);
664 break;
665 }
666 free(t);
667 }
668