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