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

📄 consarg.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $RCSfile: consarg.c,v $$Revision: 4.0.1.4 $$Date: 92/06/08 12:26: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:	consarg.c,v $ * Revision 4.0.1.4  92/06/08  12:26:27  lwall * patch20: new warning for use of x with non-numeric right operand * patch20: modulus with highest bit in left operand set didn't always work * patch20: illegal lvalue message could be followed by core dump * patch20: deleted some minor memory leaks *  * Revision 4.0.1.3  91/11/05  16:21:16  lwall * patch11: random cleanup * patch11: added eval {} * patch11: added sort {} LIST * patch11: "foo" x -1 dumped core * patch11: substr() and vec() weren't allowed in an lvalue list *  * Revision 4.0.1.2  91/06/07  10:33:12  lwall * patch4: new copyright notice * patch4: length($`), length($&), length($') now optimized to avoid string copy *  * Revision 4.0.1.1  91/04/11  17:38:34  lwall * patch1: fixed "Bad free" error *  * Revision 4.0  91/03/20  01:06:15  lwall * 4.0 baseline. *  */#include "EXTERN.h"#include "perl.h"static int nothing_in_common();static int arg_common();static int spat_common();ARG *make_split(stab,arg,limarg)register STAB *stab;register ARG *arg;ARG *limarg;{    register SPAT *spat;    if (arg->arg_type != O_MATCH) {	Newz(201,spat,1,SPAT);	spat->spat_next = curstash->tbl_spatroot; /* link into spat list */	curstash->tbl_spatroot = spat;	spat->spat_runtime = arg;	arg = make_match(O_MATCH,stab2arg(A_STAB,defstab),spat);    }    Renew(arg,4,ARG);    arg->arg_len = 3;    if (limarg) {	if (limarg->arg_type == O_ITEM) {	    Copy(limarg+1,arg+3,1,ARG);	    limarg[1].arg_type = A_NULL;	    arg_free(limarg);	}	else {	    arg[3].arg_flags = 0;	    arg[3].arg_len = 0;	    arg[3].arg_type = A_EXPR;	    arg[3].arg_ptr.arg_arg = limarg;	}    }    else {	arg[3].arg_flags = 0;	arg[3].arg_len = 0;	arg[3].arg_type = A_NULL;	arg[3].arg_ptr.arg_arg = Nullarg;    }    arg->arg_type = O_SPLIT;    spat = arg[2].arg_ptr.arg_spat;    spat->spat_repl = stab2arg(A_STAB,aadd(stab));    if (spat->spat_short) {	/* exact match can bypass regexec() */	if (!((spat->spat_flags & SPAT_SCANFIRST) &&	    (spat->spat_flags & SPAT_ALL) )) {	    str_free(spat->spat_short);	    spat->spat_short = Nullstr;	}    }    return arg;}ARG *mod_match(type,left,pat)register ARG *left;register ARG *pat;{    register SPAT *spat;    register ARG *newarg;    if (!pat)	return Nullarg;    if ((pat->arg_type == O_MATCH ||	 pat->arg_type == O_SUBST ||	 pat->arg_type == O_TRANS ||	 pat->arg_type == O_SPLIT	) &&	pat[1].arg_ptr.arg_stab == defstab ) {	switch (pat->arg_type) {	case O_MATCH:	    newarg = make_op(type == O_MATCH ? O_MATCH : O_NMATCH,		pat->arg_len,		left,Nullarg,Nullarg);	    break;	case O_SUBST:	    newarg = l(make_op(type == O_MATCH ? O_SUBST : O_NSUBST,		pat->arg_len,		left,Nullarg,Nullarg));	    break;	case O_TRANS:	    newarg = l(make_op(type == O_MATCH ? O_TRANS : O_NTRANS,		pat->arg_len,		left,Nullarg,Nullarg));	    break;	case O_SPLIT:	    newarg = make_op(type == O_MATCH ? O_SPLIT : O_SPLIT,		pat->arg_len,		left,Nullarg,Nullarg);	    break;	}	if (pat->arg_len >= 2) {	    newarg[2].arg_type = pat[2].arg_type;	    newarg[2].arg_ptr = pat[2].arg_ptr;	    newarg[2].arg_len = pat[2].arg_len;	    newarg[2].arg_flags = pat[2].arg_flags;	    if (pat->arg_len >= 3) {		newarg[3].arg_type = pat[3].arg_type;		newarg[3].arg_ptr = pat[3].arg_ptr;		newarg[3].arg_len = pat[3].arg_len;		newarg[3].arg_flags = pat[3].arg_flags;	    }	}	free_arg(pat);    }    else {	Newz(202,spat,1,SPAT);	spat->spat_next = curstash->tbl_spatroot; /* link into spat list */	curstash->tbl_spatroot = spat;	spat->spat_runtime = pat;	newarg = make_op(type,2,left,Nullarg,Nullarg);	newarg[2].arg_type = A_SPAT | A_DONT;	newarg[2].arg_ptr.arg_spat = spat;    }    return newarg;}ARG *make_op(type,newlen,arg1,arg2,arg3)int type;int newlen;ARG *arg1;ARG *arg2;ARG *arg3;{    register ARG *arg;    register ARG *chld;    register unsigned doarg;    register int i;    extern ARG *arg4;	/* should be normal arguments, really */    extern ARG *arg5;    arg = op_new(newlen);    arg->arg_type = type;    /*SUPPRESS 560*/    if (chld = arg1) {	if (chld->arg_type == O_ITEM &&	    (hoistable[ i = (chld[1].arg_type&A_MASK)] || i == A_LVAL ||	     (i == A_LEXPR &&	      (chld[1].arg_ptr.arg_arg->arg_type == O_LIST ||	       chld[1].arg_ptr.arg_arg->arg_type == O_ARRAY ||	       chld[1].arg_ptr.arg_arg->arg_type == O_HASH ))))	{	    arg[1].arg_type = chld[1].arg_type;	    arg[1].arg_ptr = chld[1].arg_ptr;	    arg[1].arg_flags |= chld[1].arg_flags;	    arg[1].arg_len = chld[1].arg_len;	    free_arg(chld);	}	else {	    arg[1].arg_type = A_EXPR;	    arg[1].arg_ptr.arg_arg = chld;	}    }    /*SUPPRESS 560*/    if (chld = arg2) {	if (chld->arg_type == O_ITEM && 	    (hoistable[chld[1].arg_type&A_MASK] || 	     (type == O_ASSIGN && 	      ((chld[1].arg_type == A_READ && !(arg[1].arg_type & A_DONT))		||	       (chld[1].arg_type == A_INDREAD && !(arg[1].arg_type & A_DONT))		||	       (chld[1].arg_type == A_GLOB && !(arg[1].arg_type & A_DONT))	      ) ) ) ) {	    arg[2].arg_type = chld[1].arg_type;	    arg[2].arg_ptr = chld[1].arg_ptr;	    arg[2].arg_len = chld[1].arg_len;	    free_arg(chld);	}	else {	    arg[2].arg_type = A_EXPR;	    arg[2].arg_ptr.arg_arg = chld;	}    }    /*SUPPRESS 560*/    if (chld = arg3) {	if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type&A_MASK]) {	    arg[3].arg_type = chld[1].arg_type;	    arg[3].arg_ptr = chld[1].arg_ptr;	    arg[3].arg_len = chld[1].arg_len;	    free_arg(chld);	}	else {	    arg[3].arg_type = A_EXPR;	    arg[3].arg_ptr.arg_arg = chld;	}    }    if (newlen >= 4 && (chld = arg4)) {	if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type&A_MASK]) {	    arg[4].arg_type = chld[1].arg_type;	    arg[4].arg_ptr = chld[1].arg_ptr;	    arg[4].arg_len = chld[1].arg_len;	    free_arg(chld);	}	else {	    arg[4].arg_type = A_EXPR;	    arg[4].arg_ptr.arg_arg = chld;	}    }    if (newlen >= 5 && (chld = arg5)) {	if (chld->arg_type == O_ITEM && hoistable[chld[1].arg_type&A_MASK]) {	    arg[5].arg_type = chld[1].arg_type;	    arg[5].arg_ptr = chld[1].arg_ptr;	    arg[5].arg_len = chld[1].arg_len;	    free_arg(chld);	}	else {	    arg[5].arg_type = A_EXPR;	    arg[5].arg_ptr.arg_arg = chld;	}    }    doarg = opargs[type];    for (i = 1; i <= newlen; ++i) {	if (!(doarg & 1))	    arg[i].arg_type |= A_DONT;	if (doarg & 2)	    arg[i].arg_flags |= AF_ARYOK;	doarg >>= 2;    }#ifdef DEBUGGING    if (debug & 16) {	fprintf(stderr,"%lx <= make_op(%s",arg,opname[arg->arg_type]);	if (arg1)	    fprintf(stderr,",%s=%lx",		argname[arg[1].arg_type&A_MASK],arg[1].arg_ptr.arg_arg);	if (arg2)	    fprintf(stderr,",%s=%lx",		argname[arg[2].arg_type&A_MASK],arg[2].arg_ptr.arg_arg);	if (arg3)	    fprintf(stderr,",%s=%lx",		argname[arg[3].arg_type&A_MASK],arg[3].arg_ptr.arg_arg);	if (newlen >= 4)	    fprintf(stderr,",%s=%lx",		argname[arg[4].arg_type&A_MASK],arg[4].arg_ptr.arg_arg);	if (newlen >= 5)	    fprintf(stderr,",%s=%lx",		argname[arg[5].arg_type&A_MASK],arg[5].arg_ptr.arg_arg);	fprintf(stderr,")\n");    }#endif    arg = evalstatic(arg);	/* see if we can consolidate anything */    return arg;}ARG *evalstatic(arg)register ARG *arg;{    static STR *str = Nullstr;    register STR *s1;    register STR *s2;    double value;		/* must not be register */    register char *tmps;    int i;    unsigned long tmplong;    long tmp2;    double exp(), log(), sqrt(), modf();    char *crypt();    double sin(), cos(), atan2(), pow();    if (!arg || !arg->arg_len)	return arg;    if (!str)	str = Str_new(20,0);    if (arg[1].arg_type == A_SINGLE)	s1 = arg[1].arg_ptr.arg_str;    else	s1 = Nullstr;    if (arg->arg_len >= 2 && arg[2].arg_type == A_SINGLE)	s2 = arg[2].arg_ptr.arg_str;    else	s2 = Nullstr;#define CHECK1 if (!s1) return arg#define CHECK2 if (!s2) return arg#define CHECK12 if (!s1 || !s2) return arg    switch (arg->arg_type) {    default:	return arg;    case O_SORT:	if (arg[1].arg_type == A_CMD)	    arg[1].arg_type |= A_DONT;	return arg;    case O_EVAL:	if (arg[1].arg_type == A_CMD) {	    arg->arg_type = O_TRY;	    arg[1].arg_type |= A_DONT;	    return arg;	}	CHECK1;	arg->arg_type = O_EVALONCE;	return arg;    case O_AELEM:	CHECK2;	i = (int)str_gnum(s2);	if (i < 32767 && i >= 0) {	    arg->arg_type = O_ITEM;	    arg->arg_len = 1;	    arg[1].arg_type = A_ARYSTAB;	/* $abc[123] is hoistable now */	    arg[1].arg_len = i;	    str_free(s2);	    Renew(arg, 2, ARG);	}	return arg;    case O_CONCAT:	CHECK12;	str_sset(str,s1);	str_scat(str,s2);	break;    case O_REPEAT:	CHECK2;	if (dowarn && !s2->str_nok && !looks_like_number(s2))	    warn("Right operand of x is not numeric");	CHECK1;	i = (int)str_gnum(s2);	tmps = str_get(s1);	str_nset(str,"",0);	if (i > 0) {	    STR_GROW(str, i * s1->str_cur + 1);	    repeatcpy(str->str_ptr, tmps, s1->str_cur, i);	    str->str_cur = i * s1->str_cur;	    str->str_ptr[str->str_cur] = '\0';	}	break;    case O_MULTIPLY:	CHECK12;	value = str_gnum(s1);	str_numset(str,value * str_gnum(s2));	break;    case O_DIVIDE:	CHECK12;	value = str_gnum(s2);	if (value == 0.0)	    yyerror("Illegal division by constant zero");	else#ifdef SLOPPYDIVIDE	/* insure that 20./5. == 4. */	{	    double x;	    int    k;	    x =  str_gnum(s1);	    if ((double)(int)x     == x &&		(double)(int)value == value &&		(k = (int)x/(int)value)*(int)value == (int)x) {		value = k;	    } else {		value = x/value;	    }	    str_numset(str,value);	}#else	str_numset(str,str_gnum(s1) / value);#endif	break;    case O_MODULO:	CHECK12;	tmplong = (unsigned long)str_gnum(s2);	if (tmplong == 0L) {	    yyerror("Illegal modulus of constant zero");	    return arg;	}	value = str_gnum(s1);#ifndef lint	if (value >= 0.0)	    str_numset(str,(double)(((unsigned long)value) % tmplong));	else {	    tmp2 = (long)value;	    str_numset(str,(double)((tmplong-((-tmp2 - 1) % tmplong)) - 1));	}#else	tmp2 = tmp2;#endif	break;    case O_ADD:	CHECK12;	value = str_gnum(s1);	str_numset(str,value + str_gnum(s2));	break;    case O_SUBTRACT:	CHECK12;	value = str_gnum(s1);	str_numset(str,value - str_gnum(s2));	break;    case O_LEFT_SHIFT:	CHECK12;	value = str_gnum(s1);	i = (int)str_gnum(s2);#ifndef lint	str_numset(str,(double)(((long)value) << i));#endif	break;    case O_RIGHT_SHIFT:	CHECK12;	value = str_gnum(s1);	i = (int)str_gnum(s2);#ifndef lint	str_numset(str,(double)(((long)value) >> i));#endif	break;    case O_LT:	CHECK12;	value = str_gnum(s1);	str_numset(str,(value < str_gnum(s2)) ? 1.0 : 0.0);	break;    case O_GT:	CHECK12;	value = str_gnum(s1);	str_numset(str,(value > str_gnum(s2)) ? 1.0 : 0.0);	break;    case O_LE:	CHECK12;	value = str_gnum(s1);	str_numset(str,(value <= str_gnum(s2)) ? 1.0 : 0.0);	break;    case O_GE:	CHECK12;	value = str_gnum(s1);	str_numset(str,(value >= str_gnum(s2)) ? 1.0 : 0.0);	break;    case O_EQ:	CHECK12;	if (dowarn) {	    if ((!s1->str_nok && !looks_like_number(s1)) ||		(!s2->str_nok && !looks_like_number(s2)) )		warn("Possible use of == on string value");	}	value = str_gnum(s1);	str_numset(str,(value == str_gnum(s2)) ? 1.0 : 0.0);	break;    case O_NE:	CHECK12;	value = str_gnum(s1);	str_numset(str,(value != str_gnum(s2)) ? 1.0 : 0.0);	break;    case O_NCMP:	CHECK12;	value = str_gnum(s1);	value -= str_gnum(s2);	if (value > 0.0)	    value = 1.0;	else if (value < 0.0)	    value = -1.0;	str_numset(str,value);	break;    case O_BIT_AND:	CHECK12;	value = str_gnum(s1);#ifndef lint	str_numset(str,(double)(U_L(value) & U_L(str_gnum(s2))));#endif	break;    case O_XOR:	CHECK12;	value = str_gnum(s1);#ifndef lint	str_numset(str,(double)(U_L(value) ^ U_L(str_gnum(s2))));#endif	break;    case O_BIT_OR:	CHECK12;	value = str_gnum(s1);#ifndef lint	str_numset(str,(double)(U_L(value) | U_L(str_gnum(s2))));#endif	break;    case O_AND:	CHECK12;	if (str_true(s1))	    str_sset(str,s2);	else	    str_sset(str,s1);	break;    case O_OR:	CHECK12;	if (str_true(s1))	    str_sset(str,s1);	else	    str_sset(str,s2);	break;    case O_COND_EXPR:	CHECK12;	if ((arg[3].arg_type & A_MASK) != A_SINGLE)	    return arg;	if (str_true(s1))	    str_sset(str,s2);	else	    str_sset(str,arg[3].arg_ptr.arg_str);	str_free(arg[3].arg_ptr.arg_str);	Renew(arg, 3, ARG);	break;    case O_NEGATE:	CHECK1;	str_numset(str,(double)(-str_gnum(s1)));	break;    case O_NOT:	CHECK1;#ifdef NOTNOT	{ char xxx = str_true(s1); str_numset(str,(double)!xxx); }#else	str_numset(str,(double)(!str_true(s1)));#endif	break;    case O_COMPLEMENT:	CHECK1;#ifndef lint	str_numset(str,(double)(~U_L(str_gnum(s1))));#endif	break;    case O_SIN:	CHECK1;	str_numset(str,sin(str_gnum(s1)));	break;    case O_COS:	CHECK1;	str_numset(str,cos(str_gnum(s1)));	break;    case O_ATAN2:	CHECK12;	value = str_gnum(s1);	str_numset(str,atan2(value, str_gnum(s2)));	break;    case O_POW:	CHECK12;	value = str_gnum(s1);	str_numset(str,pow(value, str_gnum(s2)));	break;    case O_LENGTH:	if (arg[1].arg_type == A_STAB) {	    arg->arg_type = O_ITEM;	    arg[1].arg_type = A_LENSTAB;	    return arg;	}	CHECK1;	str_numset(str, (double)str_len(s1));	break;    case O_SLT:	CHECK12;	str_numset(str,(double)(str_cmp(s1,s2) < 0));	break;    case O_SGT:	CHECK12;	str_numset(str,(double)(str_cmp(s1,s2) > 0));	break;    case O_SLE:	CHECK12;	str_numset(str,(double)(str_cmp(s1,s2) <= 0));	break;    case O_SGE:	CHECK12;	str_numset(str,(double)(str_cmp(s1,s2) >= 0));	break;    case O_SEQ:	CHECK12;	str_numset(str,(double)(str_eq(s1,s2)));	break;    case O_SNE:	CHECK12;	str_numset(str,(double)(!str_eq(s1,s2)));	break;    case O_SCMP:	CHECK12;	str_numset(str,(double)(str_cmp(s1,s2)));	break;    case O_CRYPT:	CHECK12;#ifdef HAS_CRYPT	tmps = str_get(s1);	str_set(str,crypt(tmps,str_get(s2)));#else	yyerror(	"The crypt() function is unimplemented due to excessive paranoia.");#endif	break;    case O_EXP:	CHECK1;	str_numset(str,exp(str_gnum(s1)));	break;    case O_LOG:	CHECK1;	str_numset(str,log(str_gnum(s1)));	break;    case O_SQRT:	CHECK1;	str_numset(str,sqrt(str_gnum(s1)));	break;    case O_INT:	CHECK1;	value = str_gnum(s1);	if (value >= 0.0)	    (void)modf(value,&value);	else {	    (void)modf(-value,&value);	    value = -value;	}	str_numset(str,value);	break;    case O_ORD:	CHECK1;#ifndef I286	str_numset(str,(double)(*str_get(s1)));#else

⌨️ 快捷键说明

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