int execwhile(Estate state, UNUSED(int do_exec)) { Wordcode end, loop; wordcode code = state->pc[-1]; int olderrexit, oldval, isuntil = (WC_WHILE_TYPE(code) == WC_WHILE_UNTIL); int old_simple_pline = simple_pline; end = state->pc + WC_WHILE_SKIP(code); olderrexit = noerrexit; oldval = 0; pushheap(); cmdpush(isuntil ? CS_UNTIL : CS_WHILE); loops++; loop = state->pc; if (loop[0] == WC_END && loop[1] == WC_END) { /* This is an empty loop. Make sure the signal handler sets the * flags and then just wait for someone hitting ^C. */ simple_pline = 1; while (!breaks) ; breaks--; simple_pline = old_simple_pline; } else for (;;) { state->pc = loop; noerrexit = 1; /* In case the test condition is a functional no-op, * make sure signal handlers recognize ^C to end the loop. */ simple_pline = 1; execlist(state, 1, 0); simple_pline = old_simple_pline; noerrexit = olderrexit; if (!((lastval == 0) ^ isuntil)) { if (breaks) breaks--; lastval = oldval; break; } if (retflag) { lastval = oldval; break; } /* In case the loop body is also a functional no-op, * make sure signal handlers recognize ^C as above. */ simple_pline = 1; execlist(state, 1, 0); simple_pline = old_simple_pline; if (breaks) { breaks--; if (breaks || !contflag) break; contflag = 0; } if (errflag) { lastval = 1; break; } if (retflag) break; freeheap(); oldval = lastval; } cmdpop(); popheap(); loops--; state->pc = end; return lastval; }
int execselect(Estate state, UNUSED(int do_exec)) { Wordcode end, loop; wordcode code = state->pc[-1]; char *str, *s, *name; LinkNode n; int i, usezle; FILE *inp; size_t more; LinkList args; int old_simple_pline = simple_pline; /* See comments in execwhile() */ simple_pline = 1; end = state->pc + WC_FOR_SKIP(code); name = ecgetstr(state, EC_NODUP, NULL); if (WC_SELECT_TYPE(code) == WC_SELECT_PPARAM) { char **x; args = newlinklist(); for (x = pparams; *x; x++) addlinknode(args, dupstring(*x)); } else { int htok = 0; if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) { state->pc = end; simple_pline = old_simple_pline; return 0; } if (htok) { execsubst(args); if (errflag) { state->pc = end; simple_pline = old_simple_pline; return 1; } } } if (!args || empty(args)) { state->pc = end; simple_pline = old_simple_pline; return 0; } loops++; pushheap(); cmdpush(CS_SELECT); usezle = interact && SHTTY != -1 && isset(USEZLE); inp = fdopen(dup(usezle ? SHTTY : 0), "r"); more = selectlist(args, 0); loop = state->pc; for (;;) { for (;;) { if (empty(bufstack)) { if (usezle) { int oef = errflag; isfirstln = 1; str = zleentry(ZLE_CMD_READ, &prompt3, NULL, 0, ZLCON_SELECT); if (errflag) str = NULL; /* Keep any user interrupt error status */ errflag = oef | (errflag & ERRFLAG_INT); } else { str = promptexpand(prompt3, 0, NULL, NULL, NULL); zputs(str, stderr); free(str); fflush(stderr); str = fgets(zhalloc(256), 256, inp); } } else str = (char *)getlinknode(bufstack); if (!str && !errflag) setsparam("REPLY", ztrdup("")); /* EOF (user pressed Ctrl+D) */ if (!str || errflag) { if (breaks) breaks--; fprintf(stderr, "\n"); fflush(stderr); goto done; } if ((s = strchr(str, '\n'))) *s = '\0'; if (*str) break; more = selectlist(args, more); } setsparam("REPLY", ztrdup(str)); i = atoi(str); if (!i) str = ""; else { for (i--, n = firstnode(args); n && i; incnode(n), i--); if (n) str = (char *) getdata(n); else str = ""; } setsparam(name, ztrdup(str)); state->pc = loop; execlist(state, 1, 0); freeheap(); if (breaks) { breaks--; if (breaks || !contflag) break; contflag = 0; } if (retflag || errflag) break; } done: cmdpop(); popheap(); fclose(inp); loops--; simple_pline = old_simple_pline; state->pc = end; return lastval; }
void zlecore(void) { Keymap km; #if !defined(HAVE_POLL) && defined(HAVE_SELECT) struct timeval tv; fd_set foofd; FD_ZERO(&foofd); #endif pushheap(); /* * A widget function may decide to exit the shell. * We never exit directly from functions, to allow * the shell to tidy up, so we have to test for * that explicitly. */ while (!done && !errflag && !exit_pending) { UNMETACHECK(); statusline = NULL; vilinerange = 0; reselectkeymap(); selectlocalmap(invicmdmode() && region_active && (km = openkeymap("visual")) ? km : NULL); bindk = getkeycmd(); selectlocalmap(NULL); if (bindk) { if (!zlell && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) && lastchar == eofchar) { /* * Slight hack: this relies on getkeycmd returning * a value for the EOF character. However, * undefined-key is fine. That's necessary because * otherwise we can't distinguish this case from * a ^C. */ eofsent = 1; break; } if (execzlefunc(bindk, zlenoargs, 0)) { handlefeep(zlenoargs); if (eofsent) break; } handleprefixes(); /* for vi mode, make sure the cursor isn't somewhere illegal */ if (invicmdmode() && zlecs > findbol() && (zlecs == zlell || zleline[zlecs] == ZWC('\n'))) DECCS(); handleundo(); } else { errflag |= ERRFLAG_ERROR; break; } #ifdef HAVE_POLL if (baud && !(lastcmd & ZLE_MENUCMP)) { struct pollfd pfd; int to = cost * costmult / 1000; /* milliseconds */ if (to > 500) to = 500; pfd.fd = SHTTY; pfd.events = POLLIN; if (!kungetct && poll(&pfd, 1, to) <= 0) zrefresh(); } else #else # ifdef HAVE_SELECT if (baud && !(lastcmd & ZLE_MENUCMP)) { FD_SET(SHTTY, &foofd); tv.tv_sec = 0; if ((tv.tv_usec = cost * costmult) > 500000) tv.tv_usec = 500000; if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd, NULL, NULL, &tv) <= 0) zrefresh(); } else # endif #endif if (!kungetct) zrefresh(); freeheap(); } region_active = 0; popheap(); }
int exectry(Estate state, int do_exec) { Wordcode end, always; int endval; int save_retflag, save_breaks, save_contflag; zlong save_try_errflag, save_try_tryflag, save_try_interrupt; end = state->pc + WC_TRY_SKIP(state->pc[-1]); always = state->pc + 1 + WC_TRY_SKIP(*state->pc); state->pc++; pushheap(); cmdpush(CS_CURSH); /* The :try clause */ save_try_tryflag = try_tryflag; try_tryflag = 1; execlist(state, 1, do_exec); try_tryflag = save_try_tryflag; /* Don't record errflag here, may be reset. However, */ /* endval should show failure when there is an error. */ endval = lastval ? lastval : errflag; freeheap(); cmdpop(); cmdpush(CS_ALWAYS); /* The always clause. */ save_try_errflag = try_errflag; save_try_interrupt = try_interrupt; try_errflag = (zlong)(errflag & ERRFLAG_ERROR); try_interrupt = (zlong)((errflag & ERRFLAG_INT) ? 1 : 0); /* We need to reset all errors to allow the block to execute */ errflag = 0; save_retflag = retflag; retflag = 0; save_breaks = breaks; breaks = 0; save_contflag = contflag; contflag = 0; state->pc = always; execlist(state, 1, do_exec); if (try_errflag) errflag |= ERRFLAG_ERROR; else errflag &= ~ERRFLAG_ERROR; if (try_interrupt) errflag |= ERRFLAG_INT; else errflag &= ~ERRFLAG_INT; try_errflag = save_try_errflag; try_interrupt = save_try_interrupt; if (!retflag) retflag = save_retflag; if (!breaks) breaks = save_breaks; if (!contflag) contflag = save_contflag; cmdpop(); popheap(); state->pc = end; return endval; }
int execfor(Estate state, int do_exec) { Wordcode end, loop; wordcode code = state->pc[-1]; int iscond = (WC_FOR_TYPE(code) == WC_FOR_COND), ctok = 0, atok = 0; int last = 0; char *name, *str, *cond = NULL, *advance = NULL; zlong val = 0; LinkList vars = NULL, args = NULL; end = state->pc + WC_FOR_SKIP(code); if (iscond) { str = dupstring(ecgetstr(state, EC_NODUP, NULL)); singsub(&str); if (isset(XTRACE)) { char *str2 = dupstring(str); untokenize(str2); printprompt4(); fprintf(xtrerr, "%s\n", str2); fflush(xtrerr); } if (!errflag) matheval(str); if (errflag) { state->pc = end; return 1; } cond = ecgetstr(state, EC_NODUP, &ctok); advance = ecgetstr(state, EC_NODUP, &atok); } else { vars = ecgetlist(state, *state->pc++, EC_NODUP, NULL); if (WC_FOR_TYPE(code) == WC_FOR_LIST) { int htok = 0; if (!(args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok))) { state->pc = end; return 0; } if (htok) { execsubst(args); if (errflag) { state->pc = end; return 1; } } } else { char **x; args = newlinklist(); for (x = pparams; *x; x++) addlinknode(args, dupstring(*x)); } } if (!args || empty(args)) lastval = 0; loops++; pushheap(); cmdpush(CS_FOR); loop = state->pc; while (!last) { if (iscond) { if (ctok) { str = dupstring(cond); singsub(&str); } else str = cond; if (!errflag) { while (iblank(*str)) str++; if (*str) { if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s\n", str); fflush(xtrerr); } val = mathevali(str); } else val = 1; } if (errflag) { if (breaks) breaks--; lastval = 1; break; } if (!val) break; } else { LinkNode node; int count = 0; for (node = firstnode(vars); node; incnode(node)) { name = (char *)getdata(node); if (!args || !(str = (char *) ugetnode(args))) { if (count) { str = ""; last = 1; } else break; } if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s=%s\n", name, str); fflush(xtrerr); } setsparam(name, ztrdup(str)); count++; } if (!count) break; } state->pc = loop; execlist(state, 1, do_exec && args && empty(args)); if (breaks) { breaks--; if (breaks || !contflag) break; contflag = 0; } if (retflag) break; if (iscond && !errflag) { if (atok) { str = dupstring(advance); singsub(&str); } else str = advance; if (isset(XTRACE)) { printprompt4(); fprintf(xtrerr, "%s\n", str); fflush(xtrerr); } if (!errflag) matheval(str); } if (errflag) { if (breaks) breaks--; lastval = 1; break; } freeheap(); } popheap(); cmdpop(); loops--; state->pc = end; return lastval; }
mod_export void strmetasort(char **array, int sortwhat, int *unmetalenp) { char **arrptr; /* * Array of elements containing stuff to sort. Note sortptrarr * is an array of pointers, since that's more efficient * for qsort() to manipulate. sortarr is the array of * structures. */ SortElt *sortptrarr, *sortptrarrptr; SortElt sortarr, sortarrptr; int oldsortdir, oldsortnumeric, nsort; nsort = arrlen(array); if (nsort < 2) return; pushheap(); sortptrarr = (SortElt *) zhalloc(nsort * sizeof(SortElt)); sortarr = (SortElt) zhalloc(nsort * sizeof(struct sortelt)); for (arrptr = array, sortptrarrptr = sortptrarr, sortarrptr = sortarr; *arrptr; arrptr++, sortptrarrptr++, sortarrptr++) { char *metaptr; int needlen, needalloc; *sortptrarrptr = sortarrptr; sortarrptr->orig = *arrptr; if (unmetalenp) { /* * Already unmetafied. We just need to check for * embededded nulls. */ int count = unmetalenp[arrptr-array]; /* Remember this length for sorted array */ sortarrptr->origlen = count; for (metaptr = *arrptr; *metaptr != '\0' && count--; metaptr++) ; /* *metaptr must now be \0, even if we reached the end */ needlen = (count != 0); } else { /* * Not yet unmetafied. See if it needs unmetafying. * If it doesn't, there can't be any embedded nulls, * since these are metafied. */ needlen = 0; for (metaptr = *arrptr; *metaptr && *metaptr != Meta; metaptr++); } /* * See if we need to do some special checking. * Either we're going to need to copy it to transform it, * or we need to unmetafy it. */ if ((needalloc = (sortwhat & (SORTIT_IGNORING_CASE|SORTIT_IGNORING_BACKSLASHES))) || *metaptr == Meta) { char *s, *t, *src = *arrptr, *dst; int len; sortarrptr->cmp = dst = (char *)zhalloc(((sortwhat & SORTIT_IGNORING_CASE)?2:1)*strlen(src)+1); if (unmetalenp) { /* Already unmetafied and we have the length. */ len = unmetalenp[arrptr-array]; } else if (*metaptr != '\0') { /* * Needs unmetafying. We need to check for * embedded nulls while we do this. */ char *t = dst + (metaptr - src); if (metaptr != src) memcpy(dst, src, metaptr - src); while ((*t = *metaptr++)) { if (*t++ == Meta) { if ((t[-1] = *metaptr++ ^ 32) == '\0') needlen = 1; } } len = t - dst; src = dst; } else { /* * Doesn't need unmetafying. * This means metaptr is the NULL at the * end of the string, so we have the length, and * there are no embedded nulls, so we don't * need the length later. * We're only copying the string to transform it * below. */ len = metaptr - src; } if (sortwhat & SORTIT_IGNORING_CASE) { char *send = src + len; #ifdef MULTIBYTE_SUPPORT if (isset(MULTIBYTE)) { /* * Lower the case the hard way. Convert to a wide * character, process that, and convert back. We * don't assume the characters have the same * multibyte length. We can't use casemodify() * because we have unmetafied data, which may have * been passed down to use. */ mbstate_t mbsin, mbsout; int clen; wchar_t wc; memset(&mbsin, 0, sizeof(mbstate_t)); memset(&mbsout, 0, sizeof(mbstate_t)); for (s = src, t = dst; s < send; ) { clen = mbrtowc(&wc, s, send-s, &mbsin); if (clen < 0) { /* invalid or unfinished: treat as single bytes */ while (s < send) *t++ = tulower(*s++); break; } if (clen == 0) { /* embedded null */ *t++ = '\0'; s++; continue; } s += clen; wc = towlower(wc); clen = wcrtomb(t, wc, &mbsout); t += clen; DPUTS(clen < 0, "Bad conversion when lowering case"); } *t = '\0'; len = t - dst; } else #endif for (s = src, t = dst; s < send; ) *t++ = tulower(*s++); src = dst; } if (sortwhat & SORTIT_IGNORING_BACKSLASHES) { char *end = src + len + 1; /* copy null byte, so increment length */ for (s = src, t = dst; s < end; ) { if (*s == '\\') { s++; len--; } *t++ = *s++; } } /* Do we need to store the length (embedded null)? */ sortarrptr->len = needlen ? len : -1; } else { /* * We can use the string as is, although it's possible * we still need to take account of an embedded null. */ sortarrptr->cmp = *arrptr; sortarrptr->len = needlen ? unmetalenp[arrptr-array] : -1; } } /* * We probably don't need to restore the following, but it's pretty cheap. */ oldsortdir = sortdir; oldsortnumeric = sortnumeric; sortdir = (sortwhat & SORTIT_BACKWARDS) ? -1 : 1; sortnumeric = (sortwhat & SORTIT_NUMERICALLY) ? 1 : 0; qsort(sortptrarr, nsort, sizeof(SortElt), eltpcmp); sortnumeric = oldsortnumeric; sortdir = oldsortdir; for (arrptr = array, sortptrarrptr = sortptrarr; nsort--; ) { if (unmetalenp) unmetalenp[arrptr-array] = (*sortptrarrptr)->origlen; *arrptr++ = (*sortptrarrptr++)->orig; } popheap(); }