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