source: trunk/minix/commands/sh/sh2.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 12.3 KB
RevLine 
[9]1#define Extern extern
2#include <sys/types.h>
3#include <signal.h>
4#include <errno.h>
5#include <setjmp.h>
6#include "sh.h"
7
8/* -------- csyn.c -------- */
9/*
10 * shell: syntax (C version)
11 */
12
13typedef union {
14 char *cp;
15 char **wp;
16 int i;
17 struct op *o;
18} YYSTYPE;
19#define WORD 256
20#define LOGAND 257
21#define LOGOR 258
22#define BREAK 259
23#define IF 260
24#define THEN 261
25#define ELSE 262
26#define ELIF 263
27#define FI 264
28#define CASE 265
29#define ESAC 266
30#define FOR 267
31#define WHILE 268
32#define UNTIL 269
33#define DO 270
34#define DONE 271
35#define IN 272
36#define YYERRCODE 300
37
38/* flags to yylex */
39#define CONTIN 01 /* skip new lines to complete command */
40
41/* #include "sh.h" */
42#define SYNTAXERR zzerr()
43static int startl;
44static int peeksym;
45static int nlseen;
46static int iounit = IODEFAULT;
47
48static YYSTYPE yylval;
49
50_PROTOTYPE(static struct op *pipeline, (int cf ));
51_PROTOTYPE(static struct op *andor, (void));
52_PROTOTYPE(static struct op *c_list, (void));
53_PROTOTYPE(static int synio, (int cf ));
54_PROTOTYPE(static void musthave, (int c, int cf ));
55_PROTOTYPE(static struct op *simple, (void));
56_PROTOTYPE(static struct op *nested, (int type, int mark ));
57_PROTOTYPE(static struct op *command, (int cf ));
58_PROTOTYPE(static struct op *dogroup, (int onlydone ));
59_PROTOTYPE(static struct op *thenpart, (void));
60_PROTOTYPE(static struct op *elsepart, (void));
61_PROTOTYPE(static struct op *caselist, (void));
62_PROTOTYPE(static struct op *casepart, (void));
63_PROTOTYPE(static char **pattern, (void));
64_PROTOTYPE(static char **wordlist, (void));
65_PROTOTYPE(static struct op *list, (struct op *t1, struct op *t2 ));
66_PROTOTYPE(static struct op *block, (int type, struct op *t1, struct op *t2, char **wp ));
67_PROTOTYPE(static struct op *newtp, (void));
68_PROTOTYPE(static struct op *namelist, (struct op *t ));
69_PROTOTYPE(static char **copyw, (void));
70_PROTOTYPE(static void word, (char *cp ));
71_PROTOTYPE(static struct ioword **copyio, (void));
72_PROTOTYPE(static struct ioword *io, (int u, int f, char *cp ));
73_PROTOTYPE(static void zzerr, (void));
74_PROTOTYPE(void yyerror, (char *s ));
75_PROTOTYPE(static int yylex, (int cf ));
76_PROTOTYPE(int collect, (int c, int c1 ));
77_PROTOTYPE(int dual, (int c ));
78_PROTOTYPE(static void diag, (int ec ));
79_PROTOTYPE(static char *tree, (unsigned size ));
80_PROTOTYPE(void printf, (char *s ));
81
82int
83yyparse()
84{
85 startl = 1;
86 peeksym = 0;
87 yynerrs = 0;
88 outtree = c_list();
89 musthave('\n', 0);
90 return(yynerrs!=0);
91}
92
93static struct op *
94pipeline(cf)
95int cf;
96{
97 register struct op *t, *p;
98 register int c;
99
100 t = command(cf);
101 if (t != NULL) {
102 while ((c = yylex(0)) == '|') {
103 if ((p = command(CONTIN)) == NULL)
104 SYNTAXERR;
105 if (t->type != TPAREN && t->type != TCOM) {
106 /* shell statement */
107 t = block(TPAREN, t, NOBLOCK, NOWORDS);
108 }
109 t = block(TPIPE, t, p, NOWORDS);
110 }
111 peeksym = c;
112 }
113 return(t);
114}
115
116static struct op *
117andor()
118{
119 register struct op *t, *p;
120 register int c;
121
122 t = pipeline(0);
123 if (t != NULL) {
124 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
125 if ((p = pipeline(CONTIN)) == NULL)
126 SYNTAXERR;
127 t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS);
128 }
129 peeksym = c;
130 }
131 return(t);
132}
133
134static struct op *
135c_list()
136{
137 register struct op *t, *p;
138 register int c;
139
140 t = andor();
141 if (t != NULL) {
142 if((peeksym = yylex(0)) == '&')
143 t = block(TASYNC, t, NOBLOCK, NOWORDS);
144 while ((c = yylex(0)) == ';' || c == '&' || (multiline && c == '\n')) {
145 if ((p = andor()) == NULL)
146 return(t);
147 if((peeksym = yylex(0)) == '&')
148 p = block(TASYNC, p, NOBLOCK, NOWORDS);
149 t = list(t, p);
150 }
151 peeksym = c;
152 }
153 return(t);
154}
155
156
157static int
158synio(cf)
159int cf;
160{
161 register struct ioword *iop;
162 register int i;
163 register int c;
164
165 if ((c = yylex(cf)) != '<' && c != '>') {
166 peeksym = c;
167 return(0);
168 }
169 i = yylval.i;
170 musthave(WORD, 0);
171 iop = io(iounit, i, yylval.cp);
172 iounit = IODEFAULT;
173 if (i & IOHERE)
174 markhere(yylval.cp, iop);
175 return(1);
176}
177
178static void
179musthave(c, cf)
180int c, cf;
181{
182 if ((peeksym = yylex(cf)) != c)
183 SYNTAXERR;
184 peeksym = 0;
185}
186
187static struct op *
188simple()
189{
190 register struct op *t;
191
192 t = NULL;
193 for (;;) {
194 switch (peeksym = yylex(0)) {
195 case '<':
196 case '>':
197 (void) synio(0);
198 break;
199
200 case WORD:
201 if (t == NULL) {
202 t = newtp();
203 t->type = TCOM;
204 }
205 peeksym = 0;
206 word(yylval.cp);
207 break;
208
209 default:
210 return(t);
211 }
212 }
213}
214
215static struct op *
216nested(type, mark)
217int type, mark;
218{
219 register struct op *t;
220
221 multiline++;
222 t = c_list();
223 musthave(mark, 0);
224 multiline--;
225 return(block(type, t, NOBLOCK, NOWORDS));
226}
227
228static struct op *
229command(cf)
230int cf;
231{
232 register struct op *t;
233 struct wdblock *iosave;
234 register int c;
235
236 iosave = iolist;
237 iolist = NULL;
238 if (multiline)
239 cf |= CONTIN;
240 while (synio(cf))
241 cf = 0;
242 switch (c = yylex(cf)) {
243 default:
244 peeksym = c;
245 if ((t = simple()) == NULL) {
246 if (iolist == NULL)
247 return((struct op *)NULL);
248 t = newtp();
249 t->type = TCOM;
250 }
251 break;
252
253 case '(':
254 t = nested(TPAREN, ')');
255 break;
256
257 case '{':
258 t = nested(TBRACE, '}');
259 break;
260
261 case FOR:
262 t = newtp();
263 t->type = TFOR;
264 musthave(WORD, 0);
265 startl = 1;
266 t->str = yylval.cp;
267 multiline++;
268 t->words = wordlist();
269 if ((c = yylex(0)) != '\n' && c != ';')
270 peeksym = c;
271 t->left = dogroup(0);
272 multiline--;
273 break;
274
275 case WHILE:
276 case UNTIL:
277 multiline++;
278 t = newtp();
279 t->type = c == WHILE? TWHILE: TUNTIL;
280 t->left = c_list();
281 t->right = dogroup(1);
282 t->words = NULL;
283 multiline--;
284 break;
285
286 case CASE:
287 t = newtp();
288 t->type = TCASE;
289 musthave(WORD, 0);
290 t->str = yylval.cp;
291 startl++;
292 multiline++;
293 musthave(IN, CONTIN);
294 startl++;
295 t->left = caselist();
296 musthave(ESAC, 0);
297 multiline--;
298 break;
299
300 case IF:
301 multiline++;
302 t = newtp();
303 t->type = TIF;
304 t->left = c_list();
305 t->right = thenpart();
306 musthave(FI, 0);
307 multiline--;
308 break;
309 }
310 while (synio(0))
311 ;
312 t = namelist(t);
313 iolist = iosave;
314 return(t);
315}
316
317static struct op *
318dogroup(onlydone)
319int onlydone;
320{
321 register int c;
322 register struct op *list;
323
324 c = yylex(CONTIN);
325 if (c == DONE && onlydone)
326 return((struct op *)NULL);
327 if (c != DO)
328 SYNTAXERR;
329 list = c_list();
330 musthave(DONE, 0);
331 return(list);
332}
333
334static struct op *
335thenpart()
336{
337 register int c;
338 register struct op *t;
339
340 if ((c = yylex(0)) != THEN) {
341 peeksym = c;
342 return((struct op *)NULL);
343 }
344 t = newtp();
345 t->type = 0;
346 t->left = c_list();
347 if (t->left == NULL)
348 SYNTAXERR;
349 t->right = elsepart();
350 return(t);
351}
352
353static struct op *
354elsepart()
355{
356 register int c;
357 register struct op *t;
358
359 switch (c = yylex(0)) {
360 case ELSE:
361 if ((t = c_list()) == NULL)
362 SYNTAXERR;
363 return(t);
364
365 case ELIF:
366 t = newtp();
367 t->type = TELIF;
368 t->left = c_list();
369 t->right = thenpart();
370 return(t);
371
372 default:
373 peeksym = c;
374 return((struct op *)NULL);
375 }
376}
377
378static struct op *
379caselist()
380{
381 register struct op *t;
382
383 t = NULL;
384 while ((peeksym = yylex(CONTIN)) != ESAC)
385 t = list(t, casepart());
386 return(t);
387}
388
389static struct op *
390casepart()
391{
392 register struct op *t;
393
394 t = newtp();
395 t->type = TPAT;
396 t->words = pattern();
397 musthave(')', 0);
398 t->left = c_list();
399 if ((peeksym = yylex(CONTIN)) != ESAC)
400 musthave(BREAK, CONTIN);
401 return(t);
402}
403
404static char **
405pattern()
406{
407 register int c, cf;
408
409 cf = CONTIN;
410 do {
411 musthave(WORD, cf);
412 word(yylval.cp);
413 cf = 0;
414 } while ((c = yylex(0)) == '|');
415 peeksym = c;
416 word(NOWORD);
417 return(copyw());
418}
419
420static char **
421wordlist()
422{
423 register int c;
424
425 if ((c = yylex(0)) != IN) {
426 peeksym = c;
427 return((char **)NULL);
428 }
429 startl = 0;
430 while ((c = yylex(0)) == WORD)
431 word(yylval.cp);
432 word(NOWORD);
433 peeksym = c;
434 return(copyw());
435}
436
437/*
438 * supporting functions
439 */
440static struct op *
441list(t1, t2)
442register struct op *t1, *t2;
443{
444 if (t1 == NULL)
445 return(t2);
446 if (t2 == NULL)
447 return(t1);
448 return(block(TLIST, t1, t2, NOWORDS));
449}
450
451static struct op *
452block(type, t1, t2, wp)
453int type;
454struct op *t1, *t2;
455char **wp;
456{
457 register struct op *t;
458
459 t = newtp();
460 t->type = type;
461 t->left = t1;
462 t->right = t2;
463 t->words = wp;
464 return(t);
465}
466
467struct res {
468 char *r_name;
469 int r_val;
470} restab[] = {
471 "for", FOR,
472 "case", CASE,
473 "esac", ESAC,
474 "while", WHILE,
475 "do", DO,
476 "done", DONE,
477 "if", IF,
478 "in", IN,
479 "then", THEN,
480 "else", ELSE,
481 "elif", ELIF,
482 "until", UNTIL,
483 "fi", FI,
484
485 ";;", BREAK,
486 "||", LOGOR,
487 "&&", LOGAND,
488 "{", '{',
489 "}", '}',
490
491 0,
492};
493
494int
495rlookup(n)
496register char *n;
497{
498 register struct res *rp;
499
500 for (rp = restab; rp->r_name; rp++)
501 if (strcmp(rp->r_name, n) == 0)
502 return(rp->r_val);
503 return(0);
504}
505
506static struct op *
507newtp()
508{
509 register struct op *t;
510
511 t = (struct op *)tree(sizeof(*t));
512 t->type = 0;
513 t->words = NULL;
514 t->ioact = NULL;
515 t->left = NULL;
516 t->right = NULL;
517 t->str = NULL;
518 return(t);
519}
520
521static struct op *
522namelist(t)
523register struct op *t;
524{
525 if (iolist) {
526 iolist = addword((char *)NULL, iolist);
527 t->ioact = copyio();
528 } else
529 t->ioact = NULL;
530 if (t->type != TCOM) {
531 if (t->type != TPAREN && t->ioact != NULL) {
532 t = block(TPAREN, t, NOBLOCK, NOWORDS);
533 t->ioact = t->left->ioact;
534 t->left->ioact = NULL;
535 }
536 return(t);
537 }
538 word(NOWORD);
539 t->words = copyw();
540 return(t);
541}
542
543static char **
544copyw()
545{
546 register char **wd;
547
548 wd = getwords(wdlist);
549 wdlist = 0;
550 return(wd);
551}
552
553static void
554word(cp)
555char *cp;
556{
557 wdlist = addword(cp, wdlist);
558}
559
560static struct ioword **
561copyio()
562{
563 register struct ioword **iop;
564
565 iop = (struct ioword **) getwords(iolist);
566 iolist = 0;
567 return(iop);
568}
569
570static struct ioword *
571io(u, f, cp)
572int u;
573int f;
574char *cp;
575{
576 register struct ioword *iop;
577
578 iop = (struct ioword *) tree(sizeof(*iop));
579 iop->io_unit = u;
580 iop->io_flag = f;
581 iop->io_name = cp;
582 iolist = addword((char *)iop, iolist);
583 return(iop);
584}
585
586static void
587zzerr()
588{
589 yyerror("syntax error");
590}
591
592void
593yyerror(s)
594char *s;
595{
596 yynerrs++;
597 if (talking && e.iop <= iostack) {
598 multiline = 0;
599 while (eofc() == 0 && yylex(0) != '\n')
600 ;
601 }
602 err(s);
603 fail();
604}
605
606static int
607yylex(cf)
608int cf;
609{
610 register int c, c1;
611 int atstart;
612
613 if ((c = peeksym) > 0) {
614 peeksym = 0;
615 if (c == '\n')
616 startl = 1;
617 return(c);
618 }
619 nlseen = 0;
620 e.linep = line;
621 atstart = startl;
622 startl = 0;
623 yylval.i = 0;
624
625loop:
626 while ((c = getc(0)) == ' ' || c == '\t')
627 ;
628 switch (c) {
629 default:
630 if (any(c, "0123456789")) {
631 unget(c1 = getc(0));
632 if (c1 == '<' || c1 == '>') {
633 iounit = c - '0';
634 goto loop;
635 }
636 *e.linep++ = c;
637 c = c1;
638 }
639 break;
640
641 case '#':
642 while ((c = getc(0)) != 0 && c != '\n')
643 ;
644 unget(c);
645 goto loop;
646
647 case 0:
648 return(c);
649
650 case '$':
651 *e.linep++ = c;
652 if ((c = getc(0)) == '{') {
653 if ((c = collect(c, '}')) != '\0')
654 return(c);
655 goto pack;
656 }
657 break;
658
659 case '`':
660 case '\'':
661 case '"':
662 if ((c = collect(c, c)) != '\0')
663 return(c);
664 goto pack;
665
666 case '|':
667 case '&':
668 case ';':
669 if ((c1 = dual(c)) != '\0') {
670 startl = 1;
671 return(c1);
672 }
673 startl = 1;
674 return(c);
675 case '^':
676 startl = 1;
677 return('|');
678 case '>':
679 case '<':
680 diag(c);
681 return(c);
682
683 case '\n':
684 nlseen++;
685 gethere();
686 startl = 1;
687 if (multiline || cf & CONTIN) {
688 if (talking && e.iop <= iostack)
689 prs(cprompt->value);
690 if (cf & CONTIN)
691 goto loop;
692 }
693 return(c);
694
695 case '(':
696 case ')':
697 startl = 1;
698 return(c);
699 }
700
701 unget(c);
702
703pack:
704 while ((c = getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n"))
705 if (e.linep >= elinep)
706 err("word too long");
707 else
708 *e.linep++ = c;
709 unget(c);
710 if(any(c, "\"'`$"))
711 goto loop;
712 *e.linep++ = '\0';
713 if (atstart && (c = rlookup(line))!=0) {
714 startl = 1;
715 return(c);
716 }
717 yylval.cp = strsave(line, areanum);
718 return(WORD);
719}
720
721int
722collect(c, c1)
723register c, c1;
724{
725 char s[2];
726
727 *e.linep++ = c;
728 while ((c = getc(c1)) != c1) {
729 if (c == 0) {
730 unget(c);
731 s[0] = c1;
732 s[1] = 0;
733 prs("no closing "); yyerror(s);
734 return(YYERRCODE);
735 }
736 if (talking && c == '\n' && e.iop <= iostack)
737 prs(cprompt->value);
738 *e.linep++ = c;
739 }
740 *e.linep++ = c;
741 return(0);
742}
743
744int
745dual(c)
746register c;
747{
748 char s[3];
749 register char *cp = s;
750
751 *cp++ = c;
752 *cp++ = getc(0);
753 *cp = 0;
754 if ((c = rlookup(s)) == 0)
755 unget(*--cp);
756 return(c);
757}
758
759static void
760diag(ec)
761register int ec;
762{
763 register int c;
764
765 c = getc(0);
766 if (c == '>' || c == '<') {
767 if (c != ec)
768 zzerr();
769 yylval.i = ec == '>'? IOWRITE|IOCAT: IOHERE;
770 c = getc(0);
771 } else
772 yylval.i = ec == '>'? IOWRITE: IOREAD;
773 if (c != '&' || yylval.i == IOHERE)
774 unget(c);
775 else
776 yylval.i |= IODUP;
777}
778
779static char *
780tree(size)
781unsigned size;
782{
783 register char *t;
784
785 if ((t = getcell(size)) == NULL) {
786 prs("command line too complicated\n");
787 fail();
788 /* NOTREACHED */
789 }
790 return(t);
791}
792
793/* VARARGS1 */
794/* ARGSUSED */
795void
796printf(s) /* yyparse calls it */
797char *s;
798{
799}
800
Note: See TracBrowser for help on using the repository browser.