コード例 #1
0
ファイル: hashtable.c プロジェクト: cdaffara/symbiandump-mw1
int
scanmatchtable(HashTable ht, Patprog pprog, int flags1, int flags2, ScanFunc scanfunc, int scanflags)
{
    int i, hsize = ht->hsize;
    HashNode *nodes = ht->nodes;
    int match = 0;
    struct scanstatus st;

    st.sorted = 0;
    ht->scan = &st;

    for (i = 0; i < hsize; i++)
	for (st.u.u = nodes[i]; st.u.u; ) {
	    HashNode hn = st.u.u;
	    st.u.u = st.u.u->next;
	    if ((hn->flags & flags1) + !flags1 && !(hn->flags & flags2) &&
		pattry(pprog, hn->nam)) {
		scanfunc(hn, scanflags);
		match++;
	    }
	}

    ht->scan = NULL;

    return match;
}
コード例 #2
0
ファイル: loop.c プロジェクト: phy1729/zsh
int
execcase(Estate state, int do_exec)
{
    Wordcode end, next;
    wordcode code = state->pc[-1];
    char *word, *pat;
    int npat, save, nalts, ialt, patok;
    Patprog *spprog, pprog;

    end = state->pc + WC_CASE_SKIP(code);

    word = ecgetstr(state, EC_DUP, NULL);
    singsub(&word);
    untokenize(word);

    cmdpush(CS_CASE);
    while (state->pc < end) {
	code = *state->pc++;
	if (wc_code(code) != WC_CASE)
	    break;

	save = 0;
	next = state->pc + WC_CASE_SKIP(code);
	nalts = *state->pc++;
	ialt = patok = 0;

	if (isset(XTRACE)) {
	    printprompt4();
	    fprintf(xtrerr, "case %s (", word);
	}

	while (!patok && nalts) {
	    npat = state->pc[1];
	    spprog = state->prog->pats + npat;
	    pprog = NULL;
	    pat = NULL;
	
	    if (isset(XTRACE)) {
		int htok = 0;
		pat = dupstring(ecrawstr(state->prog, state->pc, &htok));
		if (htok)
		    singsub(&pat);

		if (ialt++)
		    fprintf(stderr, " | ");
		quote_tokenized_output(pat, xtrerr);
	    }

	    if (*spprog != dummy_patprog1 && *spprog != dummy_patprog2)
		pprog = *spprog;

	    if (!pprog) {
		if (!pat) {
		    char *opat;
		    int htok = 0;

		    pat = dupstring(opat = ecrawstr(state->prog,
						    state->pc, &htok));
		    if (htok)
			singsub(&pat);
		    save = (!(state->prog->flags & EF_HEAP) &&
			    !strcmp(pat, opat) && *spprog != dummy_patprog2);
		}
		if (!(pprog = patcompile(pat, (save ? PAT_ZDUP : PAT_STATIC),
					 NULL)))
		    zerr("bad pattern: %s", pat);
		else if (save)
		    *spprog = pprog;
	    }
	    if (pprog && pattry(pprog, word))
		patok = 1;
	    state->pc += 2;
	    nalts--;
	}
	state->pc += 2 * nalts;
	if (isset(XTRACE)) {
	    fprintf(xtrerr, ")\n");
	    fflush(xtrerr);
	}
	if (patok) {
	    execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
				do_exec));
	    while (!retflag && wc_code(code) == WC_CASE &&
		   WC_CASE_TYPE(code) == WC_CASE_AND && state->pc < end) {
		state->pc = next;
		code = *state->pc++;
		next = state->pc + WC_CASE_SKIP(code);
		nalts = *state->pc++;
		state->pc += 2 * nalts;
		execlist(state, 1, ((WC_CASE_TYPE(code) == WC_CASE_OR) &&
				    do_exec));
	    }
	    if (WC_CASE_TYPE(code) != WC_CASE_TESTAND)
		break;
	}
	state->pc = next;
    }
    cmdpop();

    state->pc = end;

    return lastval;
}
コード例 #3
0
ファイル: complete.c プロジェクト: Jaharmi/zsh
static int
do_comp_vars(int test, int na, char *sa, int nb, char *sb, int mod)
{
    switch (test) {
    case CVT_RANGENUM:
	{
	    int l = arrlen(compwords);

	    if (na < 0)
		na += l;
	    else
		na--;
	    if (nb < 0)
		nb += l;
	    else
		nb--;

	    if (compcurrent - 1 < na || compcurrent - 1 > nb)
		return 0;
	    if (mod)
		restrict_range(na, nb);
	    return 1;
	}
    case CVT_RANGEPAT:
	{
	    char **p;
	    int i, l = arrlen(compwords), t = 0, b = 0, e = l - 1;
	    Patprog pp;

	    i = compcurrent - 1;
	    if (i < 0 || i >= l)
		return 0;

	    singsub(&sa);
	    pp = patcompile(sa, PAT_STATIC, NULL);

	    for (i--, p = compwords + i; i >= 0; p--, i--) {
		if (pattry(pp, *p)) {
		    b = i + 1;
		    t = 1;
		    break;
		}
	    }
	    if (t && sb) {
		int tt = 0;

		singsub(&sb);
		pp = patcompile(sb, PAT_STATIC, NULL);

		for (i++, p = compwords + i; i < l; p++, i++) {
		    if (pattry(pp, *p)) {
			e = i - 1;
			tt = 1;
			break;
		    }
		}
		if (tt && i < compcurrent)
		    t = 0;
	    }
	    if (e < b)
		t = 0;
	    if (t && mod)
		restrict_range(b, e);
	    return t;
	}
    case CVT_PRENUM:
    case CVT_SUFNUM:
	if (!na)
	    return 1;
	if (na > 0 &&
	    (int)strlen(test == CVT_PRENUM ? compprefix : compsuffix) >= na) {
	    if (mod) {
		if (test == CVT_PRENUM)
		    ignore_prefix(na);
		else
		    ignore_suffix(na);
		return 1;
	    }
	    return 0;
	}
    case CVT_PREPAT:
    case CVT_SUFPAT:
	{
	    Patprog pp;

	    if (!na)
		return 0;

	    if (!(pp = patcompile(sa, PAT_STATIC, 0)))
		return 0;

	    if (test == CVT_PREPAT) {
		int l, add;
		char *p, sav;

		if (!(l = strlen(compprefix)))
		    return ((na == 1 || na == -1) && pattry(pp, compprefix));
		if (na < 0) {
		    p = compprefix + l;
		    na = -na;
		    add = -1;
		} else {
		    p = compprefix + 1 + (*compprefix == Meta);
		    if (p > compprefix + l)
			p = compprefix + l;
		    add = 1;
		}
		for (;;) {
		    sav = *p;
		    *p = '\0';
		    test = pattry(pp, compprefix);
		    *p = sav;
		    if (test && !--na)
			break;
		    if (add > 0) {
			if (p == compprefix + l)
			    return 0;
			p = p + 1 + (*p == Meta);
			if (p > compprefix + l)
			    p = compprefix + l;
		    } else {
			if (p == compprefix)
			    return 0;
			p--;
			if (p > compprefix && p[-1] == Meta)
			    p--;
		    }
		}
		if (mod)
		    ignore_prefix(p - compprefix);
	    } else {
		int l, ol, add;
		char *p;

		if (!(ol = l = strlen(compsuffix)))
		    return ((na == 1 || na == -1) && pattry(pp, compsuffix));
		if (na < 0) {
		    p = compsuffix;
		    na = -na;
		    add = 1;
		} else {
		    p = compsuffix + l - 1;
		    if (p > compsuffix && p[-1] == Meta)
			p--;
		    add = -1;
		}
		for (;;) {
		    if (pattry(pp, p) && !--na)
			break;

		    if (add > 0) {
			if (p == compsuffix + l)
			    return 0;
			if (*p == Meta)
			    p += 2;
			else
			    p++;
		    } else {
			if (p == compsuffix)
			    return 0;
			p--;
			if (p > compsuffix && p[-1] == Meta)
			    p--;
		    }
		}

		if (mod)
		    ignore_suffix(ol - (p - compsuffix));
	    }
	    return 1;
	}
    }
    return 0;
}
コード例 #4
0
ファイル: cond.c プロジェクト: AMDmi3/zsh
int
evalcond(Estate state, char *fromtest)
{
    struct stat *st;
    char *left, *right, *overridename, overridebuf[13];
    Wordcode pcode;
    wordcode code;
    int ctype, htok = 0, ret;

 rec:

    left = right = overridename = NULL;
    pcode = state->pc++;
    code = *pcode;
    ctype = WC_COND_TYPE(code);

    switch (ctype) {
    case COND_NOT:
	if (tracingcond)
	    fprintf(xtrerr, " %s", condstr[ctype]);
	ret = evalcond(state, fromtest);
	if (ret == 2)
	    return ret;
	else
	    return !ret;
    case COND_AND:
	if (!(ret = evalcond(state, fromtest))) {
	    if (tracingcond)
		fprintf(xtrerr, " %s", condstr[ctype]);
	    goto rec;
	} else {
	    state->pc = pcode + (WC_COND_SKIP(code) + 1);
	    return ret;
	}
    case COND_OR:
	if ((ret = evalcond(state, fromtest)) == 1) {
	    if (tracingcond)
		fprintf(xtrerr, " %s", condstr[ctype]);
	    goto rec;
	} else {
	    state->pc = pcode + (WC_COND_SKIP(code) + 1);
	    return ret;
	}
    case COND_REGEX:
	{
	    char *modname = isset(REMATCHPCRE) ? "zsh/pcre" : "zsh/regex";
	    sprintf(overridename = overridebuf, "-%s-match", modname+4);
	    (void)ensurefeature(modname, "C:", overridename+1);
	    ctype = COND_MODI;
	}
	/*FALLTHROUGH*/
    case COND_MOD:
    case COND_MODI:
	{
	    Conddef cd;
	    char *name = overridename, *errname;
	    char **strs;
	    int l = WC_COND_SKIP(code);

	    if (name == NULL)
		name = ecgetstr(state, EC_NODUP, NULL);
	    if (ctype == COND_MOD)
		strs = ecgetarr(state, l, EC_DUP, NULL);
	    else {
		char *sbuf[3];

		sbuf[0] = ecgetstr(state, EC_NODUP, NULL);
		sbuf[1] = ecgetstr(state, EC_NODUP, NULL);
		sbuf[2] = NULL;

		strs = arrdup(sbuf);
		l = 2;
	    }
	    if (name && name[0] == '-')
		errname = name;
	    else if (strs[0] && *strs[0] == '-')
		errname = strs[0];
	    else
		errname = "<null>";
	    if (name && name[0] == '-' &&
		(cd = getconddef((ctype == COND_MODI), name + 1, 1))) {
		if (ctype == COND_MOD &&
		    (l < cd->min || (cd->max >= 0 && l > cd->max))) {
		    zwarnnam(fromtest, "unknown condition: %s", name);
		    return 2;
		}
		if (tracingcond)
		    tracemodcond(name, strs, ctype == COND_MODI);
		return !cd->handler(strs, cd->condid);
	    }
	    else {
		char *s = strs[0];

		if (overridename) {
		    /*
		     * Standard regex function not available: this
		     * is a hard error.
		     */
		    zerrnam(fromtest, "%s not available for regex",
			     overridename);
		    return 2;
		}

		strs[0] = dupstring(name);
		name = s;

		if (name && name[0] == '-' &&
		    (cd = getconddef(0, name + 1, 1))) {
		    if (l < cd->min || (cd->max >= 0 && l > cd->max)) {
			zwarnnam(fromtest, "unknown condition: %s",
				 errname);
			return 2;
		    }
		    if (tracingcond)
			tracemodcond(name, strs, ctype == COND_MODI);
		    return !cd->handler(strs, cd->condid);
		} else {
		    zwarnnam(fromtest,
			     "unknown condition: %s",
			     errname);
		}
	    }
	    /* module not found, error */
	    return 2;
	}
    }
    left = ecgetstr(state, EC_DUPTOK, &htok);
    if (htok) {
	cond_subst(&left, !fromtest);
	untokenize(left);
    }
    if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRNEQ) {
	right = ecgetstr(state, EC_DUPTOK, &htok);
	if (htok) {
	    cond_subst(&right, !fromtest);
	    untokenize(right);
	}
    }
    if (tracingcond) {
	if (ctype < COND_MOD) {
	    fputc(' ',xtrerr);
	    quotedzputs(left, xtrerr);
	    fprintf(xtrerr, " %s ", condstr[ctype]);
	    if (ctype == COND_STREQ || ctype == COND_STRNEQ) {
		char *rt = dupstring(ecrawstr(state->prog, state->pc, NULL));
		cond_subst(&rt, !fromtest);
		quote_tokenized_output(rt, xtrerr);
	    }
	    else
		quotedzputs((char *)right, xtrerr);
	} else {
	    fprintf(xtrerr, " -%c ", ctype);
	    quotedzputs(left, xtrerr);
	}
    }

    if (ctype >= COND_EQ && ctype <= COND_GE) {
	mnumber mn1, mn2;
	if (fromtest) {
	    /*
	     * For test and [, the expressions must be base 10 integers,
	     * not integer expressions.
	     */
	    char *eptr, *err;

	    mn1.u.l = zstrtol(left, &eptr, 10);
	    if (!*eptr)
	    {
		mn2.u.l = zstrtol(right, &eptr, 10);
		err = right;
	    }
	    else
		err = left;

	    if (*eptr)
	    {
		zwarnnam(fromtest, "integer expression expected: %s", err);
		return 2;
	    }

	    mn1.type = mn2.type = MN_INTEGER;
	} else {
	    mn1 = matheval(left);
	    mn2 = matheval(right);
	}

	if (((mn1.type|mn2.type) & (MN_INTEGER|MN_FLOAT)) ==
	    (MN_INTEGER|MN_FLOAT)) {
	    /* promote to float */
	    if (mn1.type & MN_INTEGER) {
		mn1.type = MN_FLOAT;
		mn1.u.d = (double)mn1.u.l;
	    }
	    if (mn2.type & MN_INTEGER) {
		mn2.type = MN_FLOAT;
		mn2.u.d = (double)mn2.u.l;
	    }
	}
	switch(ctype) {
	case COND_EQ:
	    return !((mn1.type & MN_FLOAT) ? (mn1.u.d == mn2.u.d) :
		     (mn1.u.l == mn2.u.l));
	case COND_NE:
	    return !((mn1.type & MN_FLOAT) ? (mn1.u.d != mn2.u.d) :
		     (mn1.u.l != mn2.u.l));
	case COND_LT:
	    return !((mn1.type & MN_FLOAT) ? (mn1.u.d < mn2.u.d) :
		     (mn1.u.l < mn2.u.l));
	case COND_GT:
	    return !((mn1.type & MN_FLOAT) ? (mn1.u.d > mn2.u.d) :
		     (mn1.u.l > mn2.u.l));
	case COND_LE:
	    return !((mn1.type & MN_FLOAT) ? (mn1.u.d <= mn2.u.d) :
		     (mn1.u.l <= mn2.u.l));
	case COND_GE:
	    return !((mn1.type & MN_FLOAT) ? (mn1.u.d >= mn2.u.d) :
		     (mn1.u.l >= mn2.u.l));
	}
    }

    switch (ctype) {
    case COND_STREQ:
    case COND_STRNEQ:
	{
	    int test, npat = state->pc[1];
	    Patprog pprog = state->prog->pats[npat];

	    if (pprog == dummy_patprog1 || pprog == dummy_patprog2) {
		char *opat;
		int save;

		right = dupstring(opat = ecrawstr(state->prog, state->pc,
						  &htok));
		singsub(&right);
		save = (!(state->prog->flags & EF_HEAP) &&
			!strcmp(opat, right) && pprog != dummy_patprog2);

		if (!(pprog = patcompile(right, (save ? PAT_ZDUP : PAT_STATIC),
					 NULL))) {
		    zwarnnam(fromtest, "bad pattern: %s", right);
		    return 2;
		}
		else if (save)
		    state->prog->pats[npat] = pprog;
	    }
	    state->pc += 2;
	    test = (pprog && pattry(pprog, left));

	    return !(ctype == COND_STREQ ? test : !test);
	}
    case COND_STRLT:
	return !(strcmp(left, right) < 0);
    case COND_STRGTR:
	return !(strcmp(left, right) > 0);
    case 'e':
    case 'a':
	return (!doaccess(left, F_OK));
    case 'b':
	return (!S_ISBLK(dostat(left)));
    case 'c':
	return (!S_ISCHR(dostat(left)));
    case 'd':
	return (!S_ISDIR(dostat(left)));
    case 'f':
	return (!S_ISREG(dostat(left)));
    case 'g':
	return (!(dostat(left) & S_ISGID));
    case 'k':
	return (!(dostat(left) & S_ISVTX));
    case 'n':
	return (!strlen(left));
    case 'o':
	return (optison(fromtest, left));
    case 'p':
	return (!S_ISFIFO(dostat(left)));
    case 'r':
	return (!doaccess(left, R_OK));
    case 's':
	return !((st = getstat(left)) && !!(st->st_size));
    case 'S':
	return (!S_ISSOCK(dostat(left)));
    case 'u':
	return (!(dostat(left) & S_ISUID));
    case 'w':
	return (!doaccess(left, W_OK));
    case 'x':
	if (privasserted()) {
	    mode_t mode = dostat(left);
	    return !((mode & S_IXUGO) || S_ISDIR(mode));
	}
	return !doaccess(left, X_OK);
    case 'z':
	return !!(strlen(left));
    case 'h':
    case 'L':
	return (!S_ISLNK(dolstat(left)));
    case 'O':
	return !((st = getstat(left)) && st->st_uid == geteuid());
    case 'G':
	return !((st = getstat(left)) && st->st_gid == getegid());
    case 'N':
#if defined(GET_ST_MTIME_NSEC) && defined(GET_ST_ATIME_NSEC)
	if (!(st = getstat(left)))
	    return 1;
        return (st->st_atime == st->st_mtime) ?
        	GET_ST_ATIME_NSEC(*st) > GET_ST_MTIME_NSEC(*st) :
        	st->st_atime > st->st_mtime;
#else
	return !((st = getstat(left)) && st->st_atime <= st->st_mtime);
#endif
    case 't':
	return !isatty(mathevali(left));
    case COND_NT:
    case COND_OT:
	{
	    time_t a;
#ifdef GET_ST_MTIME_NSEC
	    long nsecs;
#endif

	    if (!(st = getstat(left)))
		return 1;
	    a = st->st_mtime;
#ifdef GET_ST_MTIME_NSEC
	    nsecs = GET_ST_MTIME_NSEC(*st);
#endif
	    if (!(st = getstat(right)))
		return 1;
#ifdef GET_ST_MTIME_NSEC
	    if (a == st->st_mtime) {
                return !((ctype == COND_NT) ? nsecs > GET_ST_MTIME_NSEC(*st) :
                        nsecs < GET_ST_MTIME_NSEC(*st));
	    }
#endif
	    return !((ctype == COND_NT) ? a > st->st_mtime : a < st->st_mtime);
	}
    case COND_EF:
	{
	    dev_t d;
	    ino_t i;

	    if (!(st = getstat(left)))
		return 1;
	    d = st->st_dev;
	    i = st->st_ino;
	    if (!(st = getstat(right)))
		return 1;
	    return !(d == st->st_dev && i == st->st_ino);
	}
    default:
	zwarnnam(fromtest, "bad cond code");
	return 2;
    }
}
コード例 #5
0
ファイル: hashtable.c プロジェクト: lol768/zsh
mod_export int
scanmatchtable(HashTable ht, Patprog pprog, int sorted,
	       int flags1, int flags2, ScanFunc scanfunc, int scanflags)
{
    int match = 0;
    struct scanstatus st;

    /*
     * scantab is currently only used by modules to scan
     * tables where the contents are generated on the fly from
     * other objects.  Note the fact that in this case pprog,
     * sorted, flags1 and flags2 are ignore.
     */
    if (!pprog && ht->scantab) {
	ht->scantab(ht, scanfunc, scanflags);
	return ht->ct;
    }
    if (sorted) {
	int i, ct = ht->ct;
	VARARR(HashNode, hnsorttab, ct);
	HashNode *htp, hn;

	/*
	 * Because the structure might change under our feet,
	 * we can't apply the flags and the pattern before sorting,
	 * tempting though that is.
	 */
	for (htp = hnsorttab, i = 0; i < ht->hsize; i++)
	    for (hn = ht->nodes[i]; hn; hn = hn->next)
		*htp++ = hn;
	qsort((void *)hnsorttab, ct, sizeof(HashNode), hnamcmp);

	st.sorted = 1;
	st.u.s.hashtab = hnsorttab;
	st.u.s.ct = ct;
	ht->scan = &st;

	for (htp = hnsorttab, i = 0; i < ct; i++, htp++) {
	    if ((!flags1 || ((*htp)->flags & flags1)) &&
		!((*htp)->flags & flags2) &&
		(!pprog || pattry(pprog, (*htp)->nam))) {
		match++;
		scanfunc(*htp, scanflags);
	    }
	}

	ht->scan = NULL;
    } else {
	int i, hsize = ht->hsize;
	HashNode *nodes = ht->nodes;

	st.sorted = 0;
	ht->scan = &st;

	for (i = 0; i < hsize; i++)
	    for (st.u.u = nodes[i]; st.u.u; ) {
		HashNode hn = st.u.u;
		st.u.u = st.u.u->next;
		if ((!flags1 || (hn->flags & flags1)) && !(hn->flags & flags2)
		    && (!pprog || pattry(pprog, hn->nam))) {
		    match++;
		    scanfunc(hn, scanflags);
		}
	    }

	ht->scan = NULL;
    }

    return match;
}
コード例 #6
0
ファイル: zpty.c プロジェクト: zsh-users/zsh
static int
ptyread(char *nam, Ptycmd cmd, char **args, int noblock, int mustmatch)
{
    int blen, used, seen = 0, ret = 0, matchok = 0;
    char *buf;
    Patprog prog = NULL;

    if (*args && args[1]) {
	char *p;

	if (args[2]) {
	    zwarnnam(nam, "too many arguments");
	    return 1;
	}
	p = dupstring(args[1]);
	tokenize(p);
	remnulargs(p);
	/* Signals handlers might stomp PAT_STATIC */
	if (!(prog = patcompile(p, PAT_ZDUP, NULL))) {
	    zwarnnam(nam, "bad pattern: %s", args[1]);
	    return 1;
	}
    } else
	fflush(stdout);

    if (cmd->old) {
	used = cmd->olen;
	buf = (char *) zhalloc((blen = 256 + used) + 1);
	memcpy(buf, cmd->old, cmd->olen);
	zfree(cmd->old, cmd->olen);
	cmd->old = NULL;
	cmd->olen = 0;
    } else {
	used = 0;
	buf = (char *) zhalloc((blen = 256) + 1);
    }
    if (cmd->read != -1) {
	buf[used] = (char) cmd->read;
	buf[used + 1] = '\0';
	seen = used = 1;
	cmd->read = -1;
    }
    do {
	if (noblock && cmd->read == -1) {
	    int pollret;
	    /*
	     * Check there is data available.  Borrowed from
	     * poll_read() in utils.c and simplified.
	     */
#ifdef HAVE_SELECT
	    fd_set foofd;
	    struct timeval expire_tv;
	    expire_tv.tv_sec = 0;
	    expire_tv.tv_usec = 0;
	    FD_ZERO(&foofd);
	    FD_SET(cmd->fd, &foofd);
	    pollret = select(cmd->fd+1,
			 (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
#else
#ifdef FIONREAD
	    if (ioctl(cmd->fd, FIONREAD, (char *) &val) == 0)
		pollret = (val > 0);
#endif
#endif

	    if (pollret < 0) {
		/*
		 * See read_poll() for this.
		 * Last despairing effort to poll: attempt to
		 * set nonblocking I/O and actually read the
		 * character.  cmd->read stores the character read.
		 */
		long mode;

		if (setblock_fd(0, cmd->fd, &mode))
		    pollret = read(cmd->fd, &cmd->read, 1);
		if (mode != -1)
		    fcntl(cmd->fd, F_SETFL, mode);
	    }
	    if (pollret == 0)
		break;
	}
	if (!ret) {
	    checkptycmd(cmd);
	    if (cmd->fin)
		break;
	}
	if (cmd->read != -1 || (ret = read(cmd->fd, buf + used, 1)) == 1) {
	    int readchar;
	    if (cmd->read != -1) {
		ret = 1;
		readchar = cmd->read;
		cmd->read = -1;
	    } else
		readchar = STOUC(buf[used]);
	    if (imeta(readchar)) {
		buf[used++] = Meta;
		buf[used++] = (char) (readchar ^ 32);
	    } else
		buf[used++] = (char) readchar;
	    seen = 1;
	    if (used >= blen-1) {
		if (!*args) {
		    buf[used] = '\0';
		    unmetafy(buf, &used);
		    write_loop(1, buf, used);
		    used = 0;
		} else {
		    buf = hrealloc(buf, blen, blen << 1);
		    blen <<= 1;
		}
	    }
	}
	buf[used] = '\0';

	if (!prog) {
	    if (ret <= 0 || (*args && buf[used - 1] == '\n' &&
			     (used < 2 || buf[used-2] != Meta)))
		break;
	} else {
	    if (ret < 0
#ifdef EWOULDBLOCK
		&& errno != EWOULDBLOCK
#else
#ifdef EAGAIN
		&& errno != EAGAIN
#endif
#endif
		)
		break;
	}
    } while (!(errflag || breaks || retflag || contflag) &&
	     used < READ_MAX &&
	     !(prog && ret && (matchok = pattry(prog, buf))));

    if (prog && ret < 0 &&
#ifdef EWOULDBLOCK
	errno == EWOULDBLOCK
#else
#ifdef EAGAIN
	errno == EAGAIN
#endif
#endif
	) {
	cmd->old = (char *) zalloc(cmd->olen = used);
	memcpy(cmd->old, buf, cmd->olen);

	return 1;
    }
    if (*args)
	setsparam(*args, ztrdup(buf));
    else if (used) {
	unmetafy(buf, &used);
	write_loop(1, buf, used);
    }

    {
	int ret = cmd->fin + 1;
	if (seen && (!prog || matchok || !mustmatch))
	    ret = 0;
	if (prog)
	    freepatprog(prog);
	return ret;
    }
}