BSD 3 development
[unix-history] / usr / src / cmd / csh / sh.parse.c
CommitLineData
8d4b421d
BJ
1/* Copyright (c) 1979 Regents of the University of California */
2#include "sh.h"
3
4/*
5 * C shell
6 */
7
8/*
9 * Perform aliasing on the word list lex
10 * Do a (very rudimentary) parse to separate into commands.
11 * If word 0 of a command has an alias, do it.
12 * Repeat a maximum of 20 times.
13 */
14alias(lex)
15 register struct wordent *lex;
16{
17 int aleft = 21;
18 jmp_buf osetexit;
19
20 getexit(osetexit);
21 setexit();
22 if (haderr) {
23 resexit(osetexit);
24 reset();
25 }
26 if (--aleft == 0)
27 error("Alias loop");
28 asyntax(lex->next, lex);
29 resexit(osetexit);
30}
31
32asyntax(p1, p2)
33 register struct wordent *p1, *p2;
34{
35
36 while (p1 != p2)
37 if (any(p1->word[0], ";&\n"))
38 p1 = p1->next;
39 else {
40 asyn0(p1, p2);
41 return;
42 }
43}
44
45asyn0(p1, p2)
46 struct wordent *p1;
47 register struct wordent *p2;
48{
49 register struct wordent *p;
50 register int l = 0;
51
52 for (p = p1; p != p2; p = p->next)
53 switch (p->word[0]) {
54
55 case '(':
56 l++;
57 continue;
58
59 case ')':
60 l--;
61 if (l < 0)
62 error("Too many )'s");
63 continue;
64
65 case '>':
66 if (p->next != p2 && eq(p->next->word, "&"))
67 p = p->next;
68 continue;
69
70 case '&':
71 case '|':
72 case ';':
73 case '\n':
74 if (l != 0)
75 continue;
76 asyn3(p1, p);
77 asyntax(p->next, p2);
78 return;
79 }
80 if (l == 0)
81 asyn3(p1, p2);
82}
83
84asyn3(p1, p2)
85 struct wordent *p1;
86 register struct wordent *p2;
87{
88 register struct varent *ap;
89 struct wordent alout;
90 register bool redid;
91
92 if (p1 == p2)
93 return;
94 if (p1->word[0] == '(') {
95 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
96 if (p2 == p1)
97 return;
98 if (p2 == p1->next)
99 return;
100 asyn0(p1->next, p2);
101 return;
102 }
103 ap = adrof1(p1->word, &aliases);
104 if (ap == 0)
105 return;
106 alhistp = p1->prev;
107 alhistt = p2;
108 alvec = ap->vec;
109 redid = lex(&alout);
110 alhistp = alhistt = 0;
111 alvec = 0;
112 if (err) {
113 freelex(&alout);
114 error(err);
115 }
116 if (p1->word[0] && eq(p1->word, alout.next->word)) {
117 char *cp = alout.next->word;
118
119 alout.next->word = strspl("\200", cp);
120 xfree(cp);
121 }
122 p1 = freenod(p1, redid ? p2 : p1->next);
123 if (alout.next != &alout) {
124 p1->next->prev = alout.prev->prev;
125 alout.prev->prev->next = p1->next;
126 alout.next->prev = p1;
127 p1->next = alout.next;
128 xfree(alout.prev->word);
129 xfree(alout.prev);
130 }
131 reset(); /* throw! */
132}
133
134struct wordent *
135freenod(p1, p2)
136 register struct wordent *p1, *p2;
137{
138 register struct wordent *retp = p1->prev;
139
140 while (p1 != p2) {
141 xfree(p1->word);
142 p1 = p1->next;
143 xfree(p1->prev);
144 }
145 retp->next = p2;
146 p2->prev = retp;
147 return (retp);
148}
149
150#define PHERE 1
151#define PIN 2
152#define POUT 4
153#define PDIAG 8
154
155/*
156 * syntax
157 * empty
158 * syn0
159 */
160struct command *
161syntax(p1, p2, flags)
162 register struct wordent *p1, *p2;
163 int flags;
164{
165
166 while (p1 != p2)
167 if (any(p1->word[0], ";&\n"))
168 p1 = p1->next;
169 else
170 return (syn0(p1, p2, flags));
171 return (0);
172}
173
174/*
175 * syn0
176 * syn1
177 * syn1 & syntax
178 */
179struct command *
180syn0(p1, p2, flags)
181 struct wordent *p1, *p2;
182 int flags;
183{
184 register struct wordent *p;
185 register struct command *t, *t1;
186 int l;
187
188 l = 0;
189 for (p = p1; p != p2; p = p->next)
190 switch (p->word[0]) {
191
192 case '(':
193 l++;
194 continue;
195
196 case ')':
197 l--;
198 if (l < 0)
199 seterr("Too many )'s");
200 continue;
201
202 case '|':
203 if (p->word[1] == '|')
204 continue;
205 /* fall into ... */
206
207 case '>':
208 if (p->next != p2 && eq(p->next->word, "&"))
209 p = p->next;
210 continue;
211
212 case '&':
213 if (l != 0)
214 break;
215 if (p->word[1] == '&')
216 continue;
217 t1 = syn1(p1, p, flags);
218 if (t1->t_dtyp == TLST) {
219 t = (struct command *) calloc(1, sizeof (*t));
220 t->t_dtyp = TPAR;
221 t->t_dflg = FAND|FPRS|FINT;
222 t->t_dspr = t1;
223 t1 = t;
224 } else
225 t1->t_dflg |= FAND|FPRS|FINT;
226 t = (struct command *) calloc(1, sizeof (*t));
227 t->t_dtyp = TLST;
228 t->t_dflg = 0;
229 t->t_dcar = t1;
230 t->t_dcdr = syntax(p, p2, flags);
231 return(t);
232 }
233 if (l == 0)
234 return (syn1(p1, p2, flags));
235 seterr("Too many ('s");
236 return (0);
237}
238
239/*
240 * syn1
241 * syn1a
242 * syn1a ; syntax
243 */
244struct command *
245syn1(p1, p2, flags)
246 struct wordent *p1, *p2;
247 int flags;
248{
249 register struct wordent *p;
250 register struct command *t;
251 int l;
252
253 l = 0;
254 for (p = p1; p != p2; p = p->next)
255 switch (p->word[0]) {
256
257 case '(':
258 l++;
259 continue;
260
261 case ')':
262 l--;
263 continue;
264
265 case ';':
266 case '\n':
267 if (l != 0)
268 break;
269 t = (struct command *) calloc(1, sizeof (*t));
270 t->t_dtyp = TLST;
271 t->t_dcar = syn1a(p1, p, flags);
272 t->t_dcdr = syntax(p->next, p2, flags);
273 if (t->t_dcdr == 0)
274 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
275 return (t);
276 }
277 return (syn1a(p1, p2, flags));
278}
279
280/*
281 * syn1a
282 * syn1b
283 * syn1b || syn1a
284 */
285struct command *
286syn1a(p1, p2, flags)
287 struct wordent *p1, *p2;
288 int flags;
289{
290 register struct wordent *p;
291 register struct command *t;
292 register int l = 0;
293
294 for (p = p1; p != p2; p = p->next)
295 switch (p->word[0]) {
296
297 case '(':
298 l++;
299 continue;
300
301 case ')':
302 l--;
303 continue;
304
305 case '|':
306 if (p->word[1] != '|')
307 continue;
308 if (l == 0) {
309 t = (struct command *) calloc(1, sizeof (*t));
310 t->t_dtyp = TOR;
311 t->t_dcar = syn1b(p1, p, flags);
312 t->t_dcdr = syn1a(p->next, p2, flags);
313 t->t_dflg = 0;
314 return (t);
315 }
316 continue;
317 }
318 return (syn1b(p1, p2, flags));
319}
320
321/*
322 * syn1b
323 * syn2
324 * syn2 && syn1b
325 */
326struct command *
327syn1b(p1, p2, flags)
328 struct wordent *p1, *p2;
329 int flags;
330{
331 register struct wordent *p;
332 register struct command *t;
333 register int l = 0;
334
335 l = 0;
336 for (p = p1; p != p2; p = p->next)
337 switch (p->word[0]) {
338
339 case '(':
340 l++;
341 continue;
342
343 case ')':
344 l--;
345 continue;
346
347 case '&':
348 if (p->word[1] == '&' && l == 0) {
349 t = (struct command *) calloc(1, sizeof (*t));
350 t->t_dtyp = TAND;
351 t->t_dcar = syn2(p1, p, flags);
352 t->t_dcdr = syn1b(p->next, p2, flags);
353 t->t_dflg = 0;
354 return (t);
355 }
356 continue;
357 }
358 return (syn2(p1, p2, flags));
359}
360
361/*
362 * syn2
363 * syn3
364 * syn3 | syn2
365 * syn3 |& syn2
366 */
367struct command *
368syn2(p1, p2, flags)
369 struct wordent *p1, *p2;
370 int flags;
371{
372 register struct wordent *p, *pn;
373 register struct command *t;
374 register int l = 0;
375 int f;
376
377 for (p = p1; p != p2; p = p->next)
378 switch (p->word[0]) {
379
380 case '(':
381 l++;
382 continue;
383
384 case ')':
385 l--;
386 continue;
387
388 case '|':
389 if (l != 0)
390 continue;
391 t = (struct command *) calloc(1, sizeof (*t));
392 f = flags | POUT;
393 pn = p->next;
394 if (pn != p2 && pn->word[0] == '&') {
395 f |= PDIAG;
396 t->t_dflg |= FDIAG;
397 }
398 t->t_dtyp = TFIL;
399 t->t_dcar = syn3(p1, p, f);
400 if (pn != p2 && pn->word[0] == '&')
401 p = pn;
402 t->t_dcdr = syn2(p->next, p2, flags | PIN);
403 return (t);
404 }
405 return (syn3(p1, p2, flags));
406}
407
408char *RELPAR = "<>()";
409
410/*
411 * syn3
412 * ( syn0 ) [ < in ] [ > out ]
413 * word word* [ < in ] [ > out ]
414 * KEYWORD ( word* ) word* [ < in ] [ > out ]
415 *
416 * KEYWORD = (@ exit foreach if set switch test while)
417 */
418struct command *
419syn3(p1, p2, flags)
420 struct wordent *p1, *p2;
421 int flags;
422{
423 register struct wordent *p;
424 struct wordent *lp, *rp;
425 register struct command *t;
426 register int l;
427 char **av;
428 int n, c;
429 bool specp = 0;
430
431 if (p1 != p2) {
432 p = p1;
433again:
434 switch (srchx(p->word)) {
435
436 case ZELSE:
437 p = p->next;
438 if (p != p2)
439 goto again;
440 break;
441
442 case ZEXIT:
443 case ZFOREACH:
444 case ZIF:
445 case ZLET:
446 case ZSET:
447 case ZSWITCH:
448 case ZWHILE:
449 specp = 1;
450 break;
451 }
452 }
453 n = 0;
454 l = 0;
455 for (p = p1; p != p2; p = p->next)
456 switch (p->word[0]) {
457
458 case '(':
459 if (specp)
460 n++;
461 l++;
462 continue;
463
464 case ')':
465 if (specp)
466 n++;
467 l--;
468 continue;
469
470 case '>':
471 case '<':
472 if (l != 0) {
473 if (specp)
474 n++;
475 continue;
476 }
477 if (p->next == p2)
478 continue;
479 if (any(p->next->word[0], RELPAR))
480 continue;
481 n--;
482 continue;
483
484 default:
485 if (!specp && l != 0)
486 continue;
487 n++;
488 continue;
489 }
490 if (n < 0)
491 n = 0;
492 t = (struct command *) calloc(1, sizeof (*t));
493 av = (char **) calloc(n + 1, sizeof (char **));
494 t->t_dcom = av;
495 n = 0;
496 if (p2->word[0] == ')')
497 t->t_dflg = FPAR;
498 lp = 0;
499 rp = 0;
500 l = 0;
501 for (p = p1; p != p2; p = p->next) {
502 c = p->word[0];
503 switch (c) {
504
505 case '(':
506 if (l == 0) {
507 if (lp != 0 && !specp)
508 seterr("Badly placed (");
509 lp = p->next;
510 }
511 l++;
512 goto savep;
513
514 case ')':
515 l--;
516 if (l == 0)
517 rp = p;
518 goto savep;
519
520 case '>':
521 if (l != 0)
522 goto savep;
523 if (p->word[1] == '>')
524 t->t_dflg |= FCAT;
525 if (p->next != p2 && eq(p->next->word, "&")) {
526 t->t_dflg |= FDIAG, p = p->next;
527 if (flags & (POUT|PDIAG))
528 goto badout;
529 }
530 if (p->next != p2 && eq(p->next->word, "!"))
531 t->t_dflg |= FANY, p = p->next;
532 if (p->next == p2) {
533missfile:
534 seterr("Missing name for redirect");
535 continue;
536 }
537 p = p->next;
538 if (any(p->word[0], RELPAR))
539 goto missfile;
540 if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
541badout:
542 seterr("Ambiguous output redirect");
543 else
544 t->t_drit = savestr(p->word);
545 continue;
546
547 case '<':
548 if (l != 0)
549 goto savep;
550 if (p->word[1] == '<')
551 t->t_dflg |= FHERE;
552 if (p->next == p2)
553 goto missfile;
554 p = p->next;
555 if (any(p->word[0], RELPAR))
556 goto missfile;
557 if ((flags & PHERE) && (t->t_dflg & FHERE))
558 seterr("Can't << within ()'s");
559 else if ((flags & PIN) || t->t_dlef)
560 seterr("Ambiguous input redirect");
561 else
562 t->t_dlef = savestr(p->word);
563 continue;
564
565savep:
566 if (!specp)
567 continue;
568 default:
569 if (l != 0 && !specp)
570 continue;
571 if (err == 0)
572 av[n] = savestr(p->word);
573 n++;
574 continue;
575 }
576 }
577 if (lp != 0 && !specp) {
578 if (n != 0)
579 seterr("Badly placed ()'s");
580 t->t_dtyp = TPAR;
581 t->t_dspr = syn0(lp, rp, PHERE);
582 } else {
583 if (n == 0)
584 seterr("Invalid null command");
585 t->t_dtyp = TCOM;
586 }
587 return (t);
588}
589
590freesyn(t)
591 register struct command *t;
592{
593 register char **v;
594
595 if (t == 0)
596 return;
597 switch (t->t_dtyp) {
598
599 case TCOM:
600 for (v = t->t_dcom; *v; v++)
601 xfree(*v);
602 xfree(t->t_dcom);
603 goto lr;
604
605 case TPAR:
606 freesyn(t->t_dspr);
607 /* fall into ... */
608
609lr:
610 xfree(t->t_dlef), xfree(t->t_drit);
611 break;
612
613 case TAND:
614 case TOR:
615 case TFIL:
616 case TLST:
617 freesyn(t->t_dcar), freesyn(t->t_dcdr);
618 break;
619 }
620 xfree(t);
621}