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

📄 b.xs

📁 UNIX下perl实现代码
💻 XS
📖 第 1 页 / 共 2 页
字号:
/*	B.xs * *	Copyright (c) 1996 Malcolm Beattie * *	You may distribute under the terms of either the GNU General Public *	License or the Artistic License, as specified in the README file. * */#define PERL_NO_GET_CONTEXT#include "EXTERN.h"#include "perl.h"#include "XSUB.h"#ifdef PERL_OBJECT#undef PL_op_name#undef PL_opargs #undef PL_op_desc#define PL_op_name (get_op_names())#define PL_opargs (get_opargs())#define PL_op_desc (get_op_descs())#endif#ifdef PerlIOtypedef PerlIO * InputStream;#elsetypedef FILE * InputStream;#endifstatic char *svclassnames[] = {    "B::NULL",    "B::IV",    "B::NV",    "B::RV",    "B::PV",    "B::PVIV",    "B::PVNV",    "B::PVMG",    "B::BM",    "B::PVLV",    "B::AV",    "B::HV",    "B::CV",    "B::GV",    "B::FM",    "B::IO",};typedef enum {    OPc_NULL,	/* 0 */    OPc_BASEOP,	/* 1 */    OPc_UNOP,	/* 2 */    OPc_BINOP,	/* 3 */    OPc_LOGOP,	/* 4 */    OPc_LISTOP,	/* 5 */    OPc_PMOP,	/* 6 */    OPc_SVOP,	/* 7 */    OPc_PADOP,	/* 8 */    OPc_PVOP,	/* 9 */    OPc_CVOP,	/* 10 */    OPc_LOOP,	/* 11 */    OPc_COP	/* 12 */} opclass;static char *opclassnames[] = {    "B::NULL",    "B::OP",    "B::UNOP",    "B::BINOP",    "B::LOGOP",    "B::LISTOP",    "B::PMOP",    "B::SVOP",    "B::PADOP",    "B::PVOP",    "B::CVOP",    "B::LOOP",    "B::COP"	};static int walkoptree_debug = 0;	/* Flag for walkoptree debug hook */static SV *specialsv_list[6];static opclasscc_opclass(pTHX_ OP *o){    if (!o)	return OPc_NULL;    if (o->op_type == 0)	return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;    if (o->op_type == OP_SASSIGN)	return ((o->op_private & OPpASSIGN_BACKWARDS) ? OPc_UNOP : OPc_BINOP);#ifdef USE_ITHREADS    if (o->op_type == OP_GV || o->op_type == OP_GVSV || o->op_type == OP_AELEMFAST)	return OPc_PADOP;#endif    switch (PL_opargs[o->op_type] & OA_CLASS_MASK) {    case OA_BASEOP:	return OPc_BASEOP;    case OA_UNOP:	return OPc_UNOP;    case OA_BINOP:	return OPc_BINOP;    case OA_LOGOP:	return OPc_LOGOP;    case OA_LISTOP:	return OPc_LISTOP;    case OA_PMOP:	return OPc_PMOP;    case OA_SVOP:	return OPc_SVOP;    case OA_PADOP:	return OPc_PADOP;    case OA_PVOP_OR_SVOP:        /*         * Character translations (tr///) are usually a PVOP, keeping a          * pointer to a table of shorts used to look up translations.         * Under utf8, however, a simple table isn't practical; instead,         * the OP is an SVOP, and the SV is a reference to a swash         * (i.e., an RV pointing to an HV).         */	return (o->op_private & (OPpTRANS_TO_UTF|OPpTRANS_FROM_UTF))		? OPc_SVOP : OPc_PVOP;    case OA_LOOP:	return OPc_LOOP;    case OA_COP:	return OPc_COP;    case OA_BASEOP_OR_UNOP:	/*	 * UNI(OP_foo) in toke.c returns token UNI or FUNC1 depending on	 * whether parens were seen. perly.y uses OPf_SPECIAL to	 * signal whether a BASEOP had empty parens or none.	 * Some other UNOPs are created later, though, so the best	 * test is OPf_KIDS, which is set in newUNOP.	 */	return (o->op_flags & OPf_KIDS) ? OPc_UNOP : OPc_BASEOP;    case OA_FILESTATOP:	/*	 * The file stat OPs are created via UNI(OP_foo) in toke.c but use	 * the OPf_REF flag to distinguish between OP types instead of the	 * usual OPf_SPECIAL flag. As usual, if OPf_KIDS is set, then we	 * return OPc_UNOP so that walkoptree can find our children. If	 * OPf_KIDS is not set then we check OPf_REF. Without OPf_REF set	 * (no argument to the operator) it's an OP; with OPf_REF set it's	 * an SVOP (and op_sv is the GV for the filehandle argument).	 */	return ((o->op_flags & OPf_KIDS) ? OPc_UNOP :#ifdef USE_ITHREADS		(o->op_flags & OPf_REF) ? OPc_PADOP : OPc_BASEOP);#else		(o->op_flags & OPf_REF) ? OPc_SVOP : OPc_BASEOP);#endif    case OA_LOOPEXOP:	/*	 * next, last, redo, dump and goto use OPf_SPECIAL to indicate that a	 * label was omitted (in which case it's a BASEOP) or else a term was	 * seen. In this last case, all except goto are definitely PVOP but	 * goto is either a PVOP (with an ordinary constant label), an UNOP	 * with OPf_STACKED (with a non-constant non-sub) or an UNOP for	 * OP_REFGEN (with goto &sub) in which case OPf_STACKED also seems to	 * get set.	 */	if (o->op_flags & OPf_STACKED)	    return OPc_UNOP;	else if (o->op_flags & OPf_SPECIAL)	    return OPc_BASEOP;	else	    return OPc_PVOP;    }    warn("can't determine class of operator %s, assuming BASEOP\n",	 PL_op_name[o->op_type]);    return OPc_BASEOP;}static char *cc_opclassname(pTHX_ OP *o){    return opclassnames[cc_opclass(aTHX_ o)];}static SV *make_sv_object(pTHX_ SV *arg, SV *sv){    char *type = 0;    IV iv;        for (iv = 0; iv < sizeof(specialsv_list)/sizeof(SV*); iv++) {	if (sv == specialsv_list[iv]) {	    type = "B::SPECIAL";	    break;	}    }    if (!type) {	type = svclassnames[SvTYPE(sv)];	iv = PTR2IV(sv);    }    sv_setiv(newSVrv(arg, type), iv);    return arg;}static SV *make_mg_object(pTHX_ SV *arg, MAGIC *mg){    sv_setiv(newSVrv(arg, "B::MAGIC"), PTR2IV(mg));    return arg;}static SV *cstring(pTHX_ SV *sv){    SV *sstr = newSVpvn("", 0);    STRLEN len;    char *s;    if (!SvOK(sv))	sv_setpvn(sstr, "0", 1);    else    {	/* XXX Optimise? */	s = SvPV(sv, len);	sv_catpv(sstr, "\"");	for (; len; len--, s++)	{	    /* At least try a little for readability */	    if (*s == '"')		sv_catpv(sstr, "\\\"");	    else if (*s == '\\')		sv_catpv(sstr, "\\\\");	    else if (*s >= ' ' && *s < 127) /* XXX not portable */		sv_catpvn(sstr, s, 1);	    else if (*s == '\n')		sv_catpv(sstr, "\\n");	    else if (*s == '\r')		sv_catpv(sstr, "\\r");	    else if (*s == '\t')		sv_catpv(sstr, "\\t");	    else if (*s == '\a')		sv_catpv(sstr, "\\a");	    else if (*s == '\b')		sv_catpv(sstr, "\\b");	    else if (*s == '\f')		sv_catpv(sstr, "\\f");	    else if (*s == '\v')		sv_catpv(sstr, "\\v");	    else	    {		/* no trigraph support */		char escbuff[5]; /* to fit backslash, 3 octals + trailing \0 */		/* Don't want promotion of a signed -1 char in sprintf args */		unsigned char c = (unsigned char) *s;		sprintf(escbuff, "\\%03o", c);		sv_catpv(sstr, escbuff);	    }	    /* XXX Add line breaks if string is long */	}	sv_catpv(sstr, "\"");    }    return sstr;}static SV *cchar(pTHX_ SV *sv){    SV *sstr = newSVpvn("'", 1);    STRLEN n_a;    char *s = SvPV(sv, n_a);    if (*s == '\'')	sv_catpv(sstr, "\\'");    else if (*s == '\\')	sv_catpv(sstr, "\\\\");    else if (*s >= ' ' && *s < 127) /* XXX not portable */	sv_catpvn(sstr, s, 1);    else if (*s == '\n')	sv_catpv(sstr, "\\n");    else if (*s == '\r')	sv_catpv(sstr, "\\r");    else if (*s == '\t')	sv_catpv(sstr, "\\t");    else if (*s == '\a')	sv_catpv(sstr, "\\a");    else if (*s == '\b')	sv_catpv(sstr, "\\b");    else if (*s == '\f')	sv_catpv(sstr, "\\f");    else if (*s == '\v')	sv_catpv(sstr, "\\v");    else    {	/* no trigraph support */	char escbuff[5]; /* to fit backslash, 3 octals + trailing \0 */	/* Don't want promotion of a signed -1 char in sprintf args */	unsigned char c = (unsigned char) *s;	sprintf(escbuff, "\\%03o", c);	sv_catpv(sstr, escbuff);    }    sv_catpv(sstr, "'");    return sstr;}voidwalkoptree(pTHX_ SV *opsv, char *method){    dSP;    OP *o;        if (!SvROK(opsv))	croak("opsv is not a reference");    opsv = sv_mortalcopy(opsv);    o = INT2PTR(OP*,SvIV((SV*)SvRV(opsv)));    if (walkoptree_debug) {	PUSHMARK(sp);	XPUSHs(opsv);	PUTBACK;	perl_call_method("walkoptree_debug", G_DISCARD);    }    PUSHMARK(sp);    XPUSHs(opsv);    PUTBACK;    perl_call_method(method, G_DISCARD);    if (o && (o->op_flags & OPf_KIDS)) {	OP *kid;	for (kid = ((UNOP*)o)->op_first; kid; kid = kid->op_sibling) {	    /* Use the same opsv. Rely on methods not to mess it up. */	    sv_setiv(newSVrv(opsv, cc_opclassname(aTHX_ kid)), PTR2IV(kid));	    walkoptree(aTHX_ opsv, method);	}    }}typedef OP	*B__OP;typedef UNOP	*B__UNOP;typedef BINOP	*B__BINOP;typedef LOGOP	*B__LOGOP;typedef LISTOP	*B__LISTOP;typedef PMOP	*B__PMOP;typedef SVOP	*B__SVOP;typedef PADOP	*B__PADOP;typedef PVOP	*B__PVOP;typedef LOOP	*B__LOOP;typedef COP	*B__COP;typedef SV	*B__SV;typedef SV	*B__IV;typedef SV	*B__PV;typedef SV	*B__NV;typedef SV	*B__PVMG;typedef SV	*B__PVLV;typedef SV	*B__BM;typedef SV	*B__RV;typedef AV	*B__AV;typedef HV	*B__HV;typedef CV	*B__CV;typedef GV	*B__GV;typedef IO	*B__IO;typedef MAGIC	*B__MAGIC;MODULE = B	PACKAGE = B	PREFIX = B_PROTOTYPES: DISABLEBOOT:{    HV *stash = gv_stashpvn("B", 1, TRUE);    AV *export_ok = perl_get_av("B::EXPORT_OK",TRUE);    specialsv_list[0] = Nullsv;    specialsv_list[1] = &PL_sv_undef;    specialsv_list[2] = &PL_sv_yes;    specialsv_list[3] = &PL_sv_no;    specialsv_list[4] = pWARN_ALL;    specialsv_list[5] = pWARN_NONE;#include "defsubs.h"}#define B_main_cv()	PL_main_cv#define B_init_av()	PL_initav#define B_begin_av()	PL_beginav_save#define B_end_av()	PL_endav#define B_main_root()	PL_main_root#define B_main_start()	PL_main_start#define B_amagic_generation()	PL_amagic_generation#define B_comppadlist()	(PL_main_cv ? CvPADLIST(PL_main_cv) : CvPADLIST(PL_compcv))#define B_sv_undef()	&PL_sv_undef#define B_sv_yes()	&PL_sv_yes#define B_sv_no()	&PL_sv_noB::AVB_init_av()B::AVB_begin_av()B::AVB_end_av()B::CVB_main_cv()B::OPB_main_root()B::OPB_main_start()long B_amagic_generation()B::AVB_comppadlist()B::SVB_sv_undef()B::SVB_sv_yes()B::SVB_sv_no()MODULE = B	PACKAGE = Bvoidwalkoptree(opsv, method)	SV *	opsv	char *	method    CODE:	walkoptree(aTHX_ opsv, method);intwalkoptree_debug(...)    CODE:	RETVAL = walkoptree_debug;	if (items > 0 && SvTRUE(ST(1)))	    walkoptree_debug = 1;    OUTPUT:	RETVAL#define address(sv) PTR2IV(sv)IVaddress(sv)	SV *	svB::SVsvref_2object(sv)	SV *	sv    CODE:	if (!SvROK(sv))	    croak("argument is not a reference");	RETVAL = (SV*)SvRV(sv);    OUTPUT:	RETVAL              voidopnumber(name)char *	nameCODE:{ int i;  IV  result = -1; ST(0) = sv_newmortal(); if (strncmp(name,"pp_",3) == 0)   name += 3; for (i = 0; i < PL_maxo; i++)  {   if (strcmp(name, PL_op_name[i]) == 0)    {     result = i;     break;    }  } sv_setiv(ST(0),result);}voidppname(opnum)	int	opnum    CODE:	ST(0) = sv_newmortal();	if (opnum >= 0 && opnum < PL_maxo) {	    sv_setpvn(ST(0), "pp_", 3);	    sv_catpv(ST(0), PL_op_name[opnum]);	}voidhash(sv)	SV *	sv    CODE:	char *s;	STRLEN len;	U32 hash = 0;	char hexhash[19]; /* must fit "0xffffffffffffffff" plus trailing \0 */	s = SvPV(sv, len);	PERL_HASH(hash, s, len);	sprintf(hexhash, "0x%"UVxf, (UV)hash);	ST(0) = sv_2mortal(newSVpv(hexhash, 0));#define cast_I32(foo) (I32)fooIVcast_I32(i)	IV	ivoidminus_c()    CODE:	PL_minus_c = TRUE;voidsave_BEGINs()    CODE:	PL_minus_c |= 0x10;SV *cstring(sv)	SV *	sv    CODE:	RETVAL = cstring(aTHX_ sv);    OUTPUT:	RETVALSV *cchar(sv)	SV *	sv    CODE:	RETVAL = cchar(aTHX_ sv);    OUTPUT:	RETVALvoidthreadsv_names()    PPCODE:#ifdef USE_THREADS	int i;	STRLEN len = strlen(PL_threadsv_names);	EXTEND(sp, len);	for (i = 0; i < len; i++)	    PUSHs(sv_2mortal(newSVpvn(&PL_threadsv_names[i], 1)));#endif#define OP_next(o)	o->op_next#define OP_sibling(o)	o->op_sibling#define OP_desc(o)	PL_op_desc[o->op_type]#define OP_targ(o)	o->op_targ#define OP_type(o)	o->op_type#define OP_seq(o)	o->op_seq#define OP_flags(o)	o->op_flags#define OP_private(o)	o->op_privateMODULE = B	PACKAGE = B::OP		PREFIX = OP_B::OPOP_next(o)	B::OP		oB::OPOP_sibling(o)	B::OP		ochar *OP_name(o)	B::OP		o    CODE:	RETVAL = PL_op_name[o->op_type];    OUTPUT:	RETVALvoidOP_ppaddr(o)	B::OP		o    PREINIT:	int i;	SV *sv = sv_newmortal();    CODE:	sv_setpvn(sv, "PL_ppaddr[OP_", 13);	sv_catpv(sv, PL_op_name[o->op_type]);	for (i=13; i<SvCUR(sv); ++i)	    SvPVX(sv)[i] = toUPPER(SvPVX(sv)[i]);	sv_catpv(sv, "]");	ST(0) = sv;char *OP_desc(o)	B::OP		oPADOFFSETOP_targ(o)	B::OP		oU16OP_type(o)	B::OP		oU16OP_seq(o)	B::OP		oU8OP_flags(o)	B::OP		oU8OP_private(o)	B::OP		o#define UNOP_first(o)	o->op_firstMODULE = B	PACKAGE = B::UNOP		PREFIX = UNOP_B::OP UNOP_first(o)	B::UNOP	o#define BINOP_last(o)	o->op_lastMODULE = B	PACKAGE = B::BINOP		PREFIX = BINOP_B::OPBINOP_last(o)	B::BINOP	o

⌨️ 快捷键说明

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