libxml2: copy the xml2-config to the crosstoolsdir and patch the paths in the native...
[AROS-Contrib.git] / gnu / abc-shell / c_sh.c
blob581806c3caa732071848cbe8a9c8136608529333
1 /*
2 * built-in Bourne commands
3 */
5 #include <sys/stat.h>
6 #include "sh.h"
7 #include "ksh_time.h"
8 #include "ksh_times.h"
10 static char * clocktos(int);
11 #if 0 /* not used at the moment */
12 static void p_time(struct shf *, int, struct timeval *, int, char *, char *);
13 #endif /* not used at the moment */
15 /* :, false and true */
16 int
17 c_label(char **wp)
19 return wp[0][0] == 'f' ? 1 : 0;
22 int
23 c_shift(char **wp)
25 struct block *l = e->loc;
26 int n;
27 long val;
28 char *arg;
30 if (ksh_getopt(wp, &builtin_opt, null) == '?')
31 return 1;
32 arg = wp[builtin_opt.optind];
34 if (arg) {
35 evaluate(arg, &val, KSH_UNWIND_ERROR, false);
36 n = val;
37 } else
38 n = 1;
39 if (n < 0) {
40 bi_errorf("%s: bad number", arg);
41 return (1);
43 if (l->argc < n) {
44 bi_errorf("nothing to shift");
45 return (1);
47 l->argv[n] = l->argv[0];
48 l->argv += n;
49 l->argc -= n;
50 return 0;
53 int
54 c_umask(char **wp)
56 int i;
57 char *cp;
58 int symbolic = 0;
59 mode_t old_umask;
60 int optc;
62 while ((optc = ksh_getopt(wp, &builtin_opt, "S")) != -1)
63 switch (optc) {
64 case 'S':
65 symbolic = 1;
66 break;
67 case '?':
68 return 1;
70 cp = wp[builtin_opt.optind];
71 if (cp == NULL) {
72 old_umask = umask(0);
73 umask(old_umask);
74 if (symbolic) {
75 char buf[18];
76 int j;
78 old_umask = ~old_umask;
79 cp = buf;
80 for (i = 0; i < 3; i++) {
81 *cp++ = "ugo"[i];
82 *cp++ = '=';
83 for (j = 0; j < 3; j++)
84 if (old_umask & (1 << (8 - (3*i + j))))
85 *cp++ = "rwx"[j];
86 *cp++ = ',';
88 cp[-1] = '\0';
89 shprintf("%s\n", buf);
90 } else
91 shprintf("%#3.3o\n", old_umask);
92 } else {
93 mode_t new_umask;
95 if (digit(*cp)) {
96 for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++)
97 new_umask = new_umask * 8 + (*cp - '0');
98 if (*cp) {
99 bi_errorf("bad number");
100 return 1;
102 } else {
103 /* symbolic format */
104 int positions, new_val;
105 char op;
107 old_umask = umask(0);
108 umask(old_umask); /* in case of error */
109 old_umask = ~old_umask;
110 new_umask = old_umask;
111 positions = 0;
112 while (*cp) {
113 while (*cp && strchr("augo", *cp))
114 switch (*cp++) {
115 case 'a':
116 positions |= 0111;
117 break;
118 case 'u':
119 positions |= 0100;
120 break;
121 case 'g':
122 positions |= 0010;
123 break;
124 case 'o':
125 positions |= 0001;
126 break;
128 if (!positions)
129 positions = 0111; /* default is a */
130 if (!strchr("=+-", op = *cp))
131 break;
132 cp++;
133 new_val = 0;
134 while (*cp && strchr("rwxugoXs", *cp))
135 switch (*cp++) {
136 case 'r':
137 new_val |= 04;
138 break;
139 case 'w':
140 new_val |= 02;
141 break;
142 case 'x':
143 new_val |= 01;
144 break;
145 case 'u':
146 new_val |= old_umask >> 6;
147 break;
148 case 'g':
149 new_val |= old_umask >> 3;
150 break;
151 case 'o':
152 new_val |= old_umask >> 0;
153 break;
154 case 'X':
155 if (old_umask & 0111)
156 new_val |= 01;
157 break;
158 case 's': /* ignored */
159 break;
161 new_val = (new_val & 07) * positions;
162 switch (op) {
163 case '-':
164 new_umask &= ~new_val;
165 break;
166 case '=':
167 new_umask = new_val |
168 (new_umask & ~(positions * 07));
169 break;
170 case '+':
171 new_umask |= new_val;
173 if (*cp == ',') {
174 positions = 0;
175 cp++;
176 } else if (!strchr("=+-", *cp))
177 break;
179 if (*cp) {
180 bi_errorf("bad mask");
181 return 1;
183 new_umask = ~new_umask;
185 umask(new_umask);
187 return 0;
191 c_dot(char **wp)
193 char *file, *cp;
194 char **argv;
195 int argc;
196 int i;
197 int err;
199 if (ksh_getopt(wp, &builtin_opt, null) == '?')
200 return 1;
202 if ((cp = wp[builtin_opt.optind]) == NULL)
203 return 0;
204 file = search(cp, path, R_OK, &err);
205 if (file == NULL) {
206 bi_errorf("%s: %s", cp, err ? strerror(err) : "not found");
207 return 1;
210 /* Set positional parameters? */
211 if (wp[builtin_opt.optind + 1]) {
212 argv = wp + builtin_opt.optind;
213 argv[0] = e->loc->argv[0]; /* preserve $0 */
214 for (argc = 0; argv[argc + 1]; argc++)
216 } else {
217 argc = 0;
218 argv = (char **) 0;
220 i = include(file, argc, argv, 0);
221 if (i < 0) { /* should not happen */
222 bi_errorf("%s: %s", cp, strerror(errno));
223 return 1;
225 return i;
229 c_wait(char **wp)
231 int rv = 0;
232 int sig;
234 if (ksh_getopt(wp, &builtin_opt, null) == '?')
235 return 1;
236 wp += builtin_opt.optind;
237 if (*wp == (char *) 0) {
238 while (waitfor((char *) 0, &sig) >= 0)
240 rv = sig;
241 } else {
242 for (; *wp; wp++)
243 rv = waitfor(*wp, &sig);
244 if (rv < 0)
245 rv = sig ? sig : 127; /* magic exit code: bad job-id */
247 return rv;
251 c_read(char **wp)
253 int c = 0;
254 int expand = 1, history = 0;
255 int expanding;
256 int ecode = 0;
257 char *cp;
258 int fd = 0;
259 #ifndef NEWLIB
260 struct shf *shf;
261 #endif
262 int optc;
263 const char *emsg;
264 XString cs, xs;
265 struct tbl *vp;
266 char *xp = NULL;
268 while ((optc = ksh_getopt(wp, &builtin_opt, "prsu,")) != -1)
269 switch (optc) {
270 case 'p':
271 if ((fd = coproc_getfd(R_OK, &emsg)) < 0) {
272 bi_errorf("-p: %s", emsg);
273 return 1;
275 break;
276 case 'r':
277 expand = 0;
278 break;
279 case 's':
280 history = 1;
281 break;
282 case 'u':
283 if (!*(cp = builtin_opt.optarg))
284 fd = 0;
285 else if ((fd = check_fd(cp, R_OK, &emsg)) < 0) {
286 bi_errorf("-u: %s: %s", cp, emsg);
287 return 1;
289 break;
290 case '?':
291 return 1;
293 wp += builtin_opt.optind;
295 if (*wp == NULL)
296 *--wp = strdup("REPLY");
298 /* Since we can't necessarily seek backwards on non-regular files,
299 * don't buffer them so we can't read too much.
301 shf = shf_reopen(fd, SHF_RD | SHF_INTERRUPT | can_seek(fd), shl_spare);
303 if ((cp = strchr(*wp, '?')) != NULL) {
304 *cp = 0;
305 if (isatty(fd)) {
306 /* at&t ksh says it prints prompt on fd if it's open
307 * for writing and is a tty, but it doesn't do it
308 * (it also doesn't check the interactive flag,
309 * as is indicated in the Kornshell book).
311 shellf("%s", cp+1);
315 /* If we are reading from the co-process for the first time,
316 * make sure the other side of the pipe is closed first. This allows
317 * the detection of eof.
319 * This is not compatiable with at&t ksh... the fd is kept so another
320 * coproc can be started with same ouput, however, this means eof
321 * can't be detected... This is why it is closed here.
322 * If this call is removed, remove the eof check below, too.
323 * coproc_readw_close(fd);
326 if (history)
327 Xinit(xs, xp, 128, ATEMP);
328 expanding = 0;
329 Xinit(cs, cp, 128, ATEMP);
330 for (; *wp != NULL; wp++) {
331 for (cp = Xstring(cs, cp); ; ) {
332 if (c == '\n' || c == EOF)
333 break;
334 while (1) {
335 c = shf_getc(shf);
336 if (c == '\0')
337 continue;
338 if (c == EOF && shf_error(shf) &&
339 shf_errno(shf) == EINTR)
341 /* Was the offending signal one that
342 * would normally kill a process?
343 * If so, pretend the read was killed.
345 ecode = fatal_trap_check();
347 /* non fatal (eg, CHLD), carry on */
348 if (!ecode) {
349 shf_clearerr(shf);
350 continue;
353 break;
355 if (history) {
356 Xcheck(xs, xp);
357 Xput(xs, xp, c);
359 Xcheck(cs, cp);
360 if (expanding) {
361 expanding = 0;
362 if (c == '\n') {
363 c = 0;
364 if (Flag(FTALKING_I) && isatty(fd)) {
365 set_prompt(PS2, (Source *) 0);
366 pprompt(prompt, 0);
368 } else if (c != EOF)
369 Xput(cs, cp, c);
370 continue;
372 if (expand && c == '\\') {
373 expanding = 1;
374 continue;
376 if (c == '\n' || c == EOF)
377 break;
378 if (ctype(c, C_IFS)) {
379 if (Xlength(cs, cp) == 0 && ctype(c, C_IFSWS))
380 continue;
381 if (wp[1])
382 break;
384 Xput(cs, cp, c);
386 /* strip trailing IFS white space from last variable */
387 if (!wp[1])
388 while (Xlength(cs, cp) && ctype(cp[-1], C_IFS) &&
389 ctype(cp[-1], C_IFSWS))
390 cp--;
391 Xput(cs, cp, '\0');
392 vp = global(*wp);
393 /* Must be done before setting export. */
394 if (vp->flag & RDONLY) {
395 shf_flush(shf);
396 bi_errorf("%s is read only", *wp);
397 return 1;
399 if (Flag(FEXPORT))
400 typeset(*wp, EXPORTV, 0, 0, 0);
401 if (!setstr(vp, Xstring(cs, cp), KSH_RETURN_ERROR)) {
402 shf_flush(shf);
403 return 1;
407 shf_flush(shf);
408 if (history) {
409 Xput(xs, xp, '\0');
410 source->line++;
411 histsave(source->line, Xstring(xs, xp), 1);
412 Xfree(xs, xp);
414 /* if this is the co-process fd, close the file descriptor
415 * (can get eof if and only if all processes are have died, ie,
416 * coproc.njobs is 0 and the pipe is closed).
418 if (c == EOF && !ecode)
419 coproc_read_close(fd);
421 return ecode ? ecode : c == EOF;
425 c_eval(char **wp)
427 struct source *s;
428 int rv;
430 if (ksh_getopt(wp, &builtin_opt, null) == '?')
431 return 1;
432 s = pushs(SWORDS, ATEMP);
433 s->u.strv = wp + builtin_opt.optind;
434 if (!Flag(FPOSIX)) {
436 * Handle case where the command is empty due to failed
437 * command substitution, eg, eval "$(false)".
438 * In this case, shell() will not set/change exstat (because
439 * compiled tree is empty), so will use this value.
440 * subst_exstat is cleared in execute(), so should be 0 if
441 * there were no substitutions.
443 * A strict reading of POSIX says we don't do this (though
444 * it is traditionally done). [from 1003.2-1992]
445 * 3.9.1: Simple Commands
446 * ... If there is a command name, execution shall
447 * continue as described in 3.9.1.1. If there
448 * is no command name, but the command contained a command
449 * substitution, the command shall complete with the exit
450 * status of the last command substitution
451 * 3.9.1.1: Command Search and Execution
452 * ...(1)...(a) If the command name matches the name of
453 * a special built-in utility, that special built-in
454 * utility shall be invoked.
455 * 3.14.5: Eval
456 * ... If there are no arguments, or only null arguments,
457 * eval shall return an exit status of zero.
459 exstat = subst_exstat;
462 rv = shell(s, false);
463 afree(s, ATEMP);
464 return (rv);
468 c_trap(char **wp)
470 int i;
471 char *s;
472 Trap *p;
474 if (ksh_getopt(wp, &builtin_opt, null) == '?')
475 return 1;
476 wp += builtin_opt.optind;
478 if (*wp == NULL) {
479 int anydfl = 0;
481 for (p = sigtraps, i = NSIG+1; --i >= 0; p++) {
482 if (p->trap == NULL)
483 anydfl = 1;
484 else {
485 shprintf("trap -- ");
486 print_value_quoted(p->trap);
487 shprintf(" %s\n", p->name);
490 #if 0 /* this is ugly and not clear POSIX needs it */
491 /* POSIX may need this so output of trap can be saved and
492 * used to restore trap conditions
494 if (anydfl) {
495 shprintf("trap -- -");
496 for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
497 if (p->trap == NULL && p->name)
498 shprintf(" %s", p->name);
499 shprintf(newline);
501 #else
502 (void)anydfl; // Unused
503 #endif
504 return 0;
508 * Use case sensitive lookup for first arg so the
509 * command 'exit' isn't confused with the pseudo-signal
510 * 'EXIT'.
512 s = (gettrap(*wp, false) == NULL) ? *wp++ : NULL; /* get command */
513 if (s != NULL && s[0] == '-' && s[1] == '\0')
514 s = NULL;
516 /* set/clear traps */
517 while (*wp != NULL) {
518 p = gettrap(*wp++, true);
519 if (p == NULL) {
520 bi_errorf("bad signal %s", wp[-1]);
521 return 1;
523 settrap(p, s);
525 return 0;
529 c_exitreturn(char **wp)
531 int how = LEXIT;
532 int n;
533 char *arg;
535 if (ksh_getopt(wp, &builtin_opt, null) == '?')
536 return 1;
537 arg = wp[builtin_opt.optind];
539 if (arg) {
540 if (!getn(arg, &n)) {
541 exstat = 1;
542 warningf(true, "%s: bad number", arg);
543 } else
544 exstat = n;
546 if (wp[0][0] == 'r') { /* return */
547 struct env *ep;
549 /* need to tell if this is exit or return so trap exit will
550 * work right (POSIX)
552 for (ep = e; ep; ep = ep->oenv)
553 if (STOP_RETURN(ep->type)) {
554 how = LRETURN;
555 break;
559 if (how == LEXIT && !really_exit && j_stopped_running()) {
560 really_exit = 1;
561 how = LSHELL;
564 quitenv(NULL); /* get rid of any i/o redirections */
565 unwind(how);
566 /*NOTREACHED*/
567 return 0;
571 c_brkcont(char **wp)
573 int n, quit;
574 struct env *ep, *last_ep = (struct env *) 0;
575 char *arg;
577 if (ksh_getopt(wp, &builtin_opt, null) == '?')
578 return 1;
579 arg = wp[builtin_opt.optind];
581 if (!arg)
582 n = 1;
583 else if (!bi_getn(arg, &n))
584 return 1;
585 quit = n;
586 if (quit <= 0) {
587 /* at&t ksh does this for non-interactive shells only - weird */
588 bi_errorf("%s: bad value", arg);
589 return 1;
592 /* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */
593 for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv)
594 if (ep->type == E_LOOP) {
595 if (--quit == 0)
596 break;
597 ep->flags |= EF_BRKCONT_PASS;
598 last_ep = ep;
601 if (quit) {
602 /* at&t ksh doesn't print a message - just does what it
603 * can. We print a message 'cause it helps in debugging
604 * scripts, but don't generate an error (ie, keep going).
606 if (n == quit) {
607 warningf(true, "%s: cannot %s", wp[0], wp[0]);
608 return 0;
610 /* POSIX says if n is too big, the last enclosing loop
611 * shall be used. Doesn't say to print an error but we
612 * do anyway 'cause the user messed up.
614 if (last_ep)
615 last_ep->flags &= ~EF_BRKCONT_PASS;
616 warningf(true, "%s: can only %s %d level(s)",
617 wp[0], wp[0], n - quit);
620 unwind(*wp[0] == 'b' ? LBREAK : LCONTIN);
621 /*NOTREACHED*/
625 c_set(char **wp)
627 int argi, setargs;
628 struct block *l = e->loc;
629 char **owp = wp;
631 if (wp[1] == NULL) {
632 static const char *const args [] = { "set", "-", NULL };
633 return c_typeset((char **) args);
636 argi = parse_args(wp, OF_SET, &setargs);
637 if (argi < 0)
638 return 1;
639 /* set $# and $* */
640 if (setargs) {
641 owp = wp += argi - 1;
642 wp[0] = l->argv[0]; /* save $0 */
643 while (*++wp != NULL)
644 *wp = str_save(*wp, &l->area);
645 l->argc = wp - owp - 1;
646 l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area);
647 for (wp = l->argv; (*wp++ = *owp++) != NULL; )
650 /* POSIX says set exit status is 0, but old scripts that use
651 * getopt(1), use the construct: set -- `getopt ab:c "$@"`
652 * which assumes the exit value set will be that of the ``
653 * (subst_exstat is cleared in execute() so that it will be 0
654 * if there are no command substitutions).
656 return Flag(FPOSIX) ? 0 : subst_exstat;
660 c_unset(char **wp)
662 char *id;
663 int optc, unset_var = 1;
665 while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != -1)
666 switch (optc) {
667 case 'f':
668 unset_var = 0;
669 break;
670 case 'v':
671 unset_var = 1;
672 break;
673 case '?':
674 return 1;
676 wp += builtin_opt.optind;
677 for (; (id = *wp) != NULL; wp++)
678 if (unset_var) { /* unset variable */
679 struct tbl *vp = global(id);
681 if ((vp->flag&RDONLY)) {
682 bi_errorf("%s is read only", vp->name);
683 return 1;
685 unset(vp, strchr(id, '[') ? 1 : 0);
686 } else { /* unset function */
687 define(id, (struct op *) NULL);
689 return 0;
692 #if 0 /* not used at the moment */
693 static void
694 p_time(struct shf *shf, int posix, struct timeval *tv, int width, char *prefix,
695 char *suffix)
697 if (posix)
698 shf_fprintf(shf, "%s%*ld.%02ld%s", prefix ? prefix : "",
699 width, tv->tv_sec, tv->tv_usec / 10000, suffix);
700 else
701 shf_fprintf(shf, "%s%*ldm%ld.%02lds%s", prefix ? prefix : "",
702 width, tv->tv_sec / 60, tv->tv_sec % 60,
703 tv->tv_usec / 10000, suffix);
705 #endif /* not used at the moment */
708 c_times(char **wp)
710 struct tms all;
712 (void) ksh_times(&all);
713 shprintf("Shell: %8ss user ", clocktos(all.tms_utime));
714 shprintf("%8ss system\n", clocktos(all.tms_stime));
715 shprintf("Kids: %8ss user ", clocktos(all.tms_cutime));
716 shprintf("%8ss system\n", clocktos(all.tms_cstime));
718 return 0;
722 * time pipeline (really a statement, not a built-in command)
725 timex(struct op *t, int f)
727 #define TF_NOARGS BIT(0)
728 #define TF_NOREAL BIT(1) /* don't report real time */
729 #define TF_POSIX BIT(2) /* report in posix format */
730 int rv = 0;
731 struct tms t0, t1, tms;
732 INT32 t0t, t1t = 0;
733 int tf = 0;
734 extern INT32 j_usrtime, j_systime; /* computed by j_wait */
735 char opts[1];
737 t0t = ksh_times(&t0);
738 if (t->left) {
740 * Two ways of getting cpu usage of a command: just use t0
741 * and t1 (which will get cpu usage from other jobs that
742 * finish while we are executing t->left), or get the
743 * cpu usage of t->left. at&t ksh does the former, while
744 * pdksh tries to do the later (the j_usrtime hack doesn't
745 * really work as it only counts the last job).
747 j_usrtime = j_systime = 0;
748 if (t->left->type == TCOM)
749 t->left->str = opts;
750 opts[0] = 0;
751 rv = execute(t->left, f | XTIME);
752 tf |= opts[0];
753 t1t = ksh_times(&t1);
754 } else
755 tf = TF_NOARGS;
757 if (tf & TF_NOARGS) { /* ksh93 - report shell times (shell+kids) */
758 tf |= TF_NOREAL;
759 tms.tms_utime = t0.tms_utime + t0.tms_cutime;
760 tms.tms_stime = t0.tms_stime + t0.tms_cstime;
761 } else {
762 tms.tms_utime = t1.tms_utime - t0.tms_utime + j_usrtime;
763 tms.tms_stime = t1.tms_stime - t0.tms_stime + j_systime;
766 if (!(tf & TF_NOREAL))
767 shf_fprintf(shl_out,
768 tf & TF_POSIX ? "real %8s\n" : "%8ss real ",
769 clocktos(t1t - t0t));
770 shf_fprintf(shl_out, tf & TF_POSIX ? "user %8s\n" : "%8ss user ",
771 clocktos(tms.tms_utime));
772 shf_fprintf(shl_out, tf & TF_POSIX ? "sys %8s\n" : "%8ss system\n",
773 clocktos(tms.tms_stime));
774 shf_flush(shl_out);
776 return rv;
779 void
780 timex_hook(struct op *t, char **volatile *app)
782 char **wp = *app;
783 int optc;
784 int i, j;
785 Getopt opt;
787 ksh_getopt_reset(&opt, 0);
788 opt.optind = 0; /* start at the start */
789 while ((optc = ksh_getopt(wp, &opt, ":p")) != -1)
790 switch (optc) {
791 case 'p':
792 t->str[0] |= TF_POSIX;
793 break;
794 case '?':
795 errorf("time: -%s unknown option", opt.optarg);
796 case ':':
797 errorf("time: -%s requires an argument",
798 opt.optarg);
800 /* Copy command words down over options. */
801 if (opt.optind != 0) {
802 for (i = 0; i < opt.optind; i++)
803 afree(wp[i], ATEMP);
804 for (i = 0, j = opt.optind; (wp[i] = wp[j]); i++, j++)
807 if (!wp[0])
808 t->str[0] |= TF_NOARGS;
809 *app = wp;
812 static char *
813 clocktos(int t)
815 static char temp[22]; /* enough for 64 bit INT32 */
816 int i;
817 char *cp = temp + sizeof(temp);
819 /* note: posix says must use max precision, ie, if clk_tck is
820 * 1000, must print 3 places after decimal (if non-zero, else 1).
822 if (CLK_TCK != 100) /* convert to 1/100'ths */
823 t = (t < 1000000000/CLK_TCK) ?
824 (t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
826 *--cp = '\0';
827 for (i = -2; i <= 0 || t > 0; i++) {
828 if (i == 0)
829 *--cp = '.';
830 *--cp = '0' + (char)(t%10);
831 t /= 10;
833 return cp;
836 /* exec with no args - args case is taken care of in comexec() */
838 c_exec(char ** wp)
840 int i;
842 /* make sure redirects stay in place */
843 if (e->savefd != NULL) {
844 for (i = 0; i < NUFILE; i++) {
845 if (e->savefd[i] > 0)
846 close(e->savefd[i]);
847 #if !defined __amigaos4__ && !defined __AROS__
849 * For ksh keep anything > 2 private,
850 * for sh, let them be (POSIX says what
851 * happens is unspecified and the bourne shell
852 * keeps them open).
854 if (!Flag(FSH) && i > 2 && e->savefd[i])
855 fcntl(i, F_SETFD, FD_CLOEXEC);
856 #endif
858 e->savefd = NULL;
860 return 0;
863 /* dummy function, special case in comexec() */
865 c_builtin(char ** wp)
867 return 0;
870 extern int c_test(char **wp); /* in c_test.c */
871 extern int c_ulimit(char **wp); /* in c_ulimit.c */
873 /* A leading = means assignments before command are kept;
874 * a leading * means a POSIX special builtin;
875 * a leading + means a POSIX regular builtin
876 * (* and + should not be combined).
878 const struct builtin shbuiltins [] = {
879 {"*=.", c_dot},
880 {"*=:", c_label},
881 {"[", c_test},
882 {"*=break", c_brkcont},
883 {"=builtin", c_builtin},
884 {"*=continue", c_brkcont},
885 {"*=eval", c_eval},
886 {"*=exec", c_exec},
887 {"*=exit", c_exitreturn},
888 {"+false", c_label},
889 {"*=return", c_exitreturn},
890 {"*=set", c_set},
891 {"*=shift", c_shift},
892 {"=times", c_times},
893 {"*=trap", c_trap},
894 {"+=wait", c_wait},
895 {"+read", c_read},
896 {"test", c_test},
897 {"+true", c_label},
898 {"+umask", c_umask},
899 {"*=unset", c_unset},
900 {NULL, NULL}