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

📄 doarg.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $RCSfile: doarg.c,v $$Revision: 4.0.1.8 $$Date: 1993/02/05 19:32: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: doarg.c,v $ * Revision 4.0.1.8  1993/02/05  19:32:27  lwall * patch36: substitution didn't always invalidate numericity * * Revision 4.0.1.7  92/06/11  21:07:11  lwall * patch34: join with null list attempted negative allocation * patch34: sprintf("%6.4s", "abcdefg") didn't print "abcd  " *  * Revision 4.0.1.6  92/06/08  12:34:30  lwall * patch20: removed implicit int declarations on funcions * patch20: pattern modifiers i and o didn't interact right * patch20: join() now pre-extends target string to avoid excessive copying * patch20: fixed confusion between a *var's real name and its effective name * patch20: subroutines didn't localize $`, $&, $', $1 et al correctly * patch20: usersub routines didn't reclaim temp values soon enough * patch20: ($<,$>) = ... didn't work on some architectures * patch20: added Atari ST portability *  * Revision 4.0.1.5  91/11/11  16:31:58  lwall * patch19: added little-endian pack/unpack options *  * Revision 4.0.1.4  91/11/05  16:35:06  lwall * patch11: /$foo/o optimizer could access deallocated data * patch11: minimum match length calculation in regexp is now cumulative * patch11: added some support for 64-bit integers * patch11: prepared for ctype implementations that don't define isascii() * patch11: sprintf() now supports any length of s field * patch11: indirect subroutine calls through magic vars (e.g. &$1) didn't work * patch11: defined(&$foo) and undef(&$foo) didn't work *  * Revision 4.0.1.3  91/06/10  01:18:41  lwall * patch10: pack(hh,1) dumped core *  * Revision 4.0.1.2  91/06/07  10:42:17  lwall * patch4: new copyright notice * 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: added global modifier for pattern matches * patch4: undef @array disabled "@array" interpolation * patch4: chop("") was returning "\0" rather than "" * patch4: vector logical operations &, | and ^ sometimes returned null string * patch4: syscall couldn't pass numbers with most significant bit set on sparcs *  * Revision 4.0.1.1  91/04/11  17:40:14  lwall * patch1: fixed undefined environ problem * patch1: fixed debugger coredump on subroutines *  * Revision 4.0  91/03/20  01:06:42  lwall * 4.0 baseline. *  */#include "EXTERN.h"#include "perl.h"#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)#include <signal.h>#endifextern unsigned char fold[];#ifdef BUGGY_MSC #pragma function(memcmp)#endif /* BUGGY_MSC */static void doencodes();intdo_subst(str,arg,sp)STR *str;ARG *arg;int sp;{    register SPAT *spat;    SPAT *rspat;    register STR *dstr;    register char *s = str_get(str);    char *strend = s + str->str_cur;    register char *m;    char *c;    register char *d;    int clen;    int iters = 0;    int maxiters = (strend - s) + 10;    register int i;    bool once;    char *orig;    int safebase;    rspat = spat = arg[2].arg_ptr.arg_spat;    if (!spat || !s)	fatal("panic: do_subst");    else if (spat->spat_runtime) {	nointrp = "|)";	(void)eval(spat->spat_runtime,G_SCALAR,sp);	m = str_get(dstr = stack->ary_array[sp+1]);	nointrp = "";	if (spat->spat_regexp) {	    regfree(spat->spat_regexp);	    spat->spat_regexp = Null(REGEXP*);	/* required if regcomp pukes */	}	spat->spat_regexp = regcomp(m,m+dstr->str_cur,	    spat->spat_flags & SPAT_FOLD);	if (spat->spat_flags & SPAT_KEEP) {	    if (!(spat->spat_flags & SPAT_FOLD))		scanconst(spat, m, dstr->str_cur);	    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);            }	}    }#ifdef DEBUGGING    if (debug & 8) {	deb("2.SPAT /%s/\n",spat->spat_regexp->precomp);    }#endif    safebase = ((!spat->spat_regexp || !spat->spat_regexp->nparens) &&      !sawampersand);    if (!spat->spat_regexp->prelen && lastspat)	spat = lastspat;    orig = m = s;    if (hint) {	if (hint < s || hint > strend)	    fatal("panic: hint in do_match");	s = hint;	hint = Nullch;	if (spat->spat_regexp->regback >= 0) {	    s -= spat->spat_regexp->regback;	    if (s < m)		s = m;	}	else	    s = m;    }    else if (spat->spat_short) {	if (spat->spat_flags & SPAT_SCANFIRST) {	    if (str->str_pok & SP_STUDIED) {		if (screamfirst[spat->spat_short->str_rare] < 0)		    goto nope;		else if (!(s = screaminstr(str,spat->spat_short)))		    goto nope;	    }#ifndef lint	    else if (!(s = fbminstr((unsigned char*)s, (unsigned char*)strend,	      spat->spat_short)))		goto nope;#endif	    if (s && spat->spat_regexp->regback >= 0) {		++spat->spat_short->str_u.str_useful;		s -= spat->spat_regexp->regback;		if (s < m)		    s = m;	    }	    else		s = m;	}	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 */	}    }    once = !(rspat->spat_flags & SPAT_GLOBAL);    if (rspat->spat_flags & SPAT_CONST) {	/* known replacement string? */	if ((rspat->spat_repl[1].arg_type & A_MASK) == A_SINGLE)	    dstr = rspat->spat_repl[1].arg_ptr.arg_str;	else {					/* constant over loop, anyway */	    (void)eval(rspat->spat_repl,G_SCALAR,sp);	    dstr = stack->ary_array[sp+1];	}	c = str_get(dstr);	clen = dstr->str_cur;	if (clen <= spat->spat_regexp->minlen) {					/* can do inplace substitution */	    if (regexec(spat->spat_regexp, s, strend, orig, 0,	      str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {		if (spat->spat_regexp->subbase) /* oops, no we can't */		    goto long_way;		d = s;		lastspat = spat;		str->str_pok = SP_VALID;	/* disable possible screamer */		if (once) {		    m = spat->spat_regexp->startp[0];		    d = spat->spat_regexp->endp[0];		    s = orig;		    if (m - s > strend - d) {	/* faster to shorten from end */			if (clen) {			    Copy(c, m, clen, char);			    m += clen;			}			i = strend - d;			if (i > 0) {			    Move(d, m, i, char);			    m += i;			}			*m = '\0';			str->str_cur = m - s;			STABSET(str);			str_numset(arg->arg_ptr.arg_str, 1.0);			stack->ary_array[++sp] = arg->arg_ptr.arg_str;			str->str_nok = 0;			return sp;		    }		    /*SUPPRESS 560*/		    else if (i = m - s) {	/* faster from front */			d -= clen;			m = d;			str_chop(str,d-i);			s += i;			while (i--)			    *--d = *--s;			if (clen)			    Copy(c, m, clen, char);			STABSET(str);			str_numset(arg->arg_ptr.arg_str, 1.0);			stack->ary_array[++sp] = arg->arg_ptr.arg_str;			str->str_nok = 0;			return sp;		    }		    else if (clen) {			d -= clen;			str_chop(str,d);			Copy(c,d,clen,char);			STABSET(str);			str_numset(arg->arg_ptr.arg_str, 1.0);			stack->ary_array[++sp] = arg->arg_ptr.arg_str;			str->str_nok = 0;			return sp;		    }		    else {			str_chop(str,d);			STABSET(str);			str_numset(arg->arg_ptr.arg_str, 1.0);			stack->ary_array[++sp] = arg->arg_ptr.arg_str;			str->str_nok = 0;			return sp;		    }		    /* NOTREACHED */		}		do {		    if (iters++ > maxiters)			fatal("Substitution loop");		    m = spat->spat_regexp->startp[0];		    /*SUPPRESS 560*/		    if (i = m - s) {			if (s != d)			    Move(s,d,i,char);			d += i;		    }		    if (clen) {			Copy(c,d,clen,char);			d += clen;		    }		    s = spat->spat_regexp->endp[0];		} while (regexec(spat->spat_regexp, s, strend, orig, s == m,		    Nullstr, TRUE));	/* (don't match same null twice) */		if (s != d) {		    i = strend - s;		    str->str_cur = d - str->str_ptr + i;		    Move(s,d,i+1,char);		/* include the Null */		}		STABSET(str);		str_numset(arg->arg_ptr.arg_str, (double)iters);		stack->ary_array[++sp] = arg->arg_ptr.arg_str;		str->str_nok = 0;		return sp;	    }	    str_numset(arg->arg_ptr.arg_str, 0.0);	    stack->ary_array[++sp] = arg->arg_ptr.arg_str;	    return sp;	}    }    else	c = Nullch;    if (regexec(spat->spat_regexp, s, strend, orig, 0,      str->str_pok & SP_STUDIED ? str : Nullstr, safebase)) {    long_way:	dstr = Str_new(25,str_len(str));	str_nset(dstr,m,s-m);	if (spat->spat_regexp->subbase)	    curspat = spat;	lastspat = spat;	do {	    if (iters++ > maxiters)		fatal("Substitution loop");	    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];	    str_ncat(dstr,s,m-s);	    s = spat->spat_regexp->endp[0];	    if (c) {		if (clen)		    str_ncat(dstr,c,clen);	    }	    else {		char *mysubbase = spat->spat_regexp->subbase;		spat->spat_regexp->subbase = Nullch;	/* so recursion works */		(void)eval(rspat->spat_repl,G_SCALAR,sp);		str_scat(dstr,stack->ary_array[sp+1]);		if (spat->spat_regexp->subbase)		    Safefree(spat->spat_regexp->subbase);		spat->spat_regexp->subbase = mysubbase;	    }	    if (once)		break;	} while (regexec(spat->spat_regexp, s, strend, orig, s == m, Nullstr,	    safebase));	str_ncat(dstr,s,strend - s);	str_replace(str,dstr);	STABSET(str);	str_numset(arg->arg_ptr.arg_str, (double)iters);	stack->ary_array[++sp] = arg->arg_ptr.arg_str;	str->str_nok = 0;	return sp;    }    str_numset(arg->arg_ptr.arg_str, 0.0);    stack->ary_array[++sp] = arg->arg_ptr.arg_str;    return sp;nope:    ++spat->spat_short->str_u.str_useful;    str_numset(arg->arg_ptr.arg_str, 0.0);    stack->ary_array[++sp] = arg->arg_ptr.arg_str;    return sp;}#ifdef BUGGY_MSC #pragma intrinsic(memcmp)#endif /* BUGGY_MSC */intdo_trans(str,arg)STR *str;ARG *arg;{    register short *tbl;    register char *s;    register int matches = 0;    register int ch;    register char *send;    register char *d;    register int squash = arg[2].arg_len & 1;    tbl = (short*) arg[2].arg_ptr.arg_cval;    s = str_get(str);    send = s + str->str_cur;    if (!tbl || !s)	fatal("panic: do_trans");#ifdef DEBUGGING    if (debug & 8) {	deb("2.TBL\n");    }#endif    if (!arg[2].arg_len) {	while (s < send) {	    if ((ch = tbl[*s & 0377]) >= 0) {		matches++;		*s = ch;	    }	    s++;	}    }    else {	d = s;	while (s < send) {	    if ((ch = tbl[*s & 0377]) >= 0) {		*d = ch;		if (matches++ && squash) {		    if (d[-1] == *d)			matches--;		    else			d++;		}		else		    d++;	    }	    else if (ch == -1)		/* -1 is unmapped character */		*d++ = *s;		/* -2 is delete character */	    s++;	}	matches += send - d;	/* account for disappeared chars */	*d = '\0';	str->str_cur = d - str->str_ptr;    }    STABSET(str);    return matches;}voiddo_join(str,arglast)register STR *str;int *arglast;{    register STR **st = stack->ary_array;    int sp = arglast[1];    register int items = arglast[2] - sp;    register char *delim = str_get(st[sp]);    register STRLEN len;    int delimlen = st[sp]->str_cur;    st += sp + 1;    len = (items > 0 ? (delimlen * (items - 1) ) : 0);    if (str->str_len < len + items) {	/* current length is way too short */	while (items-- > 0) {	    if (*st)		len += (*st)->str_cur;	    st++;	}	STR_GROW(str, len + 1);		/* so try to pre-extend */	items = arglast[2] - sp;	st -= items;    }    if (items-- > 0)	str_sset(str, *st++);    else	str_set(str,"");    len = delimlen;    if (len) {	for (; items > 0; items--,st++) {	    str_ncat(str,delim,len);	    str_scat(str,*st);	}    }    else {	for (; items > 0; items--,st++)	    str_scat(str,*st);    }    STABSET(str);}voiddo_pack(str,arglast)register STR *str;int *arglast;{    register STR **st = stack->ary_array;    register int sp = arglast[1];    register int items;    register char *pat = str_get(st[sp]);    register char *patend = pat + st[sp]->str_cur;    register int len;    int datumtype;    STR *fromstr;    /*SUPPRESS 442*/    static char *null10 = "\0\0\0\0\0\0\0\0\0\0";    static char *space10 = "          ";    /* These must not be in registers: */    char achar;    short ashort;    int aint;    unsigned int auint;    long along;    unsigned long aulong;#ifdef QUAD    quad aquad;    unsigned quad auquad;#endif    char *aptr;    float afloat;    double adouble;    items = arglast[2] - sp;    st += ++sp;    str_nset(str,"",0);    while (pat < patend) {#define NEXTFROM (items-- > 0 ? *st++ : &str_no)	datumtype = *pat++;	if (*pat == '*') {	    len = index("@Xxu",datumtype) ? 0 : items;	    pat++;	}	else if (isDIGIT(*pat)) {	    len = *pat++ - '0';	    while (isDIGIT(*pat))		len = (len * 10) + (*pat++ - '0');	}	else	    len = 1;	switch(datumtype) {	default:	    break;	case '%':	    fatal("% may only be used in unpack");	case '@':	    len -= str->str_cur;	    if (len > 0)		goto grow;	    len = -len;	    if (len > 0)		goto shrink;	    break;	case 'X':	  shrink:	    if (str->str_cur < len)		fatal("X outside of string");	    str->str_cur -= len;	    str->str_ptr[str->str_cur] = '\0';	    break;	case 'x':	  grow:	    while (len >= 10) {		str_ncat(str,null10,10);		len -= 10;	    }	    str_ncat(str,null10,len);	    break;	case 'A':	case 'a':	    fromstr = NEXTFROM;	    aptr = str_get(fromstr);	    if (pat[-1] == '*')		len = fromstr->str_cur;	    if (fromstr->str_cur > len)		str_ncat(str,aptr,len);	    else {		str_ncat(str,aptr,fromstr->str_cur);		len -= fromstr->str_cur;		if (datumtype == 'A') {		    while (len >= 10) {			str_ncat(str,space10,10);			len -= 10;		    }		    str_ncat(str,space10,len);		}		else {		    while (len >= 10) {			str_ncat(str,null10,10);			len -= 10;		    }		    str_ncat(str,null10,len);		}	    }	    break;	case 'B':	case 'b':	    {		char *savepat = pat;		int saveitems;		fromstr = NEXTFROM;		saveitems = items;		aptr = str_get(fromstr);		if (pat[-1] == '*')		    len = fromstr->str_cur;		pat = aptr;		aint = str->str_cur;		str->str_cur += (len+7)/8;		STR_GROW(str, str->str_cur + 1);		aptr = str->str_ptr + aint;		if (len > fromstr->str_cur)		    len = fromstr->str_cur;		aint = len;		items = 0;		if (datumtype == 'B') {		    for (len = 0; len++ < aint;) {			items |= *pat++ & 1;			if (len & 7)			    items <<= 1;			else {			    *aptr++ = items & 0xff;			    items = 0;			}		    }		}		else {		    for (len = 0; len++ < aint;) {			if (*pat++ & 1)			    items |= 128;			if (len & 7)			    items >>= 1;			else {			    *aptr++ = items & 0xff;			    items = 0;			}		    }		}		if (aint & 7) {		    if (datumtype == 'B')			items <<= 7 - (aint & 7);		    else			items >>= 7 - (aint & 7);		    *aptr++ = items & 0xff;		}		pat = str->str_ptr + str->str_cur;		while (aptr <= pat)		    *aptr++ = '\0';		pat = savepat;		items = saveitems;	    }	    break;	case 'H':	case 'h':

⌨️ 快捷键说明

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