⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dolist.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $RCSfile: dolist.c,v $$Revision: 4.0.1.5 $$Date: 92/06/08 13:13:27 $ * *    Copyright (c) 1991, Larry Wall * *    You may distribute under the terms of either the GNU General Public *    License or the Artistic License, as specified in the README file. * * $Log:	dolist.c,v $ * Revision 4.0.1.5  92/06/08  13:13:27  lwall * patch20: g pattern modifer sometimes returned extra values * patch20: m/$pattern/g didn't work * patch20: pattern modifiers i and o didn't interact right * patch20: @ in unpack failed too often * patch20: Perl now distinguishes overlapped copies from non-overlapped * patch20: slice on null list in scalar context returned random value * patch20: splice with negative offset didn't work with $[ = 1 * patch20: fixed some memory leaks in splice * patch20: scalar keys %array now counts keys for you *  * Revision 4.0.1.4  91/11/11  16:33:19  lwall * patch19: added little-endian pack/unpack options * patch19: sort $subname was busted by changes in 4.018 *  * Revision 4.0.1.3  91/11/05  17:07:02  lwall * patch11: prepared for ctype implementations that don't define isascii() * patch11: /$foo/o optimizer could access deallocated data * patch11: certain optimizations of //g in array context returned too many values * patch11: regexp with no parens in array context returned wacky $`, $& and $' * patch11: $' not set right on some //g * patch11: added some support for 64-bit integers * patch11: grep of a split lost its values * patch11: added sort {} LIST * patch11: multiple reallocations now avoided in 1 .. 100000 *  * Revision 4.0.1.2  91/06/10  01:22:15  lwall * patch10: //g only worked first time through *  * Revision 4.0.1.1  91/06/07  10:58:28  lwall * patch4: new copyright notice * patch4: added global modifier for pattern matches * patch4: // wouldn't use previous pattern if it started with a null character * patch4: //o and s///o now optimize themselves fully at runtime * patch4: $` was busted inside s/// * patch4: caller($arg) didn't work except under debugger *  * Revision 4.0  91/03/20  01:08:03  lwall * 4.0 baseline. *  */#include "EXTERN.h"#include "perl.h"static int sortcmp();static int sortsub();#ifdef BUGGY_MSC #pragma function(memcmp)#endif /* BUGGY_MSC */intdo_match(str,arg,gimme,arglast)STR *str;register ARG *arg;int gimme;int *arglast;{    register STR **st = stack->ary_array;    register SPAT *spat = arg[2].arg_ptr.arg_spat;    register char *t;    register int sp = arglast[0] + 1;    STR *srchstr = st[sp];    register char *s = str_get(st[sp]);    char *strend = s + st[sp]->str_cur;    STR *tmpstr;    char *myhint = hint;    int global;    int safebase;    char *truebase = s;    register REGEXP *rx = spat->spat_regexp;    hint = Nullch;    if (!spat) {	if (gimme == G_ARRAY)	    return --sp;	str_set(str,Yes);	STABSET(str);	st[sp] = str;	return sp;    }    global = spat->spat_flags & SPAT_GLOBAL;    safebase = (gimme == G_ARRAY) || global;    if (!s)	fatal("panic: do_match");    if (spat->spat_flags & SPAT_USED) {#ifdef DEBUGGING	if (debug & 8)	    deb("2.SPAT USED\n");#endif	if (gimme == G_ARRAY)	    return --sp;	str_set(str,No);	STABSET(str);	st[sp] = str;	return sp;    }    --sp;    if (spat->spat_runtime) {	nointrp = "|)";	sp = eval(spat->spat_runtime,G_SCALAR,sp);	st = stack->ary_array;	t = str_get(tmpstr = st[sp--]);	nointrp = "";#ifdef DEBUGGING	if (debug & 8)	    deb("2.SPAT /%s/\n",t);#endif	if (!global && rx)	    regfree(rx);	spat->spat_regexp = Null(REGEXP*);	/* crucial if regcomp aborts */	spat->spat_regexp = regcomp(t,t+tmpstr->str_cur,	    spat->spat_flags & SPAT_FOLD);	if (!spat->spat_regexp->prelen && lastspat)	    spat = lastspat;	if (spat->spat_flags & SPAT_KEEP) {	    if (!(spat->spat_flags & SPAT_FOLD))		scanconst(spat,spat->spat_regexp->precomp,		    spat->spat_regexp->prelen);	    if (spat->spat_runtime)		arg_free(spat->spat_runtime);	/* it won't change, so */	    spat->spat_runtime = Nullarg;	/* no point compiling again */	    hoistmust(spat);	    if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) {		curcmd->c_flags &= ~CF_OPTIMIZE;		opt_arg(curcmd, 1, curcmd->c_type == C_EXPR);	    }	}	if (global) {	    if (rx) {	        if (rx->startp[0]) {		    s = rx->endp[0];		    if (s == rx->startp[0])			s++;		    if (s > strend) {			regfree(rx);			rx = spat->spat_regexp;			goto nope;		    }		}		regfree(rx);	    }	}	else if (!spat->spat_regexp->nparens)	    gimme = G_SCALAR;			/* accidental array context? */	rx = spat->spat_regexp;	if (regexec(rx, s, strend, s, 0,	  srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,	  safebase)) {	    if (rx->subbase || global)		curspat = spat;	    lastspat = spat;	    goto gotcha;	}	else {	    if (gimme == G_ARRAY)		return sp;	    str_sset(str,&str_no);	    STABSET(str);	    st[++sp] = str;	    return sp;	}    }    else {#ifdef DEBUGGING	if (debug & 8) {	    char ch;	    if (spat->spat_flags & SPAT_ONCE)		ch = '?';	    else		ch = '/';	    deb("2.SPAT %c%s%c\n",ch,rx->precomp,ch);	}#endif	if (!rx->prelen && lastspat) {	    spat = lastspat;	    rx = spat->spat_regexp;	}	t = s;    play_it_again:	if (global && rx->startp[0]) {	    t = s = rx->endp[0];	    if (s == rx->startp[0])		s++,t++;	    if (s > strend)		goto nope;	}	if (myhint) {	    if (myhint < s || myhint > strend)		fatal("panic: hint in do_match");	    s = myhint;	    if (rx->regback >= 0) {		s -= rx->regback;		if (s < t)		    s = t;	    }	    else		s = t;	}	else if (spat->spat_short) {	    if (spat->spat_flags & SPAT_SCANFIRST) {		if (srchstr->str_pok & SP_STUDIED) {		    if (screamfirst[spat->spat_short->str_rare] < 0)			goto nope;		    else if (!(s = screaminstr(srchstr,spat->spat_short)))			goto nope;		    else if (spat->spat_flags & SPAT_ALL)			goto yup;		}#ifndef lint		else if (!(s = fbminstr((unsigned char*)s,		  (unsigned char*)strend, spat->spat_short)))		    goto nope;#endif		else if (spat->spat_flags & SPAT_ALL)		    goto yup;		if (s && rx->regback >= 0) {		    ++spat->spat_short->str_u.str_useful;		    s -= rx->regback;		    if (s < t)			s = t;		}		else		    s = t;	    }	    else if (!multiline && (*spat->spat_short->str_ptr != *s ||	      bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) ))		goto nope;	    if (--spat->spat_short->str_u.str_useful < 0) {		str_free(spat->spat_short);		spat->spat_short = Nullstr;	/* opt is being useless */	    }	}	if (!rx->nparens && !global) {	    gimme = G_SCALAR;			/* accidental array context? */	    safebase = FALSE;	}	if (regexec(rx, s, strend, truebase, 0,	  srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr,	  safebase)) {	    if (rx->subbase || global)		curspat = spat;	    lastspat = spat;	    if (spat->spat_flags & SPAT_ONCE)		spat->spat_flags |= SPAT_USED;	    goto gotcha;	}	else {	    if (global)		rx->startp[0] = Nullch;	    if (gimme == G_ARRAY)		return sp;	    str_sset(str,&str_no);	    STABSET(str);	    st[++sp] = str;	    return sp;	}    }    /*NOTREACHED*/  gotcha:    if (gimme == G_ARRAY) {	int iters, i, len;	iters = rx->nparens;	if (global && !iters)	    i = 1;	else	    i = 0;	if (sp + iters + i >= stack->ary_max) {	    astore(stack,sp + iters + i, Nullstr);	    st = stack->ary_array;		/* possibly realloced */	}	for (i = !i; i <= iters; i++) {	    st[++sp] = str_mortal(&str_no);	    /*SUPPRESS 560*/	    if (s = rx->startp[i]) {		len = rx->endp[i] - s;		if (len > 0)		    str_nset(st[sp],s,len);	    }	}	if (global) {	    truebase = rx->subbeg;	    goto play_it_again;	}	return sp;    }    else {	str_sset(str,&str_yes);	STABSET(str);	st[++sp] = str;	return sp;    }yup:    ++spat->spat_short->str_u.str_useful;    lastspat = spat;    if (spat->spat_flags & SPAT_ONCE)	spat->spat_flags |= SPAT_USED;    if (global) {	rx->subbeg = t;	rx->subend = strend;	rx->startp[0] = s;	rx->endp[0] = s + spat->spat_short->str_cur;	curspat = spat;	goto gotcha;    }    if (sawampersand) {	char *tmps;	if (rx->subbase)	    Safefree(rx->subbase);	tmps = rx->subbase = nsavestr(t,strend-t);	rx->subbeg = tmps;	rx->subend = tmps + (strend-t);	tmps = rx->startp[0] = tmps + (s - t);	rx->endp[0] = tmps + spat->spat_short->str_cur;	curspat = spat;    }    str_sset(str,&str_yes);    STABSET(str);    st[++sp] = str;    return sp;nope:    rx->startp[0] = Nullch;    if (spat->spat_short)	++spat->spat_short->str_u.str_useful;    if (gimme == G_ARRAY)	return sp;    str_sset(str,&str_no);    STABSET(str);    st[++sp] = str;    return sp;}#ifdef BUGGY_MSC #pragma intrinsic(memcmp)#endif /* BUGGY_MSC */intdo_split(str,spat,limit,gimme,arglast)STR *str;register SPAT *spat;register int limit;int gimme;int *arglast;{    register ARRAY *ary = stack;    STR **st = ary->ary_array;    register int sp = arglast[0] + 1;    register char *s = str_get(st[sp]);    char *strend = s + st[sp--]->str_cur;    register STR *dstr;    register char *m;    int iters = 0;    int maxiters = (strend - s) + 10;    int i;    char *orig;    int origlimit = limit;    int realarray = 0;    if (!spat || !s)	fatal("panic: do_split");    else if (spat->spat_runtime) {	nointrp = "|)";	sp = eval(spat->spat_runtime,G_SCALAR,sp);	st = stack->ary_array;	m = str_get(dstr = st[sp--]);	nointrp = "";	if (*m == ' ' && dstr->str_cur == 1) {	    str_set(dstr,"\\s+");	    m = dstr->str_ptr;	    spat->spat_flags |= SPAT_SKIPWHITE;	}	if (spat->spat_regexp) {	    regfree(spat->spat_regexp);	    spat->spat_regexp = Null(REGEXP*);	/* avoid possible double free */	}	spat->spat_regexp = regcomp(m,m+dstr->str_cur,	    spat->spat_flags & SPAT_FOLD);	if (spat->spat_flags & SPAT_KEEP ||	    (spat->spat_runtime->arg_type == O_ITEM &&	      (spat->spat_runtime[1].arg_type & A_MASK) == A_SINGLE) ) {	    arg_free(spat->spat_runtime);	/* it won't change, so */	    spat->spat_runtime = Nullarg;	/* no point compiling again */	}    }#ifdef DEBUGGING    if (debug & 8) {	deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);    }#endif    ary = stab_xarray(spat->spat_repl[1].arg_ptr.arg_stab);    if (ary && (gimme != G_ARRAY || (spat->spat_flags & SPAT_ONCE))) {	realarray = 1;	if (!(ary->ary_flags & ARF_REAL)) {	    ary->ary_flags |= ARF_REAL;	    for (i = ary->ary_fill; i >= 0; i--)		ary->ary_array[i] = Nullstr;	/* don't free mere refs */	}	ary->ary_fill = -1;	sp = -1;	/* temporarily switch stacks */    }    else	ary = stack;    orig = s;    if (spat->spat_flags & SPAT_SKIPWHITE) {	while (isSPACE(*s))	    s++;    }    if (!limit)	limit = maxiters + 2;    if (strEQ("\\s+",spat->spat_regexp->precomp)) {	while (--limit) {	    /*SUPPRESS 530*/	    for (m = s; m < strend && !isSPACE(*m); m++) ;	    if (m >= strend)		break;	    dstr = Str_new(30,m-s);	    str_nset(dstr,s,m-s);	    if (!realarray)		str_2mortal(dstr);	    (void)astore(ary, ++sp, dstr);	    /*SUPPRESS 530*/	    for (s = m + 1; s < strend && isSPACE(*s); s++) ;	}    }    else if (strEQ("^",spat->spat_regexp->precomp)) {	while (--limit) {	    /*SUPPRESS 530*/	    for (m = s; m < strend && *m != '\n'; m++) ;	    m++;	    if (m >= strend)		break;	    dstr = Str_new(30,m-s);	    str_nset(dstr,s,m-s);	    if (!realarray)		str_2mortal(dstr);	    (void)astore(ary, ++sp, dstr);	    s = m;	}    }    else if (spat->spat_short) {	i = spat->spat_short->str_cur;	if (i == 1) {	    int fold = (spat->spat_flags & SPAT_FOLD);	    i = *spat->spat_short->str_ptr;	    if (fold && isUPPER(i))		i = tolower(i);	    while (--limit) {		if (fold) {		    for ( m = s;			  m < strend && *m != i &&			    (!isUPPER(*m) || tolower(*m) != i);			  m++)			/*SUPPRESS 530*/			;		}		else				/*SUPPRESS 530*/		    for (m = s; m < strend && *m != i; m++) ;		if (m >= strend)		    break;		dstr = Str_new(30,m-s);		str_nset(dstr,s,m-s);		if (!realarray)		    str_2mortal(dstr);		(void)astore(ary, ++sp, dstr);		s = m + 1;	    }	}	else {#ifndef lint	    while (s < strend && --limit &&	      (m=fbminstr((unsigned char*)s, (unsigned char*)strend,		    spat->spat_short)) )#endif	    {		dstr = Str_new(31,m-s);		str_nset(dstr,s,m-s);		if (!realarray)		    str_2mortal(dstr);		(void)astore(ary, ++sp, dstr);		s = m + i;	    }	}    }    else {	maxiters += (strend - s) * spat->spat_regexp->nparens;	while (s < strend && --limit &&	    regexec(spat->spat_regexp, s, strend, orig, 1, Nullstr, TRUE) ) {	    if (spat->spat_regexp->subbase	      && spat->spat_regexp->subbase != orig) {		m = s;		s = orig;		orig = spat->spat_regexp->subbase;		s = orig + (m - s);		strend = s + (strend - m);	    }	    m = spat->spat_regexp->startp[0];	    dstr = Str_new(32,m-s);	    str_nset(dstr,s,m-s);	    if (!realarray)		str_2mortal(dstr);	    (void)astore(ary, ++sp, dstr);	    if (spat->spat_regexp->nparens) {		for (i = 1; i <= spat->spat_regexp->nparens; i++) {		    s = spat->spat_regexp->startp[i];		    m = spat->spat_regexp->endp[i];		    dstr = Str_new(33,m-s);		    str_nset(dstr,s,m-s);		    if (!realarray)			str_2mortal(dstr);		    (void)astore(ary, ++sp, dstr);		}	    }	    s = spat->spat_regexp->endp[0];	}    }    if (realarray)	iters = sp + 1;    else	iters = sp - arglast[0];    if (iters > maxiters)	fatal("Split loop");    if (s < strend || origlimit) {	/* keep field after final delim? */	dstr = Str_new(34,strend-s);	str_nset(dstr,s,strend-s);	if (!realarray)	    str_2mortal(dstr);	(void)astore(ary, ++sp, dstr);	iters++;    }    else {#ifndef I286x	while (iters > 0 && ary->ary_array[sp]->str_cur == 0)	    iters--,sp--;#else	char *zaps;	int   zapb;	if (iters > 0) {		zaps = str_get(afetch(ary,sp,FALSE));		zapb = (int) *zaps;	}		while (iters > 0 && (!zapb)) {	    iters--,sp--;	    if (iters > 0) {		zaps = str_get(afetch(ary,iters-1,FALSE));		zapb = (int) *zaps;	    }	}#endif    }    if (realarray) {	ary->ary_fill = sp;	if (gimme == G_ARRAY) {	    sp++;	    astore(stack, arglast[0] + 1 + sp, Nullstr);	    Copy(ary->ary_array, stack->ary_array + arglast[0] + 1, sp, STR*);	    return arglast[0] + sp;	}    }    else {	if (gimme == G_ARRAY)	    return sp;    }    sp = arglast[0] + 1;    str_numset(str,(double)iters);    STABSET(str);    st[sp] = str;    return sp;}intdo_unpack(str,gimme,arglast)STR *str;int gimme;int *arglast;{    STR **st = stack->ary_array;    register int sp = arglast[0] + 1;    register char *pat = str_get(st[sp++]);    register char *s = str_get(st[sp]);    char *strend = s + st[sp--]->str_cur;    char *strbeg = s;    register char *patend = pat + st[sp]->str_cur;    int datumtype;    register int len;    register int bits;    /* These must not be in registers: */    short ashort;    int aint;    long along;#ifdef QUAD    quad aquad;#endif    unsigned short aushort;    unsigned int auint;    unsigned long aulong;#ifdef QUAD    unsigned quad auquad;#endif    char *aptr;    float afloat;    double adouble;    int checksum = 0;    unsigned long culong;    double cdouble;    if (gimme != G_ARRAY) {		/* arrange to do first one only */	/*SUPPRESS 530*/	for (patend = pat; !isALPHA(*patend) || *patend == 'x'; patend++) ;	if (index("aAbBhH", *patend) || *pat == '%') {	    patend++;	    while (isDIGIT(*patend) || *patend == '*')		patend++;	}	else	    patend++;    }    sp--;    while (pat < patend) {      reparse:	datumtype = *pat++;	if (pat >= patend)	    len = 1;	else if (*pat == '*') {	    len = strend - strbeg;	/* long enough */	    pat++;	}	else if (isDIGIT(*pat)) {	    len = *pat++ - '0';	    while (isDIGIT(*pat))		len = (len * 10) + (*pat++ - '0');	}	else	    len = (datumtype != '@');	switch(datumtype) {	default:	    break;	case '%':	    if (len == 1 && pat[-1] != '1')

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -