diff options
Diffstat (limited to 'consarg.c')
-rw-r--r-- | consarg.c | 1289 |
1 files changed, 0 insertions, 1289 deletions
diff --git a/consarg.c b/consarg.c deleted file mode 100644 index fe4542b3da..0000000000 --- a/consarg.c +++ /dev/null @@ -1,1289 +0,0 @@ -/* $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 - { - int zapc; - char *zaps; - - zaps = str_get(s1); - zapc = (int) *zaps; - str_numset(str,(double)(zapc)); - } -#endif - break; - } - arg->arg_type = O_ITEM; /* note arg1 type is already SINGLE */ - str_free(s1); - arg[1].arg_ptr.arg_str = str; - if (s2) { - str_free(s2); - arg[2].arg_ptr.arg_str = Nullstr; - arg[2].arg_type = A_NULL; - } - str = Nullstr; - - return arg; -} - -ARG * -l(arg) -register ARG *arg; -{ - register int i; - register ARG *arg1; - register ARG *arg2; - SPAT *spat; - int arghog = 0; - - i = arg[1].arg_type & A_MASK; - - arg->arg_flags |= AF_COMMON; /* assume something in common */ - /* which forces us to copy things */ - - if (i == A_ARYLEN) { - arg[1].arg_type = A_LARYLEN; - return arg; - } - if (i == A_ARYSTAB) { - arg[1].arg_type = A_LARYSTAB; - return arg; - } - - /* see if it's an array reference */ - - if (i == A_EXPR || i == A_LEXPR) { - arg1 = arg[1].arg_ptr.arg_arg; - - if (arg1->arg_type == O_LIST || arg1->arg_type == O_ITEM) { - /* assign to list */ - if (arg->arg_len > 1) { - dehoist(arg,2); - arg2 = arg[2].arg_ptr.arg_arg; - if (nothing_in_common(arg1,arg2)) - arg->arg_flags &= ~AF_COMMON; - if (arg->arg_type == O_ASSIGN) { - if (arg1->arg_flags & AF_LOCAL) - arg->arg_flags |= AF_LOCAL; - arg[1].arg_flags |= AF_ARYOK; - arg[2].arg_flags |= AF_ARYOK; - } - } - else if (arg->arg_type != O_CHOP) - arg->arg_type = O_ASSIGN; /* possible local(); */ - for (i = arg1->arg_len; i >= 1; i--) { - switch (arg1[i].arg_type) { - case A_STAR: case A_LSTAR: - arg1[i].arg_type = A_LSTAR; - break; - case A_STAB: case A_LVAL: - arg1[i].arg_type = A_LVAL; - break; - case A_ARYLEN: case A_LARYLEN: - arg1[i].arg_type = A_LARYLEN; - break; - case A_ARYSTAB: case A_LARYSTAB: - arg1[i].arg_type = A_LARYSTAB; - break; - case A_EXPR: case A_LEXPR: - arg1[i].arg_type = A_LEXPR; - switch(arg1[i].arg_ptr.arg_arg->arg_type) { - case O_ARRAY: case O_LARRAY: - arg1[i].arg_ptr.arg_arg->arg_type = O_LARRAY; - arghog = 1; - break; - case O_AELEM: case O_LAELEM: - arg1[i].arg_ptr.arg_arg->arg_type = O_LAELEM; - break; - case O_HASH: case O_LHASH: - arg1[i].arg_ptr.arg_arg->arg_type = O_LHASH; - arghog = 1; - break; - case O_HELEM: case O_LHELEM: - arg1[i].arg_ptr.arg_arg->arg_type = O_LHELEM; - break; - case O_ASLICE: case O_LASLICE: - arg1[i].arg_ptr.arg_arg->arg_type = O_LASLICE; - break; - case O_HSLICE: case O_LHSLICE: - arg1[i].arg_ptr.arg_arg->arg_type = O_LHSLICE; - break; - case O_SUBSTR: case O_VEC: - (void)l(arg1[i].arg_ptr.arg_arg); - Renewc(arg1[i].arg_ptr.arg_arg->arg_ptr.arg_str, 1, - struct lstring, STR); - /* grow string struct to hold an lstring struct */ - break; - default: - goto ill_item; - } - break; - default: - ill_item: - (void)sprintf(tokenbuf, "Illegal item (%s) as lvalue", - argname[arg1[i].arg_type&A_MASK]); - yyerror(tokenbuf); - } - } - if (arg->arg_len > 1) { - if (arg2->arg_type == O_SPLIT && !arg2[3].arg_type && !arghog) { - arg2[3].arg_type = A_SINGLE; - arg2[3].arg_ptr.arg_str = - str_nmake((double)arg1->arg_len + 1); /* limit split len*/ - } - } - } - else if (arg1->arg_type == O_AELEM || arg1->arg_type == O_LAELEM) - if (arg->arg_type == O_DEFINED) - arg1->arg_type = O_AELEM; - else - arg1->arg_type = O_LAELEM; - else if (arg1->arg_type == O_ARRAY || arg1->arg_type == O_LARRAY) { - arg1->arg_type = O_LARRAY; - if (arg->arg_len > 1) { - dehoist(arg,2); - arg2 = arg[2].arg_ptr.arg_arg; - if (arg2->arg_type == O_SPLIT) { /* use split's builtin =?*/ - spat = arg2[2].arg_ptr.arg_spat; - if (!(spat->spat_flags & SPAT_ONCE) && - nothing_in_common(arg1,spat->spat_repl)) { - spat->spat_repl[1].arg_ptr.arg_stab = - arg1[1].arg_ptr.arg_stab; - arg1[1].arg_ptr.arg_stab = Nullstab; - spat->spat_flags |= SPAT_ONCE; - arg_free(arg1); /* recursive */ - arg[1].arg_ptr.arg_arg = Nullarg; - free_arg(arg); /* non-recursive */ - return arg2; /* split has builtin assign */ - } - } - else if (nothing_in_common(arg1,arg2)) - arg->arg_flags &= ~AF_COMMON; - if (arg->arg_type == O_ASSIGN) { - arg[1].arg_flags |= AF_ARYOK; - arg[2].arg_flags |= AF_ARYOK; - } - } - else if (arg->arg_type == O_ASSIGN) - arg[1].arg_flags |= AF_ARYOK; - } - else if (arg1->arg_type == O_HELEM || arg1->arg_type == O_LHELEM) - if (arg->arg_type == O_DEFINED) - arg1->arg_type = O_HELEM; /* avoid creating one */ - else - arg1->arg_type = O_LHELEM; - else if (arg1->arg_type == O_HASH || arg1->arg_type == O_LHASH) { - arg1->arg_type = O_LHASH; - if (arg->arg_len > 1) { - dehoist(arg,2); - arg2 = arg[2].arg_ptr.arg_arg; - if (nothing_in_common(arg1,arg2)) - arg->arg_flags &= ~AF_COMMON; - if (arg->arg_type == O_ASSIGN) { - arg[1].arg_flags |= AF_ARYOK; - arg[2].arg_flags |= AF_ARYOK; - } - } - else if (arg->arg_type == O_ASSIGN) - arg[1].arg_flags |= AF_ARYOK; - } - else if (arg1->arg_type == O_ASLICE) { - arg1->arg_type = O_LASLICE; - if (arg->arg_type == O_ASSIGN) { - dehoist(arg,2); - arg[1].arg_flags |= AF_ARYOK; - arg[2].arg_flags |= AF_ARYOK; - } - } - else if (arg1->arg_type == O_HSLICE) { - arg1->arg_type = O_LHSLICE; - if (arg->arg_type == O_ASSIGN) { - dehoist(arg,2); - arg[1].arg_flags |= AF_ARYOK; - arg[2].arg_flags |= AF_ARYOK; - } - } - else if ((arg->arg_type == O_DEFINED || arg->arg_type == O_UNDEF) && - (arg1->arg_type == (perldb ? O_DBSUBR : O_SUBR)) ) { - arg[1].arg_type |= A_DONT; - } - else if (arg1->arg_type == O_SUBSTR || arg1->arg_type == O_VEC) { - (void)l(arg1); - Renewc(arg1->arg_ptr.arg_str, 1, struct lstring, STR); - /* grow string struct to hold an lstring struct */ - } - else if (arg1->arg_type == O_ASSIGN) - /*SUPPRESS 530*/ - ; - else { - (void)sprintf(tokenbuf, - "Illegal expression (%s) as lvalue",opname[arg1->arg_type]); - yyerror(tokenbuf); - return arg; - } - arg[1].arg_type = A_LEXPR | (arg[1].arg_type & A_DONT); - if (arg->arg_type == O_ASSIGN && (arg1[1].arg_flags & AF_ARYOK)) { - arg[1].arg_flags |= AF_ARYOK; - if (arg->arg_len > 1) - arg[2].arg_flags |= AF_ARYOK; - } -#ifdef DEBUGGING - if (debug & 16) - fprintf(stderr,"lval LEXPR\n"); -#endif - return arg; - } - if (i == A_STAR || i == A_LSTAR) { - arg[1].arg_type = A_LSTAR | (arg[1].arg_type & A_DONT); - return arg; - } - - /* not an array reference, should be a register name */ - - if (i != A_STAB && i != A_LVAL) { - (void)sprintf(tokenbuf, - "Illegal item (%s) as lvalue",argname[arg[1].arg_type&A_MASK]); - yyerror(tokenbuf); - return arg; - } - arg[1].arg_type = A_LVAL | (arg[1].arg_type & A_DONT); -#ifdef DEBUGGING - if (debug & 16) - fprintf(stderr,"lval LVAL\n"); -#endif - return arg; -} - -ARG * -fixl(type,arg) -int type; -ARG *arg; -{ - if (type == O_DEFINED || type == O_UNDEF) { - if (arg->arg_type != O_ITEM) - arg = hide_ary(arg); - if (arg->arg_type == O_ITEM) { - type = arg[1].arg_type & A_MASK; - if (type == A_EXPR || type == A_LEXPR) - arg[1].arg_type = A_LEXPR|A_DONT; - } - } - return arg; -} - -void -dehoist(arg,i) -ARG *arg; -{ - ARG *tmparg; - - if (arg[i].arg_type != A_EXPR) { /* dehoist */ - tmparg = make_op(O_ITEM,1,Nullarg,Nullarg,Nullarg); - tmparg[1] = arg[i]; - arg[i].arg_ptr.arg_arg = tmparg; - arg[i].arg_type = A_EXPR; - } -} - -ARG * -addflags(i,flags,arg) -register ARG *arg; -{ - arg[i].arg_flags |= flags; - return arg; -} - -ARG * -hide_ary(arg) -ARG *arg; -{ - if (arg->arg_type == O_ARRAY || arg->arg_type == O_HASH) - return make_op(O_ITEM,1,arg,Nullarg,Nullarg); - return arg; -} - -/* maybe do a join on multiple array dimensions */ - -ARG * -jmaybe(arg) -register ARG *arg; -{ - if (arg && arg->arg_type == O_COMMA) { - arg = listish(arg); - arg = make_op(O_JOIN, 2, - stab2arg(A_STAB,stabent(";",TRUE)), - make_list(arg), - Nullarg); - } - return arg; -} - -ARG * -make_list(arg) -register ARG *arg; -{ - register int i; - register ARG *node; - register ARG *nxtnode; - register int j; - STR *tmpstr; - - if (!arg) { - arg = op_new(0); - arg->arg_type = O_LIST; - } - if (arg->arg_type != O_COMMA) { - if (arg->arg_type != O_ARRAY) - arg->arg_flags |= AF_LISTISH; /* see listish() below */ - arg->arg_flags |= AF_LISTISH; /* see listish() below */ - return arg; - } - for (i = 2, node = arg; ; i++) { - if (node->arg_len < 2) - break; - if (node[1].arg_type != A_EXPR) - break; - node = node[1].arg_ptr.arg_arg; - if (node->arg_type != O_COMMA) - break; - } - if (i > 2) { - node = arg; - arg = op_new(i); - tmpstr = arg->arg_ptr.arg_str; - StructCopy(node, arg, ARG); /* copy everything except the STR */ - arg->arg_ptr.arg_str = tmpstr; - for (j = i; ; ) { - StructCopy(node+2, arg+j, ARG); - arg[j].arg_flags |= AF_ARYOK; - --j; /* Bug in Xenix compiler */ - if (j < 2) { - StructCopy(node+1, arg+1, ARG); - free_arg(node); - break; - } - nxtnode = node[1].arg_ptr.arg_arg; - free_arg(node); - node = nxtnode; - } - } - arg[1].arg_flags |= AF_ARYOK; - arg[2].arg_flags |= AF_ARYOK; - arg->arg_type = O_LIST; - arg->arg_len = i; - str_free(arg->arg_ptr.arg_str); - arg->arg_ptr.arg_str = Nullstr; - return arg; -} - -/* turn a single item into a list */ - -ARG * -listish(arg) -ARG *arg; -{ - if (arg && arg->arg_flags & AF_LISTISH) - arg = make_op(O_LIST,1,arg,Nullarg,Nullarg); - return arg; -} - -ARG * -maybelistish(optype, arg) -int optype; -ARG *arg; -{ - ARG *tmparg = arg; - - if (optype == O_RETURN && arg->arg_type == O_ITEM && - arg[1].arg_type == A_EXPR && (tmparg = arg[1].arg_ptr.arg_arg) && - ((tmparg->arg_flags & AF_LISTISH) || (tmparg->arg_type == O_ARRAY) )) { - tmparg = listish(tmparg); - free_arg(arg); - arg = tmparg; - } - else if (optype == O_PRTF || - (arg->arg_type == O_ASLICE || arg->arg_type == O_HSLICE || - arg->arg_type == O_F_OR_R) ) - arg = listish(arg); - return arg; -} - -/* mark list of local variables */ - -ARG * -localize(arg) -ARG *arg; -{ - arg->arg_flags |= AF_LOCAL; - return arg; -} - -ARG * -rcatmaybe(arg) -ARG *arg; -{ - ARG *arg2; - - if (arg->arg_type == O_CONCAT && arg[2].arg_type == A_EXPR) { - arg2 = arg[2].arg_ptr.arg_arg; - if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) { - arg->arg_type = O_RCAT; - arg[2].arg_type = arg2[1].arg_type; - arg[2].arg_ptr = arg2[1].arg_ptr; - free_arg(arg2); - } - } - return arg; -} - -ARG * -stab2arg(atype,stab) -int atype; -register STAB *stab; -{ - register ARG *arg; - - arg = op_new(1); - arg->arg_type = O_ITEM; - arg[1].arg_type = atype; - arg[1].arg_ptr.arg_stab = stab; - return arg; -} - -ARG * -cval_to_arg(cval) -register char *cval; -{ - register ARG *arg; - - arg = op_new(1); - arg->arg_type = O_ITEM; - arg[1].arg_type = A_SINGLE; - arg[1].arg_ptr.arg_str = str_make(cval,0); - Safefree(cval); - return arg; -} - -ARG * -op_new(numargs) -int numargs; -{ - register ARG *arg; - - Newz(203,arg, numargs + 1, ARG); - arg->arg_ptr.arg_str = Str_new(21,0); - arg->arg_len = numargs; - return arg; -} - -void -free_arg(arg) -ARG *arg; -{ - str_free(arg->arg_ptr.arg_str); - Safefree(arg); -} - -ARG * -make_match(type,expr,spat) -int type; -ARG *expr; -SPAT *spat; -{ - register ARG *arg; - - arg = make_op(type,2,expr,Nullarg,Nullarg); - - arg[2].arg_type = A_SPAT|A_DONT; - arg[2].arg_ptr.arg_spat = spat; -#ifdef DEBUGGING - if (debug & 16) - fprintf(stderr,"make_match SPAT=%lx\n",(long)spat); -#endif - - if (type == O_SUBST || type == O_NSUBST) { - if (arg[1].arg_type != A_STAB) { - yyerror("Illegal lvalue"); - } - arg[1].arg_type = A_LVAL; - } - return arg; -} - -ARG * -cmd_to_arg(cmd) -CMD *cmd; -{ - register ARG *arg; - - arg = op_new(1); - arg->arg_type = O_ITEM; - arg[1].arg_type = A_CMD; - arg[1].arg_ptr.arg_cmd = cmd; - return arg; -} - -/* Check two expressions to see if there is any identifier in common */ - -static int -nothing_in_common(arg1,arg2) -ARG *arg1; -ARG *arg2; -{ - static int thisexpr = 0; /* I don't care if this wraps */ - - thisexpr++; - if (arg_common(arg1,thisexpr,1)) - return 0; /* hit eval or do {} */ - stab_lastexpr(defstab) = thisexpr; /* pretend to hit @_ */ - if (arg_common(arg2,thisexpr,0)) - return 0; /* hit identifier again */ - return 1; -} - -/* Recursively descend an expression and mark any identifier or check - * it to see if it was marked already. - */ - -static int -arg_common(arg,exprnum,marking) -register ARG *arg; -int exprnum; -int marking; -{ - register int i; - - if (!arg) - return 0; - for (i = arg->arg_len; i >= 1; i--) { - switch (arg[i].arg_type & A_MASK) { - case A_NULL: - break; - case A_LEXPR: - case A_EXPR: - if (arg_common(arg[i].arg_ptr.arg_arg,exprnum,marking)) - return 1; - break; - case A_CMD: - return 1; /* assume hanky panky */ - case A_STAR: - case A_LSTAR: - case A_STAB: - case A_LVAL: - case A_ARYLEN: - case A_LARYLEN: - if (marking) - stab_lastexpr(arg[i].arg_ptr.arg_stab) = exprnum; - else if (stab_lastexpr(arg[i].arg_ptr.arg_stab) == exprnum) - return 1; - break; - case A_DOUBLE: - case A_BACKTICK: - { - register char *s = arg[i].arg_ptr.arg_str->str_ptr; - register char *send = s + arg[i].arg_ptr.arg_str->str_cur; - register STAB *stab; - - while (*s) { - if (*s == '$' && s[1]) { - s = scanident(s,send,tokenbuf); - stab = stabent(tokenbuf,TRUE); - if (marking) - stab_lastexpr(stab) = exprnum; - else if (stab_lastexpr(stab) == exprnum) - return 1; - continue; - } - else if (*s == '\\' && s[1]) - s++; - s++; - } - } - break; - case A_SPAT: - if (spat_common(arg[i].arg_ptr.arg_spat,exprnum,marking)) - return 1; - break; - case A_READ: - case A_INDREAD: - case A_GLOB: - case A_WORD: - case A_SINGLE: - break; - } - } - switch (arg->arg_type) { - case O_ARRAY: - case O_LARRAY: - if ((arg[1].arg_type & A_MASK) == A_STAB) - (void)aadd(arg[1].arg_ptr.arg_stab); - break; - case O_HASH: - case O_LHASH: - if ((arg[1].arg_type & A_MASK) == A_STAB) - (void)hadd(arg[1].arg_ptr.arg_stab); - break; - case O_EVAL: - case O_SUBR: - case O_DBSUBR: - return 1; - } - return 0; -} - -static int -spat_common(spat,exprnum,marking) -register SPAT *spat; -int exprnum; -int marking; -{ - if (spat->spat_runtime) - if (arg_common(spat->spat_runtime,exprnum,marking)) - return 1; - if (spat->spat_repl) { - if (arg_common(spat->spat_repl,exprnum,marking)) - return 1; - } - return 0; -} |