nice is absolute after all; comment the problem Sun has with signal status
[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
c741e0c0 8static char *sccsid = "@(#)parse.c 5.3 (Berkeley) %G%";
094e80ed 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);
c741e0c0
JL
227 if (t1->t_dtyp == TLST ||
228 t1->t_dtyp == TAND ||
229 t1->t_dtyp == TOR) {
0d061c44
BJ
230 t = (struct command *) calloc(1, sizeof (*t));
231 t->t_dtyp = TPAR;
232 t->t_dflg = FAND|FINT;
233 t->t_dspr = t1;
234 t1 = t;
235 } else
236 t1->t_dflg |= FAND|FINT;
237 t = (struct command *) calloc(1, sizeof (*t));
238 t->t_dtyp = TLST;
239 t->t_dflg = 0;
240 t->t_dcar = t1;
241 t->t_dcdr = syntax(p, p2, flags);
242 return(t);
243 }
244 if (l == 0)
245 return (syn1(p1, p2, flags));
246 seterr("Too many ('s");
247 return (0);
248}
249
250/*
251 * syn1
252 * syn1a
253 * syn1a ; syntax
254 */
255struct command *
256syn1(p1, p2, flags)
257 struct wordent *p1, *p2;
258 int flags;
259{
260 register struct wordent *p;
261 register struct command *t;
262 int l;
263
264 l = 0;
265 for (p = p1; p != p2; p = p->next)
266 switch (p->word[0]) {
267
268 case '(':
269 l++;
270 continue;
271
272 case ')':
273 l--;
274 continue;
275
276 case ';':
277 case '\n':
278 if (l != 0)
279 break;
280 t = (struct command *) calloc(1, sizeof (*t));
281 t->t_dtyp = TLST;
282 t->t_dcar = syn1a(p1, p, flags);
283 t->t_dcdr = syntax(p->next, p2, flags);
284 if (t->t_dcdr == 0)
285 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
286 return (t);
287 }
288 return (syn1a(p1, p2, flags));
289}
290
291/*
292 * syn1a
293 * syn1b
294 * syn1b || syn1a
295 */
296struct command *
297syn1a(p1, p2, flags)
298 struct wordent *p1, *p2;
299 int flags;
300{
301 register struct wordent *p;
302 register struct command *t;
303 register int l = 0;
304
305 for (p = p1; p != p2; p = p->next)
306 switch (p->word[0]) {
307
308 case '(':
309 l++;
310 continue;
311
312 case ')':
313 l--;
314 continue;
315
316 case '|':
317 if (p->word[1] != '|')
318 continue;
319 if (l == 0) {
320 t = (struct command *) calloc(1, sizeof (*t));
321 t->t_dtyp = TOR;
322 t->t_dcar = syn1b(p1, p, flags);
323 t->t_dcdr = syn1a(p->next, p2, flags);
324 t->t_dflg = 0;
325 return (t);
326 }
327 continue;
328 }
329 return (syn1b(p1, p2, flags));
330}
331
332/*
333 * syn1b
334 * syn2
335 * syn2 && syn1b
336 */
337struct command *
338syn1b(p1, p2, flags)
339 struct wordent *p1, *p2;
340 int flags;
341{
342 register struct wordent *p;
343 register struct command *t;
344 register int l = 0;
345
346 l = 0;
347 for (p = p1; p != p2; p = p->next)
348 switch (p->word[0]) {
349
350 case '(':
351 l++;
352 continue;
353
354 case ')':
355 l--;
356 continue;
357
358 case '&':
359 if (p->word[1] == '&' && l == 0) {
360 t = (struct command *) calloc(1, sizeof (*t));
361 t->t_dtyp = TAND;
362 t->t_dcar = syn2(p1, p, flags);
363 t->t_dcdr = syn1b(p->next, p2, flags);
364 t->t_dflg = 0;
365 return (t);
366 }
367 continue;
368 }
369 return (syn2(p1, p2, flags));
370}
371
372/*
373 * syn2
374 * syn3
375 * syn3 | syn2
376 * syn3 |& syn2
377 */
378struct command *
379syn2(p1, p2, flags)
380 struct wordent *p1, *p2;
381 int flags;
382{
383 register struct wordent *p, *pn;
384 register struct command *t;
385 register int l = 0;
386 int f;
387
388 for (p = p1; p != p2; p = p->next)
389 switch (p->word[0]) {
390
391 case '(':
392 l++;
393 continue;
394
395 case ')':
396 l--;
397 continue;
398
399 case '|':
400 if (l != 0)
401 continue;
402 t = (struct command *) calloc(1, sizeof (*t));
403 f = flags | POUT;
404 pn = p->next;
405 if (pn != p2 && pn->word[0] == '&') {
406 f |= PDIAG;
407 t->t_dflg |= FDIAG;
408 }
409 t->t_dtyp = TFIL;
410 t->t_dcar = syn3(p1, p, f);
411 if (pn != p2 && pn->word[0] == '&')
412 p = pn;
413 t->t_dcdr = syn2(p->next, p2, flags | PIN);
414 return (t);
415 }
416 return (syn3(p1, p2, flags));
417}
418
419char *RELPAR = "<>()";
420
421/*
422 * syn3
423 * ( syn0 ) [ < in ] [ > out ]
424 * word word* [ < in ] [ > out ]
425 * KEYWORD ( word* ) word* [ < in ] [ > out ]
426 *
427 * KEYWORD = (@ exit foreach if set switch test while)
428 */
429struct command *
430syn3(p1, p2, flags)
431 struct wordent *p1, *p2;
432 int flags;
433{
434 register struct wordent *p;
435 struct wordent *lp, *rp;
436 register struct command *t;
437 register int l;
438 char **av;
439 int n, c;
440 bool specp = 0;
441
442 if (p1 != p2) {
443 p = p1;
444again:
445 switch (srchx(p->word)) {
446
447 case ZELSE:
448 p = p->next;
449 if (p != p2)
450 goto again;
451 break;
452
453 case ZEXIT:
454 case ZFOREACH:
455 case ZIF:
456 case ZLET:
457 case ZSET:
458 case ZSWITCH:
459 case ZWHILE:
460 specp = 1;
461 break;
462 }
463 }
464 n = 0;
465 l = 0;
466 for (p = p1; p != p2; p = p->next)
467 switch (p->word[0]) {
468
469 case '(':
470 if (specp)
471 n++;
472 l++;
473 continue;
474
475 case ')':
476 if (specp)
477 n++;
478 l--;
479 continue;
480
481 case '>':
482 case '<':
483 if (l != 0) {
484 if (specp)
485 n++;
486 continue;
487 }
488 if (p->next == p2)
489 continue;
490 if (any(p->next->word[0], RELPAR))
491 continue;
492 n--;
493 continue;
494
495 default:
496 if (!specp && l != 0)
497 continue;
498 n++;
499 continue;
500 }
501 if (n < 0)
502 n = 0;
503 t = (struct command *) calloc(1, sizeof (*t));
35371dec 504 av = (char **) calloc((unsigned) (n + 1), sizeof (char **));
0d061c44
BJ
505 t->t_dcom = av;
506 n = 0;
507 if (p2->word[0] == ')')
508 t->t_dflg = FPAR;
509 lp = 0;
510 rp = 0;
511 l = 0;
512 for (p = p1; p != p2; p = p->next) {
513 c = p->word[0];
514 switch (c) {
515
516 case '(':
517 if (l == 0) {
518 if (lp != 0 && !specp)
519 seterr("Badly placed (");
520 lp = p->next;
521 }
522 l++;
523 goto savep;
524
525 case ')':
526 l--;
527 if (l == 0)
528 rp = p;
529 goto savep;
530
531 case '>':
532 if (l != 0)
533 goto savep;
534 if (p->word[1] == '>')
535 t->t_dflg |= FCAT;
536 if (p->next != p2 && eq(p->next->word, "&")) {
537 t->t_dflg |= FDIAG, p = p->next;
538 if (flags & (POUT|PDIAG))
539 goto badout;
540 }
541 if (p->next != p2 && eq(p->next->word, "!"))
542 t->t_dflg |= FANY, p = p->next;
543 if (p->next == p2) {
544missfile:
545 seterr("Missing name for redirect");
546 continue;
547 }
548 p = p->next;
549 if (any(p->word[0], RELPAR))
550 goto missfile;
551 if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
552badout:
553 seterr("Ambiguous output redirect");
554 else
555 t->t_drit = savestr(p->word);
556 continue;
557
558 case '<':
559 if (l != 0)
560 goto savep;
561 if (p->word[1] == '<')
562 t->t_dflg |= FHERE;
563 if (p->next == p2)
564 goto missfile;
565 p = p->next;
566 if (any(p->word[0], RELPAR))
567 goto missfile;
568 if ((flags & PHERE) && (t->t_dflg & FHERE))
569 seterr("Can't << within ()'s");
570 else if ((flags & PIN) || t->t_dlef)
571 seterr("Ambiguous input redirect");
572 else
573 t->t_dlef = savestr(p->word);
574 continue;
575
576savep:
577 if (!specp)
578 continue;
579 default:
580 if (l != 0 && !specp)
581 continue;
582 if (err == 0)
583 av[n] = savestr(p->word);
584 n++;
585 continue;
586 }
587 }
588 if (lp != 0 && !specp) {
589 if (n != 0)
590 seterr("Badly placed ()'s");
591 t->t_dtyp = TPAR;
592 t->t_dspr = syn0(lp, rp, PHERE);
593 } else {
594 if (n == 0)
595 seterr("Invalid null command");
596 t->t_dtyp = TCOM;
597 }
598 return (t);
599}
600
601freesyn(t)
602 register struct command *t;
603{
604 register char **v;
605
606 if (t == 0)
607 return;
608 switch (t->t_dtyp) {
609
610 case TCOM:
611 for (v = t->t_dcom; *v; v++)
35371dec
EW
612 XFREE(*v)
613 XFREE((char *)t->t_dcom)
0d061c44
BJ
614 goto lr;
615
616 case TPAR:
617 freesyn(t->t_dspr);
618 /* fall into ... */
619
620lr:
35371dec
EW
621 XFREE(t->t_dlef)
622 XFREE(t->t_drit)
0d061c44
BJ
623 break;
624
625 case TAND:
626 case TOR:
627 case TFIL:
628 case TLST:
629 freesyn(t->t_dcar), freesyn(t->t_dcdr);
630 break;
631 }
35371dec 632 XFREE((char *)t)
0d061c44 633}