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

📄 dumper.xs

📁 UNIX下perl实现代码
💻 XS
📖 第 1 页 / 共 2 页
字号:
#define PERL_NO_GET_CONTEXT#include "EXTERN.h"#include "perl.h"#include "XSUB.h"#ifndef PERL_VERSION#include "patchlevel.h"#define PERL_VERSION PATCHLEVEL#endif#if PERL_VERSION < 5#  ifndef PL_sv_undef#    define PL_sv_undef	sv_undef#  endif#  ifndef ERRSV#    define ERRSV	GvSV(errgv)#  endif#  ifndef newSVpvn#    define newSVpvn	newSVpv#  endif#endifstatic I32 num_q (char *s, STRLEN slen);static I32 esc_q (char *dest, char *src, STRLEN slen);static SV *sv_x (pTHX_ SV *sv, char *str, STRLEN len, I32 n);static I32 DD_dump (pTHX_ SV *val, char *name, STRLEN namelen, SV *retval,		    HV *seenhv, AV *postav, I32 *levelp, I32 indent,		    SV *pad, SV *xpad, SV *apad, SV *sep,		    SV *freezer, SV *toaster,		    I32 purity, I32 deepcopy, I32 quotekeys, SV *bless,		    I32 maxdepth);/* does a string need to be protected? */static I32needs_quote(register char *s){TOP:    if (s[0] == ':') {	if (*++s) {	    if (*s++ != ':')		return 1;	}	else	    return 1;    }    if (isIDFIRST(*s)) {	while (*++s)	    if (!isALNUM(*s)) {		if (*s == ':')		    goto TOP;		else		    return 1;	    }    }    else 	return 1;    return 0;}/* count the number of "'"s and "\"s in string */static I32num_q(register char *s, register STRLEN slen){    register I32 ret = 0;    while (slen > 0) {	if (*s == '\'' || *s == '\\')	    ++ret;	++s;	--slen;    }    return ret;}/* returns number of chars added to escape "'"s and "\"s in s *//* slen number of characters in s will be escaped *//* destination must be long enough for additional chars */static I32esc_q(register char *d, register char *s, register STRLEN slen){    register I32 ret = 0;        while (slen > 0) {	switch (*s) {	case '\'':	case '\\':	    *d = '\\';	    ++d; ++ret;	default:	    *d = *s;	    ++d; ++s; --slen;	    break;	}    }    return ret;}/* append a repeated string to an SV */static SV *sv_x(pTHX_ SV *sv, register char *str, STRLEN len, I32 n){    if (sv == Nullsv)	sv = newSVpvn("", 0);    else	assert(SvTYPE(sv) >= SVt_PV);    if (n > 0) {	SvGROW(sv, len*n + SvCUR(sv) + 1);	if (len == 1) {	    char *start = SvPVX(sv) + SvCUR(sv);	    SvCUR(sv) += n;	    start[n] = '\0';	    while (n > 0)		start[--n] = str[0];	}	else	    while (n > 0) {		sv_catpvn(sv, str, len);		--n;	    }    }    return sv;}/* * This ought to be split into smaller functions. (it is one long function since * it exactly parallels the perl version, which was one long thing for * efficiency raisins.)  Ugggh! */static I32DD_dump(pTHX_ SV *val, char *name, STRLEN namelen, SV *retval, HV *seenhv,	AV *postav, I32 *levelp, I32 indent, SV *pad, SV *xpad,	SV *apad, SV *sep, SV *freezer, SV *toaster, I32 purity,	I32 deepcopy, I32 quotekeys, SV *bless, I32 maxdepth){    char tmpbuf[128];    U32 i;    char *c, *r, *realpack, id[128];    SV **svp;    SV *sv, *ipad, *ival;    SV *blesspad = Nullsv;    AV *seenentry = Nullav;    char *iname;    STRLEN inamelen, idlen = 0;    U32 flags;    U32 realtype;    if (!val)	return 0;    flags = SvFLAGS(val);    realtype = SvTYPE(val);        if (SvGMAGICAL(val))        mg_get(val);    if (SvROK(val)) {	if (SvOBJECT(SvRV(val)) && freezer &&	    SvPOK(freezer) && SvCUR(freezer))	{	    dSP; ENTER; SAVETMPS; PUSHMARK(sp);	    XPUSHs(val); PUTBACK;	    i = perl_call_method(SvPVX(freezer), G_EVAL|G_SCALAR);	    SPAGAIN;	    if (SvTRUE(ERRSV))		warn("WARNING(Freezer method call failed): %s",		     SvPVX(ERRSV));	    else if (i)		val = newSVsv(POPs);	    PUTBACK; FREETMPS; LEAVE;	    if (i)		(void)sv_2mortal(val);	}		ival = SvRV(val);	flags = SvFLAGS(ival);	realtype = SvTYPE(ival);        (void) sprintf(id, "0x%lx", (unsigned long)ival);	idlen = strlen(id);	if (SvOBJECT(ival))	    realpack = HvNAME(SvSTASH(ival));	else	    realpack = Nullch;	/* if it has a name, we need to either look it up, or keep a tab	 * on it so we know when we hit it later	 */	if (namelen) {	    if ((svp = hv_fetch(seenhv, id, idlen, FALSE))		&& (sv = *svp) && SvROK(sv) && (seenentry = (AV*)SvRV(sv)))	    {		SV *othername;		if ((svp = av_fetch(seenentry, 0, FALSE))		    && (othername = *svp))		{		    if (purity && *levelp > 0) {			SV *postentry;						if (realtype == SVt_PVHV)			    sv_catpvn(retval, "{}", 2);			else if (realtype == SVt_PVAV)			    sv_catpvn(retval, "[]", 2);			else			    sv_catpvn(retval, "do{my $o}", 9);			postentry = newSVpvn(name, namelen);			sv_catpvn(postentry, " = ", 3);			sv_catsv(postentry, othername);			av_push(postav, postentry);		    }		    else {			if (name[0] == '@' || name[0] == '%') {			    if ((SvPVX(othername))[0] == '\\' &&				(SvPVX(othername))[1] == name[0]) {				sv_catpvn(retval, SvPVX(othername)+1,					  SvCUR(othername)-1);			    }			    else {				sv_catpvn(retval, name, 1);				sv_catpvn(retval, "{", 1);				sv_catsv(retval, othername);				sv_catpvn(retval, "}", 1);			    }			}			else			    sv_catsv(retval, othername);		    }		    return 1;		}		else {		    warn("ref name not found for %s", id);		    return 0;		}	    }	    else {   /* store our name and continue */		SV *namesv;		if (name[0] == '@' || name[0] == '%') {		    namesv = newSVpvn("\\", 1);		    sv_catpvn(namesv, name, namelen);		}		else if (realtype == SVt_PVCV && name[0] == '*') {		    namesv = newSVpvn("\\", 2);		    sv_catpvn(namesv, name, namelen);		    (SvPVX(namesv))[1] = '&';		}		else		    namesv = newSVpvn(name, namelen);		seenentry = newAV();		av_push(seenentry, namesv);		(void)SvREFCNT_inc(val);		av_push(seenentry, val);		(void)hv_store(seenhv, id, strlen(id),			       newRV((SV*)seenentry), 0);		SvREFCNT_dec(seenentry);	    }	}	if (realpack && *realpack == 'R' && strEQ(realpack, "Regexp")) {	    STRLEN rlen;	    char *rval = SvPV(val, rlen);	    char *slash = strchr(rval, '/');	    sv_catpvn(retval, "qr/", 3);	    while (slash) {		sv_catpvn(retval, rval, slash-rval);		sv_catpvn(retval, "\\/", 2);		rlen -= slash-rval+1;		rval = slash+1;		slash = strchr(rval, '/');	    }	    sv_catpvn(retval, rval, rlen);	    sv_catpvn(retval, "/", 1);	    return 1;	}	/* If purity is not set and maxdepth is set, then check depth:	 * if we have reached maximum depth, return the string	 * representation of the thing we are currently examining	 * at this depth (i.e., 'Foo=ARRAY(0xdeadbeef)'). 	 */	if (!purity && maxdepth > 0 && *levelp >= maxdepth) {	    STRLEN vallen;	    char *valstr = SvPV(val,vallen);	    sv_catpvn(retval, "'", 1);	    sv_catpvn(retval, valstr, vallen);	    sv_catpvn(retval, "'", 1);	    return 1;	}	if (realpack) {				/* we have a blessed ref */	    STRLEN blesslen;	    char *blessstr = SvPV(bless, blesslen);	    sv_catpvn(retval, blessstr, blesslen);	    sv_catpvn(retval, "( ", 2);	    if (indent >= 2) {		blesspad = apad;		apad = newSVsv(apad);		sv_x(aTHX_ apad, " ", 1, blesslen+2);	    }	}	(*levelp)++;	ipad = sv_x(aTHX_ Nullsv, SvPVX(xpad), SvCUR(xpad), *levelp);	if (realtype <= SVt_PVBM) {			     /* scalar ref */	    SV *namesv = newSVpvn("${", 2);	    sv_catpvn(namesv, name, namelen);	    sv_catpvn(namesv, "}", 1);	    if (realpack) {				     /* blessed */ 		sv_catpvn(retval, "do{\\(my $o = ", 13);		DD_dump(aTHX_ ival, SvPVX(namesv), SvCUR(namesv), retval, seenhv,			postav, levelp,	indent, pad, xpad, apad, sep,			freezer, toaster, purity, deepcopy, quotekeys, bless,			maxdepth);		sv_catpvn(retval, ")}", 2);	    }						     /* plain */	    else {		sv_catpvn(retval, "\\", 1);		DD_dump(aTHX_ ival, SvPVX(namesv), SvCUR(namesv), retval, seenhv,			postav, levelp,	indent, pad, xpad, apad, sep,			freezer, toaster, purity, deepcopy, quotekeys, bless,			maxdepth);	    }	    SvREFCNT_dec(namesv);	}	else if (realtype == SVt_PVGV) {		     /* glob ref */	    SV *namesv = newSVpvn("*{", 2);	    sv_catpvn(namesv, name, namelen);	    sv_catpvn(namesv, "}", 1);	    sv_catpvn(retval, "\\", 1);	    DD_dump(aTHX_ ival, SvPVX(namesv), SvCUR(namesv), retval, seenhv,		    postav, levelp,	indent, pad, xpad, apad, sep,		    freezer, toaster, purity, deepcopy, quotekeys, bless,		    maxdepth);	    SvREFCNT_dec(namesv);	}	else if (realtype == SVt_PVAV) {	    SV *totpad;	    I32 ix = 0;	    I32 ixmax = av_len((AV *)ival);	    	    SV *ixsv = newSViv(0);	    /* allowing for a 24 char wide array index */	    New(0, iname, namelen+28, char);	    (void)strcpy(iname, name);	    inamelen = namelen;	    if (name[0] == '@') {		sv_catpvn(retval, "(", 1);		iname[0] = '$';	    }	    else {		sv_catpvn(retval, "[", 1);		/* omit "->" in $foo{bar}->[0], but not in ${$foo}->[0] */		/*if (namelen > 0		    && name[namelen-1] != ']' && name[namelen-1] != '}'		    && (namelen < 4 || (name[1] != '{' && name[2] != '{')))*/		if ((namelen > 0		     && name[namelen-1] != ']' && name[namelen-1] != '}')		    || (namelen > 4		        && (name[1] == '{'			    || (name[0] == '\\' && name[2] == '{'))))		{		    iname[inamelen++] = '-'; iname[inamelen++] = '>';		    iname[inamelen] = '\0';		}	    }	    if (iname[0] == '*' && iname[inamelen-1] == '}' && inamelen >= 8 &&		(instr(iname+inamelen-8, "{SCALAR}") ||		 instr(iname+inamelen-7, "{ARRAY}") ||		 instr(iname+inamelen-6, "{HASH}"))) {		iname[inamelen++] = '-'; iname[inamelen++] = '>';	    }	    iname[inamelen++] = '['; iname[inamelen] = '\0';	    totpad = newSVsv(sep);	    sv_catsv(totpad, pad);	    sv_catsv(totpad, apad);	    for (ix = 0; ix <= ixmax; ++ix) {		STRLEN ilen;		SV *elem;		svp = av_fetch((AV*)ival, ix, FALSE);		if (svp)		    elem = *svp;		else		    elem = &PL_sv_undef;				ilen = inamelen;		sv_setiv(ixsv, ix);                (void) sprintf(iname+ilen, "%"IVdf, (IV)ix);		ilen = strlen(iname);		iname[ilen++] = ']'; iname[ilen] = '\0';		if (indent >= 3) {		    sv_catsv(retval, totpad);		    sv_catsv(retval, ipad);		    sv_catpvn(retval, "#", 1);		    sv_catsv(retval, ixsv);		}		sv_catsv(retval, totpad);		sv_catsv(retval, ipad);		DD_dump(aTHX_ elem, iname, ilen, retval, seenhv, postav,			levelp,	indent, pad, xpad, apad, sep,			freezer, toaster, purity, deepcopy, quotekeys, bless,			maxdepth);		if (ix < ixmax)		    sv_catpvn(retval, ",", 1);	    }	    if (ixmax >= 0) {		SV *opad = sv_x(aTHX_ Nullsv, SvPVX(xpad), SvCUR(xpad), (*levelp)-1);		sv_catsv(retval, totpad);		sv_catsv(retval, opad);		SvREFCNT_dec(opad);	    }	    if (name[0] == '@')		sv_catpvn(retval, ")", 1);	    else		sv_catpvn(retval, "]", 1);	    SvREFCNT_dec(ixsv);	    SvREFCNT_dec(totpad);	    Safefree(iname);	}	else if (realtype == SVt_PVHV) {	    SV *totpad, *newapad;	    SV *iname, *sname;	    HE *entry;	    char *key;	    I32 klen;	    SV *hval;	    	    iname = newSVpvn(name, namelen);	    if (name[0] == '%') {		sv_catpvn(retval, "(", 1);		(SvPVX(iname))[0] = '$';	    }	    else {		sv_catpvn(retval, "{", 1);		/* omit "->" in $foo[0]->{bar}, but not in ${$foo}->{bar} */		if ((namelen > 0		     && name[namelen-1] != ']' && name[namelen-1] != '}')		    || (namelen > 4		        && (name[1] == '{'			    || (name[0] == '\\' && name[2] == '{'))))		{		    sv_catpvn(iname, "->", 2);		}	    }	    if (name[0] == '*' && name[namelen-1] == '}' && namelen >= 8 &&		(instr(name+namelen-8, "{SCALAR}") ||		 instr(name+namelen-7, "{ARRAY}") ||		 instr(name+namelen-6, "{HASH}"))) {		sv_catpvn(iname, "->", 2);	    }	    sv_catpvn(iname, "{", 1);

⌨️ 快捷键说明

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