mod_export void iremovesuffix(ZLE_INT_T c, int keep) { if (suffixfunc) { Shfunc shfunc = getshfunc(suffixfunc); if (shfunc) { LinkList args = newlinklist(); char buf[20]; int osc = sfcontext; int wasmeta = (zlemetaline != 0); if (wasmeta) { /* * The suffix removal function runs as a normal * ZLE function, not a completion function, so * the line should be unmetafied if this was * called from completion. (It may not be since * we may decide to remove the suffix later.) */ unmetafy_line(); } sprintf(buf, "%d", suffixfunclen); addlinknode(args, suffixfunc); addlinknode(args, buf); startparamscope(); makezleparams(0); sfcontext = SFC_COMPLETE; doshfunc(shfunc, args, 1); sfcontext = osc; endparamscope(); if (wasmeta) metafy_line(); } zsfree(suffixfunc); suffixfunc = NULL; } else { int sl = 0, flags = 0; struct suffixset *ss; if (c == NO_INSERT_CHAR) { sl = suffixnoinsrem ? suffixlen : 0; } else { ZLE_CHAR_T ch = c; /* * Search for a match for ch in the suffix list. * We stop if we encounter a match in a positive or negative * list, using the suffix length specified or zero respectively. * If we reached the end and passed through a negative * list, we use the suffix length for that, else zero. * This would break if it were possible to have negative * sets with different suffix length: that's not supposed * to happen. */ int negsuflen = 0, found = 0; for (ss = suffixlist; ss; ss = ss->next) { switch (ss->tp) { case SUFTYP_POSSTR: if (ZS_memchr(ss->chars, ch, ss->lenstr)) { sl = ss->lensuf; found = 1; } break; case SUFTYP_NEGSTR: if (ZS_memchr(ss->chars, ch, ss->lenstr)) { sl = 0; found = 1; } else { negsuflen = ss->lensuf; } break; case SUFTYP_POSRNG: if (ss->chars[0] <= ch && ch <= ss->chars[1]) { sl = ss->lensuf; found = 1; } break; case SUFTYP_NEGRNG: if (ss->chars[0] <= ch && ch <= ss->chars[1]) { sl = 0; found = 1; } else { negsuflen = ss->lensuf; } break; } if (found) { flags = ss->flags; break; } } if (!found) sl = negsuflen; } if (sl) { /* must be shifting wide character lengths */ backdel(sl, CUT_RAW); if (flags & SUFFLAGS_SPACE) { /* Add a space and advance over it */ spaceinline(1); if (zlemetaline) { zlemetaline[zlemetacs++] = ' '; } else { zleline[zlecs++] = ZWC(' '); } } if (!keep) invalidatelist(); } } fixsuffix(); }
enum loop_return loop(int toplevel, int justonce) { Eprog prog; int err, non_empty = 0; queue_signals(); pushheap(); if (!toplevel) zcontext_save(); for (;;) { freeheap(); if (stophist == 3) /* re-entry via preprompt() */ hend(NULL); hbegin(1); /* init history mech */ if (isset(SHINSTDIN)) { setblock_stdin(); if (interact && toplevel) { int hstop = stophist; stophist = 3; /* * Reset all errors including the interrupt error status * immediately, so preprompt runs regardless of what * just happened. We'll reset again below as a * precaution to ensure we get back to the command line * no matter what. */ errflag = 0; preprompt(); if (stophist != 3) hbegin(1); else stophist = hstop; /* * Reset all errors, including user interupts. * This is what allows ^C in an interactive shell * to return us to the command line. */ errflag = 0; } } use_exit_printed = 0; intr(); /* interrupts on */ lexinit(); /* initialize lexical state */ if (!(prog = parse_event(ENDINPUT))) { /* if we couldn't parse a list */ hend(NULL); if ((tok == ENDINPUT && !errflag) || (tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) || justonce) break; if (exit_pending) { /* * Something down there (a ZLE function?) decided * to exit when there was stuff to clear up. * Handle that now. */ stopmsg = 1; zexit(exit_pending >> 1, 0); } if (tok == LEXERR && !lastval) lastval = 1; continue; } if (hend(prog)) { enum lextok toksav = tok; non_empty = 1; if (toplevel && (getshfunc("preexec") || paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) { LinkList args; char *cmdstr; /* * As we're about to freeheap() or popheap() * anyway, there's no gain in using permanent * storage here. */ args = newlinklist(); addlinknode(args, "preexec"); /* If curline got dumped from the history, we don't know * what the user typed. */ if (hist_ring && curline.histnum == curhist) addlinknode(args, hist_ring->node.nam); else addlinknode(args, ""); addlinknode(args, dupstring(getjobtext(prog, NULL))); addlinknode(args, cmdstr = getpermtext(prog, NULL, 0)); callhookfunc("preexec", args, 1, NULL); /* The only permanent storage is from getpermtext() */ zsfree(cmdstr); /* * Note this does *not* remove a user interrupt error * condition, even though we're at the top level loop: * that would be inconsistent with the case where * we didn't execute a preexec function. This is * an implementation detail that an interrupting user * does't care about. */ errflag &= ~ERRFLAG_ERROR; } if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; execode(prog, 0, 0, toplevel ? "toplevel" : "file"); tok = toksav; if (toplevel) noexitct = 0; } if (ferror(stderr)) { zerr("write error"); clearerr(stderr); } if (subsh) /* how'd we get this far in a subshell? */ exit(lastval); if (((!interact || sourcelevel) && errflag) || retflag) break; if (isset(SINGLECOMMAND) && toplevel) { dont_queue_signals(); if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); exit(lastval); } if (justonce) break; }
void loop(int toplevel, int justonce) { List list; #ifdef DEBUG int oasp = toplevel ? 0 : alloc_stackp; #endif pushheap(); for (;;) { freeheap(); errflag = 0; if (isset(SHINSTDIN)) { setblock_stdin(); if (interact) preprompt(); } hbegin(); /* init history mech */ intr(); /* interrupts on */ lexinit(); /* initialize lexical state */ if (!(list = parse_event())) { /* if we couldn't parse a list */ hend(); if ((tok == ENDINPUT && !errflag) || justonce) break; continue; } if (hend()) { int toksav = tok; List prelist; if (toplevel && (prelist = getshfunc("preexec")) != &dummy_list) { Histent he = gethistent(curhist); LinkList args; PERMALLOC { args = newlinklist(); addlinknode(args, "preexec"); if (he && he->text) addlinknode(args, he->text); } LASTALLOC; doshfunc(prelist, args, 0, 1); freelinklist(args, (FreeFunc) NULL); errflag = 0; } if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; execlist(list, 0, 0); tok = toksav; if (toplevel) noexitct = 0; } DPUTS(alloc_stackp != oasp, "BUG: alloc_stackp changed in loop()"); if (ferror(stderr)) { zerr("write error", NULL, 0); clearerr(stderr); } if (subsh) /* how'd we get this far in a subshell? */ exit(lastval); if (((!interact || sourcelevel) && errflag) || retflag) break; if (trapreturn) { lastval = trapreturn; trapreturn = 0; } if (isset(SINGLECOMMAND) && toplevel) { if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); exit(lastval); } if (justonce) break; }
static mnumber callmathfunc(char *o) { MathFunc f; char *a, *n; static mnumber dummy; n = a = dupstring(o); while (*a != '(') a++; *a++ = '\0'; a[strlen(a) - 1] = '\0'; if ((f = getmathfunc(n, 1))) { if (f->flags & MFF_STR) { return f->sfunc(n, a, f->funcid); } else { int argc = 0; mnumber *argv = NULL, *q, marg; LinkList l = newlinklist(); LinkNode node; if (f->flags & MFF_USERFUNC) { /* first argument is function name: always use mathfunc */ addlinknode(l, n); } while (iblank(*a)) a++; while (*a) { if (*a) { argc++; if (f->flags & MFF_USERFUNC) { /* need to pass strings */ char *str; marg = mathevall(a, MPREC_ARG, &a); if (marg.type & MN_FLOAT) { /* convfloat is off the heap */ str = convfloat(marg.u.d, 0, 0, NULL); } else { char buf[BDIGBUFSIZE]; convbase(buf, marg.u.l, 10); str = dupstring(buf); } addlinknode(l, str); } else { q = (mnumber *) zhalloc(sizeof(mnumber)); *q = mathevall(a, MPREC_ARG, &a); addlinknode(l, q); } if (errflag || mtok != COMMA) break; } } if (*a && !errflag) zerr("bad math expression: illegal character: %c", *a); if (!errflag) { if (argc >= f->minargs && (f->maxargs < 0 || argc <= f->maxargs)) { if (f->flags & MFF_USERFUNC) { char *shfnam = f->module ? f->module : n; Shfunc shfunc = getshfunc(shfnam); if (!shfunc) zerr("no such function: %s", shfnam); else { doshfunc(shfunc, l, 1); return lastmathval; } } else { if (argc) { q = argv = (mnumber *)zhalloc(argc * sizeof(mnumber)); for (node = firstnode(l); node; incnode(node)) *q++ = *(mnumber *)getdata(node); } return f->nfunc(n, argc, argv, f->funcid); } } else zerr("wrong number of arguments: %s", o); } } } else { zerr("unknown function: %s", n); } dummy.type = MN_INTEGER; dummy.u.l = 0; return dummy; }
enum loop_return loop(int toplevel, int justonce) { Eprog prog; int err, non_empty = 0; pushheap(); if (!toplevel) lexsave(); for (;;) { freeheap(); if (stophist == 3) /* re-entry via preprompt() */ hend(NULL); hbegin(1); /* init history mech */ if (isset(SHINSTDIN)) { setblock_stdin(); if (interact && toplevel) { int hstop = stophist; stophist = 3; preprompt(); if (stophist != 3) hbegin(1); else stophist = hstop; errflag = 0; } } use_exit_printed = 0; intr(); /* interrupts on */ lexinit(); /* initialize lexical state */ if (!(prog = parse_event())) { /* if we couldn't parse a list */ hend(NULL); if ((tok == ENDINPUT && !errflag) || (tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) || justonce) break; if (exit_pending) { /* * Something down there (a ZLE function?) decided * to exit when there was stuff to clear up. * Handle that now. */ stopmsg = 1; zexit(exit_pending >> 1, 0); } if (tok == LEXERR && !lastval) lastval = 1; continue; } if (hend(prog)) { int toksav = tok; non_empty = 1; if (toplevel && (getshfunc("preexec") || paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) { LinkList args; char *cmdstr; /* * As we're about to freeheap() or popheap() * anyway, there's no gain in using permanent * storage here. */ args = newlinklist(); addlinknode(args, "preexec"); /* If curline got dumped from the history, we don't know * what the user typed. */ if (hist_ring && curline.histnum == curhist) addlinknode(args, hist_ring->node.nam); else addlinknode(args, ""); addlinknode(args, dupstring(getjobtext(prog, NULL))); addlinknode(args, cmdstr = getpermtext(prog, NULL, 0)); callhookfunc("preexec", args, 1, NULL); /* The only permanent storage is from getpermtext() */ zsfree(cmdstr); errflag = 0; } if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; execode(prog, 0, 0, toplevel ? "toplevel" : "file"); tok = toksav; if (toplevel) noexitct = 0; } if (ferror(stderr)) { zerr("write error"); clearerr(stderr); } if (subsh) /* how'd we get this far in a subshell? */ exit(lastval); if (((!interact || sourcelevel) && errflag) || retflag) break; if (isset(SINGLECOMMAND) && toplevel) { if (sigtrapped[SIGEXIT]) dotrap(SIGEXIT); exit(lastval); } if (justonce) break; }