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