]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - release/picobsd/tinyware/msh/sh4.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 / sh4.c
1 #define Extern extern
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <dirent.h>
5 #include <limits.h>
6 #include <signal.h>
7 #define _NSIG NSIG
8 #include <errno.h>
9 #include <setjmp.h>
10 #include "sh.h"
11
12 /* -------- eval.c -------- */
13 /* #include "sh.h" */
14 /* #include "word.h" */
15
16 /*
17  * ${}
18  * `command`
19  * blank interpretation
20  * quoting
21  * glob
22  */
23
24 _PROTOTYPE(static int expand, (char *cp, struct wdblock **wbp, int f ));
25 _PROTOTYPE(static char *blank, (int f ));
26 _PROTOTYPE(static int dollar, (int quoted ));
27 _PROTOTYPE(static int grave, (int quoted ));
28 _PROTOTYPE(void globname, (char *we, char *pp ));
29 _PROTOTYPE(static char *generate, (char *start1, char *end1, char *middle, char *end ));
30 _PROTOTYPE(static int anyspcl, (struct wdblock *wb ));
31 _PROTOTYPE(static int xstrcmp, (char *p1, char *p2 ));
32 _PROTOTYPE(void glob0, (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *)));
33 _PROTOTYPE(void glob1, (char *base, char *lim ));
34 _PROTOTYPE(void glob2, (char *i, char *j ));
35 _PROTOTYPE(void glob3, (char *i, char *j, char *k ));
36 _PROTOTYPE(char *memcopy, (char *ato, char *from, int nb ));
37
38 char **
39 eval(ap, f)
40 register char **ap;
41 int f;
42 {
43         struct wdblock *wb;
44         char **wp;
45         char **wf;
46         jmp_buf ev;
47
48         wp = NULL;
49         wb = NULL;
50         wf = NULL;
51         if (newenv(setjmp(errpt = ev)) == 0) {
52                 while (*ap && isassign(*ap))
53                         expand(*ap++, &wb, f & ~DOGLOB);
54                 if (flag['k']) {
55                         for (wf = ap; *wf; wf++) {
56                                 if (isassign(*wf))
57                                         expand(*wf, &wb, f & ~DOGLOB);
58                         }
59                 }
60                 for (wb = addword((char *)0, wb); *ap; ap++) {
61                         if (!flag['k'] || !isassign(*ap))
62                                 expand(*ap, &wb, f & ~DOKEY);
63                 }
64                 wb = addword((char *)0, wb);
65                 wp = getwords(wb);
66                 quitenv();
67         } else
68                 gflg = 1;
69         return(gflg? (char **)NULL: wp);
70 }
71
72 /*
73  * Make the exported environment from the exported
74  * names in the dictionary. Keyword assignments
75  * will already have been done.
76  */
77 char **
78 makenv()
79
80 {
81         register struct wdblock *wb;
82         register struct var *vp;
83
84         wb = NULL;
85         for (vp = vlist; vp; vp = vp->next)
86                 if (vp->status & EXPORT)
87                         wb = addword(vp->name, wb);
88         wb = addword((char *)0, wb);
89         return(getwords(wb));
90 }
91
92 char *
93 evalstr(cp, f)
94 register char *cp;
95 int f;
96 {
97         struct wdblock *wb;
98
99         wb = NULL;
100         if (expand(cp, &wb, f)) {
101                 if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL)
102                         cp = "";
103                 DELETE(wb);
104         } else
105                 cp = NULL;
106         return(cp);
107 }
108
109 static int
110 expand(cp, wbp, f)
111 register char *cp;
112 register struct wdblock **wbp;
113 int f;
114 {
115         jmp_buf ev;
116
117         gflg = 0;
118         if (cp == NULL)
119                 return(0);
120         if (!anys("$`'\"", cp) &&
121             !anys(ifs->value, cp) &&
122             ((f&DOGLOB)==0 || !anys("[*?", cp))) {
123                 cp = strsave(cp, areanum);
124                 if (f & DOTRIM)
125                         unquote(cp);
126                 *wbp = addword(cp, *wbp);
127                 return(1);
128         }
129         if (newenv(setjmp(errpt = ev)) == 0) {
130                 PUSHIO(aword, cp, strchar);
131                 e.iobase = e.iop;
132                 while ((cp = blank(f)) && gflg == 0) {
133                         e.linep = cp;
134                         cp = strsave(cp, areanum);
135                         if ((f&DOGLOB) == 0) {
136                                 if (f & DOTRIM)
137                                         unquote(cp);
138                                 *wbp = addword(cp, *wbp);
139                         } else
140                                 *wbp = glob(cp, *wbp);
141                 }
142                 quitenv();
143         } else
144                 gflg = 1;
145         return(gflg == 0);
146 }
147
148 /*
149  * Blank interpretation and quoting
150  */
151 static char *
152 blank(f)
153 int f;
154 {
155         register c, c1;
156         register char *sp;
157         int scanequals, foundequals;
158
159         sp = e.linep;
160         scanequals = f & DOKEY;
161         foundequals = 0;
162
163 loop:
164         switch (c = subgetc('"', foundequals)) {
165         case 0:
166                 if (sp == e.linep)
167                         return(0);
168                 *e.linep++ = 0;
169                 return(sp);
170
171         default:
172                 if (f & DOBLANK && any(c, ifs->value))
173                         goto loop;
174                 break;
175
176         case '"':
177         case '\'':
178                 scanequals = 0;
179                 if (INSUB())
180                         break;
181                 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
182                         if (c == 0)
183                                 break;
184                         if (c == '\'' || !any(c, "$`\""))
185                                 c |= QUOTE;
186                         *e.linep++ = c;
187                 }
188                 c = 0;
189         }
190         unget(c);
191         if (!letter(c))
192                 scanequals = 0;
193         for (;;) {
194                 c = subgetc('"', foundequals);
195                 if (c == 0 ||
196                     f & (DOBLANK && any(c, ifs->value)) ||
197                     (!INSUB() && any(c, "\"'"))) {
198                         scanequals = 0;
199                         unget(c);
200                         if (any(c, "\"'"))
201                                 goto loop;
202                         break;
203                 }
204                 if (scanequals)
205                         if (c == '=') {
206                                 foundequals = 1;
207                                 scanequals  = 0;
208                         }
209                         else if (!letnum(c))
210                                 scanequals = 0;
211                 *e.linep++ = c;
212         }
213         *e.linep++ = 0;
214         return(sp);
215 }
216
217 /*
218  * Get characters, substituting for ` and $
219  */
220 int
221 subgetc(ec, quoted)
222 register char ec;
223 int quoted;
224 {
225         register char c;
226
227 again:
228         c = getc(ec);
229         if (!INSUB() && ec != '\'') {
230                 if (c == '`') {
231                         if (grave(quoted) == 0)
232                                 return(0);
233                         e.iop->task = XGRAVE;
234                         goto again;
235                 }
236                 if (c == '$' && (c = dollar(quoted)) == 0) {
237                         e.iop->task = XDOLL;
238                         goto again;
239                 }
240         }
241         return(c);
242 }
243
244 /*
245  * Prepare to generate the string returned by ${} substitution.
246  */
247 static int
248 dollar(quoted)
249 int quoted;
250 {
251         int otask;
252         struct io *oiop;
253         char *dolp;
254         register char *s, c, *cp;
255         struct var *vp;
256
257         c = readc();
258         s = e.linep;
259         if (c != '{') {
260                 *e.linep++ = c;
261                 if (letter(c)) {
262                         while ((c = readc())!=0 && letnum(c))
263                                 if (e.linep < elinep)
264                                         *e.linep++ = c;
265                         unget(c);
266                 }
267                 c = 0;
268         } else {
269                 oiop = e.iop;
270                 otask = e.iop->task;
271                 e.iop->task = XOTHER;
272                 while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n')
273                         if (e.linep < elinep)
274                                 *e.linep++ = c;
275                 if (oiop == e.iop)
276                         e.iop->task = otask;
277                 if (c != '}') {
278                         err("unclosed ${");
279                         gflg++;
280                         return(c);
281                 }
282         }
283         if (e.linep >= elinep) {
284                 err("string in ${} too long");
285                 gflg++;
286                 e.linep -= 10;
287         }
288         *e.linep = 0;
289         if (*s)
290                 for (cp = s+1; *cp; cp++)
291                         if (any(*cp, "=-+?")) {
292                                 c = *cp;
293                                 *cp++ = 0;
294                                 break;
295                         }
296         if (s[1] == 0 && (*s == '*' || *s == '@')) {
297                 if (dolc > 1) {
298                         /* currently this does not distinguish $* and $@ */
299                         /* should check dollar */
300                         e.linep = s;
301                         PUSHIO(awordlist, dolv+1, dolchar);
302                         return(0);
303                 } else {        /* trap the nasty ${=} */
304                         s[0] = '1';
305                         s[1] = 0;
306                 }
307         }
308         vp = lookup(s);
309         if ((dolp = vp->value) == null) {
310                 switch (c) {
311                 case '=':
312                         if (digit(*s)) {
313                                 err("cannot use ${...=...} with $n");
314                                 gflg++;
315                                 break;
316                         }
317                         setval(vp, cp);
318                         dolp = vp->value;
319                         break;
320
321                 case '-':
322                         dolp = strsave(cp, areanum);
323                         break;
324
325                 case '?':
326                         if (*cp == 0) {
327                                 prs("missing value for ");
328                                 err(s);
329                         } else
330                                 err(cp);
331                         gflg++;
332                         break;
333                 }
334         } else if (c == '+')
335                 dolp = strsave(cp, areanum);
336         if (flag['u'] && dolp == null) {
337                 prs("unset variable: ");
338                 err(s);
339                 gflg++;
340         }
341         e.linep = s;
342         PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
343         return(0);
344 }
345
346 /*
347  * Run the command in `...` and read its output.
348  */
349 static int
350 grave(quoted)
351 int quoted;
352 {
353         register char *cp;
354         register int i;
355         int pf[2];
356
357         for (cp = e.iop->argp->aword; *cp != '`'; cp++)
358                 if (*cp == 0) {
359                         err("no closing `");
360                         return(0);
361                 }
362         if (openpipe(pf) < 0)
363                 return(0);
364         if ((i = fork()) == -1) {
365                 closepipe(pf);
366                 err("try again");
367                 return(0);
368         }
369         if (i != 0) {
370                 e.iop->argp->aword = ++cp;
371                 close(pf[1]);
372                 PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar);
373                 return(1);
374         }
375         *cp = 0;
376         /* allow trapped signals */
377         for (i=0; i<=_NSIG; i++)
378                 if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN)
379                         signal(i, SIG_DFL);
380         dup2(pf[1], 1);
381         closepipe(pf);
382         flag['e'] = 0;
383         flag['v'] = 0;
384         flag['n'] = 0;
385         cp = strsave(e.iop->argp->aword, 0);
386         areanum = 1;
387         freehere(areanum);
388         freearea(areanum);      /* free old space */
389         e.oenv = NULL;
390         e.iop = (e.iobase = iostack) - 1;
391         unquote(cp);
392         talking = 0;
393         PUSHIO(aword, cp, nlchar);
394         onecommand();
395         exit(1);
396 }
397
398 char *
399 unquote(as)
400 register char *as;
401 {
402         register char *s;
403
404         if ((s = as) != NULL)
405                 while (*s)
406                         *s++ &= ~QUOTE;
407         return(as);
408 }
409
410 /* -------- glob.c -------- */
411 /* #include "sh.h" */
412
413 /*
414  * glob
415  */
416
417 #define scopy(x) strsave((x), areanum)
418 #define BLKSIZ  512
419 #define NDENT   ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
420
421 static  struct wdblock  *cl, *nl;
422 static  char    spcl[] = "[?*";
423
424 struct wdblock *
425 glob(cp, wb)
426 char *cp;
427 struct wdblock *wb;
428 {
429         register i;
430         register char *pp;
431
432         if (cp == 0)
433                 return(wb);
434         i = 0;
435         for (pp = cp; *pp; pp++)
436                 if (any(*pp, spcl))
437                         i++;
438                 else if (!any(*pp & ~QUOTE, spcl))
439                         *pp &= ~QUOTE;
440         if (i != 0) {
441                 for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) {
442                         nl = newword(cl->w_nword*2);
443                         for(i=0; i<cl->w_nword; i++) { /* for each argument */
444                                 for (pp = cl->w_words[i]; *pp; pp++)
445                                         if (any(*pp, spcl)) {
446                                                 globname(cl->w_words[i], pp);
447                                                 break;
448                                         }
449                                 if (*pp == '\0')
450                                         nl = addword(scopy(cl->w_words[i]), nl);
451                         }
452                         for(i=0; i<cl->w_nword; i++)
453                                 DELETE(cl->w_words[i]);
454                         DELETE(cl);
455                 }
456                 for(i=0; i<cl->w_nword; i++)
457                         unquote(cl->w_words[i]);
458                 glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
459                 if (cl->w_nword) {
460                         for (i=0; i<cl->w_nword; i++)
461                                 wb = addword(cl->w_words[i], wb);
462                         DELETE(cl);
463                         return(wb);
464                 }
465         }
466         wb = addword(unquote(cp), wb);
467         return(wb);
468 }
469
470 void
471 globname(we, pp)
472 char *we;
473 register char *pp;
474 {
475         register char *np, *cp;
476         char *name, *gp, *dp;
477         int dn, j, n, k;
478         DIR *dirp;
479         struct dirent *de;
480         char dname[NAME_MAX+1];
481         struct stat dbuf;
482
483         for (np = we; np != pp; pp--)
484                 if (pp[-1] == '/')
485                         break;
486         for (dp = cp = space((int)(pp-np)+3); np < pp;)
487                 *cp++ = *np++;
488         *cp++ = '.';
489         *cp = '\0';
490         for (gp = cp = space(strlen(pp)+1); *np && *np != '/';)
491                 *cp++ = *np++;
492         *cp = '\0';
493         dirp = opendir(dp);
494         if (dirp == 0) {
495                 DELETE(dp);
496                 DELETE(gp);
497                 return;
498         }
499         dname[NAME_MAX] = '\0';
500         while ((de=readdir(dirp))!=NULL) {
501                 /* XXX Hmmm... What this could be? (abial) */
502                 /*
503                 if (ent[j].d_ino == 0)
504                         continue;
505                 */
506                 strncpy(dname, de->d_name, NAME_MAX);
507                         if (dname[0] == '.')
508                                 if (*gp != '.')
509                                         continue;
510                         for(k=0; k<NAME_MAX; k++)
511                                 if (any(dname[k], spcl))
512                                         dname[k] |= QUOTE;
513                         if (gmatch(dname, gp)) {
514                                 name = generate(we, pp, dname, np);
515                                 if (*np && !anys(np, spcl)) {
516                                         if (stat(name,&dbuf)) {
517                                                 DELETE(name);
518                                                 continue;
519                                         }
520                                 }
521                                 nl = addword(name, nl);
522                         }
523         }
524         closedir(dirp);
525         DELETE(dp);
526         DELETE(gp);
527 }
528
529 /*
530  * generate a pathname as below.
531  * start..end1 / middle end
532  * the slashes come for free
533  */
534 static char *
535 generate(start1, end1, middle, end)
536 char *start1;
537 register char *end1;
538 char *middle, *end;
539 {
540         char *p;
541         register char *op, *xp;
542
543         p = op = space((int)(end1-start1)+strlen(middle)+strlen(end)+2);
544         for (xp = start1; xp != end1;)
545                 *op++ = *xp++;
546         for (xp = middle; (*op++ = *xp++) != '\0';)
547                 ;
548         op--;
549         for (xp = end; (*op++ = *xp++) != '\0';)
550                 ;
551         return(p);
552 }
553
554 static int
555 anyspcl(wb)
556 register struct wdblock *wb;
557 {
558         register i;
559         register char **wd;
560
561         wd = wb->w_words;
562         for (i=0; i<wb->w_nword; i++)
563                 if (anys(spcl, *wd++))
564                         return(1);
565         return(0);
566 }
567
568 static int
569 xstrcmp(p1, p2)
570 char *p1, *p2;
571 {
572         return(strcmp(*(char **)p1, *(char **)p2));
573 }
574
575 /* -------- word.c -------- */
576 /* #include "sh.h" */
577 /* #include "word.h" */
578
579 #define NSTART  16      /* default number of words to allow for initially */
580
581 struct wdblock *
582 newword(nw)
583 register int nw;
584 {
585         register struct wdblock *wb;
586
587         wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *));
588         wb->w_bsize = nw;
589         wb->w_nword = 0;
590         return(wb);
591 }
592
593 struct wdblock *
594 addword(wd, wb)
595 char *wd;
596 register struct wdblock *wb;
597 {
598         register struct wdblock *wb2;
599         register nw;
600
601         if (wb == NULL)
602                 wb = newword(NSTART);
603         if ((nw = wb->w_nword) >= wb->w_bsize) {
604                 wb2 = newword(nw * 2);
605                 memcopy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
606                 wb2->w_nword = nw;
607                 DELETE(wb);
608                 wb = wb2;
609         }
610         wb->w_words[wb->w_nword++] = wd;
611         return(wb);
612 }
613
614 char **
615 getwords(wb)
616 register struct wdblock *wb;
617 {
618         register char **wd;
619         register nb;
620
621         if (wb == NULL)
622                 return((char **)NULL);
623         if (wb->w_nword == 0) {
624                 DELETE(wb);
625                 return((char **)NULL);
626         }
627         wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
628         memcopy((char *)wd, (char *)wb->w_words, nb);
629         DELETE(wb);     /* perhaps should done by caller */
630         return(wd);
631 }
632
633 _PROTOTYPE(int (*func), (char *, char *));
634 int     globv;
635
636 void
637 glob0(a0, a1, a2, a3)
638 char *a0;
639 unsigned a1;
640 int a2;
641 _PROTOTYPE(int (*a3), (char *, char *));
642 {
643         func = a3;
644         globv = a2;
645         glob1(a0, a0 + a1 * a2);
646 }
647
648 void
649 glob1(base, lim)
650 char *base, *lim;
651 {
652         register char *i, *j;
653         int v2;
654         char *lptr, *hptr;
655         int c;
656         unsigned n;
657
658
659         v2 = globv;
660
661 top:
662         if ((n=(int)(lim-base)) <= v2)
663                 return;
664         n = v2 * (n / (2*v2));
665         hptr = lptr = base+n;
666         i = base;
667         j = lim-v2;
668         for(;;) {
669                 if (i < lptr) {
670                         if ((c = (*func)(i, lptr)) == 0) {
671                                 glob2(i, lptr -= v2);
672                                 continue;
673                         }
674                         if (c < 0) {
675                                 i += v2;
676                                 continue;
677                         }
678                 }
679
680 begin:
681                 if (j > hptr) {
682                         if ((c = (*func)(hptr, j)) == 0) {
683                                 glob2(hptr += v2, j);
684                                 goto begin;
685                         }
686                         if (c > 0) {
687                                 if (i == lptr) {
688                                         glob3(i, hptr += v2, j);
689                                         i = lptr += v2;
690                                         goto begin;
691                                 }
692                                 glob2(i, j);
693                                 j -= v2;
694                                 i += v2;
695                                 continue;
696                         }
697                         j -= v2;
698                         goto begin;
699                 }
700
701
702                 if (i == lptr) {
703                         if (lptr-base >= lim-hptr) {
704                                 glob1(hptr+v2, lim);
705                                 lim = lptr;
706                         } else {
707                                 glob1(base, lptr);
708                                 base = hptr+v2;
709                         }
710                         goto top;
711                 }
712
713
714                 glob3(j, lptr -= v2, i);
715                 j = hptr -= v2;
716         }
717 }
718
719 void
720 glob2(i, j)
721 char *i, *j;
722 {
723         register char *index1, *index2, c;
724         int m;
725
726         m = globv;
727         index1 = i;
728         index2 = j;
729         do {
730                 c = *index1;
731                 *index1++ = *index2;
732                 *index2++ = c;
733         } while(--m);
734 }
735
736 void
737 glob3(i, j, k)
738 char *i, *j, *k;
739 {
740         register char *index1, *index2, *index3;
741         int c;
742         int m;
743
744         m = globv;
745         index1 = i;
746         index2 = j;
747         index3 = k;
748         do {
749                 c = *index1;
750                 *index1++ = *index3;
751                 *index3++ = *index2;
752                 *index2++ = c;
753         } while(--m);
754 }
755
756 char *
757 memcopy(ato, from, nb)
758 register char *ato, *from;
759 register int nb;
760 {
761         register char *to;
762
763         to = ato;
764         while (--nb >= 0)
765                 *to++ = *from++;
766         return(ato);
767 }