From 3a903f4839911204f04b4d2777a189941c9e5c06 Mon Sep 17 00:00:00 2001 From: Tanaka Akira Date: Mon, 2 Aug 1999 16:52:12 +0000 Subject: zsh-workers:7349 --- Src/loop.c | 136 +++++++++++++++++++++++++++++---------------- Src/signals.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 256 insertions(+), 55 deletions(-) diff --git a/Src/loop.c b/Src/loop.c index 95ec4832a..3432c384f 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -44,22 +44,26 @@ int contflag; /**/ int breaks; - + /**/ int -execfor(Cmd cmd) +execfor(Cmd cmd, LinkList args, int flags) { - List list; Forcmd node; char *str; - int val = 0; - LinkList args; + zlong val = 0; node = cmd->u.forcmd; - args = cmd->args; if (node->condition) { - str = node->name; + str = dupstring(node->name); singsub(&str); + if (isset(XTRACE)) { + char *str2 = dupstring(str); + untokenize(str2); + printprompt4(); + fprintf(stderr, "%s\n", str2); + fflush(stderr); + } if (!errflag) matheval(str); if (errflag) @@ -69,11 +73,12 @@ execfor(Cmd cmd) args = newlinklist(); for (x = pparams; *x; x++) - addlinknode(args, ztrdup(*x)); + addlinknode(args, dupstring(*x)); } lastval = 0; loops++; pushheap(); + cmdpush(CS_FOR); for (;;) { if (node->condition) { str = dupstring(node->condition); @@ -81,9 +86,14 @@ execfor(Cmd cmd) if (!errflag) { while (iblank(*str)) str++; - if (*str) + if (*str) { + if (isset(XTRACE)) { + printprompt4(); + fprintf(stderr, "%s\n", str); + fflush(stderr); + } val = matheval(str); - else + } else val = 1; } if (errflag) { @@ -95,13 +105,17 @@ execfor(Cmd cmd) if (!val) break; } else { - str = (char *) ugetnode(args); - if (!str) + if (!args || !(str = (char *) ugetnode(args))) break; + if (isset(XTRACE)) { + printprompt4(); + fprintf(stderr, "%s=%s\n", node->name, str); + fflush(stderr); + } setsparam(node->name, ztrdup(str)); } - list = (List) dupstruct(node->list); - execlist(list, 1, (cmd->flags & CFLAG_EXEC) && empty(args)); + execlist(node->list, 1, + (flags & CFLAG_EXEC) && args && empty(args)); if (breaks) { breaks--; if (breaks || !contflag) @@ -110,6 +124,11 @@ execfor(Cmd cmd) } if (node->condition && !errflag) { str = dupstring(node->advance); + if (isset(XTRACE)) { + printprompt4(); + fprintf(stderr, "%s\n", str); + fflush(stderr); + } singsub(&str); if (!errflag) matheval(str); @@ -123,44 +142,49 @@ execfor(Cmd cmd) freeheap(); } popheap(); + cmdpop(); loops--; return lastval; } /**/ int -execselect(Cmd cmd) +execselect(Cmd cmd, LinkList args, int flags) { - List list; Forcmd node; char *str, *s; - LinkList args; LinkNode n; int i; FILE *inp; + size_t more; node = cmd->u.forcmd; - args = cmd->args; if (!node->inflag) { char **x; args = newlinklist(); for (x = pparams; *x; x++) - addlinknode(args, ztrdup(*x)); + addlinknode(args, dupstring(*x)); } - if (empty(args)) + if (!args || empty(args)) return 1; loops++; lastval = 0; pushheap(); + cmdpush(CS_SELECT); inp = fdopen(dup((SHTTY == -1) ? 0 : SHTTY), "r"); - selectlist(args); + more = selectlist(args, 0); for (;;) { for (;;) { if (empty(bufstack)) { if (interact && SHTTY != -1 && isset(USEZLE)) { + int oef = errflag; + isfirstln = 1; str = (char *)zleread(prompt3, NULL, 0); + if (errflag) + str = NULL; + errflag = oef; } else { str = promptexpand(prompt3, 0, NULL, NULL); zputs(str, stderr); @@ -181,7 +205,7 @@ execselect(Cmd cmd) *s = '\0'; if (*str) break; - selectlist(args); + more = selectlist(args, more); } setsparam("REPLY", ztrdup(str)); i = atoi(str); @@ -195,8 +219,7 @@ execselect(Cmd cmd) str = ""; } setsparam(node->name, ztrdup(str)); - list = (List) dupstruct(node->list); - execlist(list, 1, 0); + execlist(node->list, 1, 0); freeheap(); if (breaks) { breaks--; @@ -208,6 +231,7 @@ execselect(Cmd cmd) break; } done: + cmdpop(); popheap(); fclose(inp); loops--; @@ -217,8 +241,8 @@ execselect(Cmd cmd) /* And this is used to print select lists. */ /**/ -static void -selectlist(LinkList l) +size_t +selectlist(LinkList l, size_t start) { size_t longest = 1, fct, fw = 0, colsz, t0, t1, ct; LinkNode n; @@ -245,7 +269,7 @@ selectlist(LinkList l) else fw = (columns - 1) / fct; colsz = (ct + fct - 1) / fct; - for (t1 = 0; t1 != colsz; t1++) { + for (t1 = start; t1 != colsz && t1 - start < lines - 2; t1++) { ap = arr + t1; do { int t2 = strlen(*ap) + 2, t3; @@ -271,13 +295,14 @@ selectlist(LinkList l) } while (*ap);*/ fflush(stderr); + + return t1 < colsz ? t1 : 0; } /**/ int -execwhile(Cmd cmd) +execwhile(Cmd cmd, LinkList args, int flags) { - List list; struct whilecmd *node; int olderrexit, oldval; @@ -285,11 +310,11 @@ execwhile(Cmd cmd) node = cmd->u.whilecmd; oldval = 0; pushheap(); + cmdpush(node->cond ? CS_UNTIL : CS_WHILE); loops++; for (;;) { - list = (List) dupstruct(node->cont); noerrexit = 1; - execlist(list, 1, 0); + execlist(node->cont, 1, 0); noerrexit = olderrexit; if (!((lastval == 0) ^ node->cond)) { if (breaks) @@ -297,8 +322,7 @@ execwhile(Cmd cmd) lastval = oldval; break; } - list = (List) dupstruct(node->loop); - execlist(list, 1, 0); + execlist(node->loop, 1, 0); if (breaks) { breaks--; if (breaks || !contflag) @@ -312,6 +336,7 @@ execwhile(Cmd cmd) } oldval = lastval; } + cmdpop(); popheap(); loops--; return lastval; @@ -319,22 +344,21 @@ execwhile(Cmd cmd) /**/ int -execrepeat(Cmd cmd) +execrepeat(Cmd cmd, LinkList args, int flags) { - List list; int count; lastval = 0; - if (empty(cmd->args) || nextnode(firstnode(cmd->args))) { + if (!args || empty(args) || nextnode(firstnode(args))) { zerr("bad argument for repeat", NULL, 0); return 1; } - count = atoi(peekfirst(cmd->args)); + count = atoi(peekfirst(args)); pushheap(); + cmdpush(CS_REPEAT); loops++; while (count--) { - list = (List) dupstruct(cmd->u.list); - execlist(list, 1, 0); + execlist(cmd->u.list, 1, 0); freeheap(); if (breaks) { breaks--; @@ -347,6 +371,7 @@ execrepeat(Cmd cmd) break; } } + cmdpop(); popheap(); loops--; return lastval; @@ -354,10 +379,10 @@ execrepeat(Cmd cmd) /**/ int -execif(Cmd cmd) +execif(Cmd cmd, LinkList args, int flags) { struct ifcmd *node; - int olderrexit; + int olderrexit, s = 0; List *i, *t; olderrexit = noerrexit; @@ -368,17 +393,22 @@ execif(Cmd cmd) if (!noerrexit) noerrexit = 1; while (*i) { + cmdpush(s ? CS_ELIF : CS_IF); execlist(*i, 1, 0); + cmdpop(); if (!lastval) break; + s = 1; i++; t++; } noerrexit = olderrexit; - if (*t) - execlist(*t, 1, cmd->flags & CFLAG_EXEC); - else + if (*t) { + cmdpush(*i ? (s ? CS_ELIFTHEN : CS_IFTHEN) : CS_ELSE); + execlist(*t, 1, flags & CFLAG_EXEC); + cmdpop(); + } else lastval = 0; return lastval; @@ -386,7 +416,7 @@ execif(Cmd cmd) /**/ int -execcase(Cmd cmd) +execcase(Cmd cmd, LinkList args, int flags) { struct casecmd *node; char *word; @@ -397,25 +427,33 @@ execcase(Cmd cmd) l = node->lists; p = node->pats; - word = *p++; + word = dupstring(*p++); singsub(&word); untokenize(word); lastval = 0; if (node) { + cmdpush(CS_CASE); while (*p) { - char *pat = *p + 1; + char *pat = dupstring(*p + 1); singsub(&pat); + if (isset(XTRACE)) { + char *pat2 = dupstring(pat); + untokenize(pat2); + printprompt4(); + fprintf(stderr, "case %s (%s)\n", word, pat2); + fflush(stderr); + } if (matchpat(word, pat)) { do { - execlist(*l++, 1, **p == ';' && (cmd->flags & CFLAG_EXEC)); + execlist(*l++, 1, **p == ';' && (flags & CFLAG_EXEC)); } while(**p++ == '&' && *p); break; } p++; l++; } + cmdpop(); } return lastval; } - diff --git a/Src/signals.c b/Src/signals.c index 65bac0f52..583933f14 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -129,10 +129,9 @@ intr(void) install_handler(SIGINT); } -#if 0 /* disable ^C interrupts */ -/**/ +#if 0 /**/ void nointr(void) { @@ -505,7 +504,7 @@ handler(int sig) #ifdef SIGWINCH case SIGWINCH: - adjustwinsize(); /* check window size and adjust */ + adjustwinsize(1); /* check window size and adjust */ if (sigtrapped[SIGWINCH]) dotrap(SIGWINCH); break; @@ -587,7 +586,10 @@ killjb(Job jn, int sig) for (pn = jn->procs; pn->next; pn = pn->next) err = kill(pn->pid, sig); - + + if (!jobtab[jn->other].procs && pn) + err = kill(pn->pid, sig); + return err; } @@ -603,6 +605,61 @@ killjb(Job jn, int sig) return err; } +/* + * List for saving traps. We don't usually have that many traps + * at once, so just use a linked list. + */ +struct savetrap { + int sig, flags, local; + void *list; +}; + +static LinkList savetraps; + +/* Flag to unsettrap not to free the structs, which we're keeping */ + +/**/ +int notrapfree; + +/* + * Save the current trap and unset it. + */ + +static void +dosavetrap(int sig, int level) +{ + struct savetrap *st; + st = (struct savetrap *)zalloc(sizeof(*st)); + st->sig = sig; + st->local = level; + notrapfree++; + if ((st->flags = sigtrapped[sig]) & ZSIG_FUNC) { + /* + * Get the old function: this assumes we haven't added + * the new one yet. + */ + char func[20]; + sprintf(func, "TRAP%s", sigs[sig]); + /* We call removehashnode() directly because otherwise + * removeshfuncnode() would be called which in turn would + * call us again so that we would end up with a NULL pointer + * instead of the list for the trap. */ + st->list = removehashnode(shfunctab, func); + } else { + st->list = sigfuncs[sig]; + unsettrap(sig); + } + notrapfree--; + PERMALLOC { + if (!savetraps) + savetraps = newlinklist(); + /* + * Put this at the front of the list + */ + insertlinknode(savetraps, (LinkNode)savetraps, st); + } LASTALLOC; +} + /**/ int settrap(int sig, List l) @@ -613,7 +670,15 @@ settrap(int sig, List l) zerr("can't trap SIG%s in interactive shells", sigs[sig], 0); return 1; } - if (sigfuncs[sig]) + /* + * Note that we save the trap here even if there isn't an existing + * one, to aid in removing this one. However, if there's + * already one at the current locallevel we just overwrite it. + */ + if (isset(LOCALTRAPS) && locallevel && + (!sigtrapped[sig] || locallevel > (sigtrapped[sig] >> ZSIG_SHIFT))) { + dosavetrap(sig, locallevel); + } else if (sigfuncs[sig]) unsettrap(sig); sigfuncs[sig] = l; if (!l) { @@ -633,6 +698,12 @@ settrap(int sig, List l) sig != SIGCHLD) install_handler(sig); } + /* + * Note that introducing the locallevel does not affect whether + * sigtrapped[sig] is zero or not, i.e. a test without a mask + * works just the same. + */ + sigtrapped[sig] |= (locallevel << ZSIG_SHIFT); return 0; } @@ -646,6 +717,19 @@ unsettrap(int sig) (jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN))) { return; } + if (isset(LOCALTRAPS) && locallevel && + sigtrapped[sig] && locallevel > (sigtrapped[sig] >> ZSIG_SHIFT)) { + /* + * This calls unsettrap recursively to do any dirty work, so + * make sure this bit doesn't happen: a bit messy, but hard + * to avoid. + */ + int oldlt = opts[LOCALTRAPS]; + opts[LOCALTRAPS] = 0; + dosavetrap(sig, locallevel); + opts[LOCALTRAPS] = oldlt; + return; + } sigtrapped[sig] = 0; if (sig == SIGINT && interact) { /* PWS 1995/05/16: added test for interactive, also noholdintr() * @@ -660,6 +744,8 @@ unsettrap(int sig) #endif sig != SIGCHLD) signal_default(sig); + if (notrapfree) + return; if (trapped & ZSIG_FUNC) { char func[20]; HashNode hn; @@ -673,6 +759,83 @@ unsettrap(int sig) } } +/**/ +void +starttrapscope(void) +{ + /* + * SIGEXIT needs to be restored at the current locallevel, + * so give it the next higher one. + */ + if (sigtrapped[SIGEXIT]) + dosavetrap(SIGEXIT, locallevel+1); +} + +/* + * Reset traps after the end of a function: must be called after + * endparamscope() so that the locallevel has been decremented. + */ + +/**/ +void +endtrapscope(void) +{ + LinkNode ln; + struct savetrap *st; + int exittr; + void *exitfn = NULL; + + /* + * Remember the exit trap, but don't run it until + * after all the other traps have been put back. + */ + if ((exittr = sigtrapped[SIGEXIT])) { + notrapfree++; + if (exittr & ZSIG_FUNC) { + exitfn = shfunctab->removenode(shfunctab, "TRAPEXIT"); + } else { + exitfn = sigfuncs[SIGEXIT]; + unsettrap(SIGEXIT); + } + notrapfree--; + } + + if (savetraps) { + while ((ln = firstnode(savetraps)) && + (st = (struct savetrap *) ln->dat) && + st->local > locallevel) { + int sig = st->sig; + + remnode(savetraps, ln); + + if (sigtrapped[sig]) + unsettrap(sig); + if (st->flags) { + List list = (st->flags & ZSIG_FUNC) ? + ((Shfunc) st->list)->funcdef : (List) st->list; + /* prevent settrap from saving this */ + int oldlt = opts[LOCALTRAPS]; + opts[LOCALTRAPS] = 0; + settrap(sig, list); + opts[LOCALTRAPS] = oldlt; + if ((sigtrapped[sig] = st->flags) & ZSIG_FUNC) + shfunctab->addnode(shfunctab, ((Shfunc)st->list)->nam, + (Shfunc) st->list); + } + zfree(st, sizeof(*st)); + } + } + + if (exittr) { + dotrapargs(SIGEXIT, &exittr, (exittr & ZSIG_FUNC) ? + ((Shfunc)exitfn)->funcdef : (List) exitfn); + if (exittr & ZSIG_FUNC) + shfunctab->freenode((HashNode)exitfn); + else + freestruct(exitfn); + } +} + /* Execute a trap function for a given signal, possibly * with non-standard sigtrapped & sigfuncs values */ @@ -720,7 +883,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn) freelinklist(args, (FreeFunc) NULL); zsfree(name); } else HEAPALLOC { - execlist(dupstruct(sigfn), 1, 0); + execlist(sigfn, 1, 0); } LASTALLOC; if (trapreturn > 0) trapret = trapreturn; -- cgit 1.4.1