=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/parse/eval.c,v retrieving revision 1.9 retrieving revision 1.47 diff -u -p -r1.9 -r1.47 --- OpenXM_contrib2/asir2000/parse/eval.c 2001/08/20 09:50:34 1.9 +++ OpenXM_contrib2/asir2000/parse/eval.c 2005/09/29 08:55:26 1.47 @@ -45,7 +45,7 @@ * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE, * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE. * - * $OpenXM: OpenXM_contrib2/asir2000/parse/eval.c,v 1.8 2000/12/05 01:24:56 noro Exp $ + * $OpenXM: OpenXM_contrib2/asir2000/parse/eval.c,v 1.46 2005/09/28 08:08:34 noro Exp $ */ #include #include "ca.h" @@ -54,36 +54,39 @@ #include "parse.h" #include #include -#if PARI +#if defined(PARI) #include "genpari.h" #endif -extern jmp_buf timer_env; +extern JMP_BUF timer_env; int f_break,f_return,f_continue; int evalstatline; int recv_intr; +int show_crossref; +void gen_searchf_searchonly(char *name,FUNC *r); -pointer bevalf(), evalmapf(), evall(); -pointer eval_rec_mapf(), beval_rec_mapf(); -Obj getopt_from_cpvs(); - -pointer eval(f) -FNODE f; +pointer eval(FNODE f) { LIST t; STRING str; pointer val = 0; pointer a,a1,a2; - NODE tn,ind; + NODE tn,ind,match; R u; DP dp; - int pv,c; + unsigned int pv; + int c,ret; FNODE f1; UP2 up2; UP up; + UM um; + Obj obj; GF2N gf2n; GFPN gfpn; + GFSN gfsn; + RANGE range; + QUOTE expr,pattern; #if defined(VISUAL) if ( recv_intr ) { @@ -100,10 +103,28 @@ FNODE f; if ( !f ) return ( 0 ); switch ( f->id ) { + case I_PAREN: + val = eval((FNODE)(FA0(f))); + break; + case I_MINUS: + a1 = eval((FNODE)(FA0(f))); + arf_chsgn((Obj)a1,&obj); + val = (pointer)obj; + break; case I_BOP: a1 = eval((FNODE)FA1(f)); a2 = eval((FNODE)FA2(f)); (*((ARF)FA0(f))->fp)(CO,a1,a2,&val); - break; + break; + case I_NARYOP: + tn = (NODE)FA1(f); + a = eval((FNODE)BDY(tn)); + for ( tn = NEXT(tn); tn; tn = NEXT(tn) ) { + a1 = eval((FNODE)BDY(tn)); + (*((ARF)FA0(f))->fp)(CO,a,a1,&a2); + a = a2; + } + val = a; + break; case I_COP: a1 = eval((FNODE)FA1(f)); a2 = eval((FNODE)FA2(f)); c = arf_comp(CO,a1,a2); @@ -158,8 +179,7 @@ FNODE f; case I_FUNC_OPT: val = evalf((FUNC)FA0(f),(FNODE)FA1(f),(FNODE)FA2(f)); break; case I_PFDERIV: - error("eval : not implemented yet"); - break; + val = evalf_deriv((FUNC)FA0(f),(FNODE)FA1(f),(FNODE)FA2(f)); break; case I_MAP: val = evalmapf((FUNC)FA0(f),(FNODE)FA1(f)); break; case I_RECMAP: @@ -176,7 +196,7 @@ FNODE f; expired = (Obj)eval((FNODE)FA2(f)); set_timer(interval); savepvs(); - if ( !setjmp(timer_env) ) + if ( !SETJMP(timer_env) ) val = eval((FNODE)FA1(f)); else { val = (pointer)expired; @@ -189,7 +209,7 @@ FNODE f; case I_PRESELF: f1 = (FNODE)FA1(f); if ( ID(f1) == I_PVAR ) { - pv = (int)FA0(f1); ind = (NODE)FA1(f1); GETPV(pv,a); + pv = (unsigned int)FA0(f1); ind = (NODE)FA1(f1); GETPV(pv,a); if ( !ind ) { (*((ARF)FA0(f))->fp)(CO,a,ONE,&val); ASSPV(pv,val); } else if ( a ) { @@ -202,7 +222,7 @@ FNODE f; case I_POSTSELF: f1 = (FNODE)FA1(f); if ( ID(f1) == I_PVAR ) { - pv = (int)FA0(f1); ind = (NODE)FA1(f1); GETPV(pv,val); + pv = (unsigned int)FA0(f1); ind = (NODE)FA1(f1); GETPV(pv,val); if ( !ind ) { (*((ARF)FA0(f))->fp)(CO,val,ONE,&u); ASSPV(pv,u); } else if ( val ) { @@ -214,7 +234,9 @@ FNODE f; error("-- : not implemented yet"); break; case I_PVAR: - pv = (int)FA0(f); ind = (NODE)FA1(f); GETPV(pv,a); + pv = (unsigned int)FA0(f); + ind = (NODE)FA1(f); + GETPV(pv,a); if ( !ind ) val = a; else { @@ -224,7 +246,7 @@ FNODE f; case I_ASSPVAR: f1 = (FNODE)FA0(f); if ( ID(f1) == I_PVAR ) { - pv = (int)FA0(f1); ind = (NODE)FA1(f1); + pv = (unsigned int)FA0(f1); ind = (NODE)FA1(f1); if ( !ind ) { val = eval((FNODE)FA1(f)); ASSPV(pv,val); } else { @@ -241,6 +263,8 @@ FNODE f; a = eval((FNODE)FA0(f1)); ind = (NODE)FA1(f1); evalnodebody(ind,&tn); putarray(a,tn,val = eval((FNODE)FA1(f))); + } else { + error("eval : invalid assignment"); } break; case I_ANS: @@ -256,12 +280,20 @@ FNODE f; break; case I_GFPNGEN: up = UPALLOC(1); - up->d=1; - up->c[0] = 0; - up->c[1] = (Num)ONELM; + DEG(up)=1; + COEF(up)[0] = 0; + COEF(up)[1] = (Num)ONELM; MKGFPN(up,gfpn); val = (pointer)gfpn; break; + case I_GFSNGEN: + um = UMALLOC(1); + DEG(um) = 1; + COEF(um)[0] = 0; + COEF(um)[1] = _onesf(); + MKGFSN(um,gfsn); + val = (pointer)gfsn; + break; case I_STR: MKSTR(str,FA0(f)); val = (pointer)str; break; case I_FORMULA: @@ -287,8 +319,6 @@ FNODE f; MKLIST(t,NEXT(BDY((LIST)a))); val = (pointer)t; } break; - case I_PROC: - val = (pointer)FA0(f); break; case I_INDEX: a = eval((FNODE)FA0(f)); ind = (NODE)FA1(f); evalnodebody(ind,&tn); getarray(a,tn,&val); @@ -313,15 +343,262 @@ FNODE f; return ( val ); } -pointer evalstat(f) -SNODE f; +NODE quote_to_nary_node(NODE); +NODE quote_to_bin_node(NODE,int); + +FNODE quote_to_nary(FNODE f) { + FNODE a0,a1,a2; + NODE n,t,t0; + pointer val; + char *op; + + if ( !f ) + return f; + switch ( f->id ) { + case I_NARYOP: + n = quote_to_nary_node((NODE)FA1(f)); + return mkfnode(2,I_NARYOP,FA0(f),n); + + case I_BOP: + a1 = quote_to_nary((FNODE)FA1(f)); + a2 = quote_to_nary((FNODE)FA2(f)); + op = ((ARF)FA0(f))->name; + if ( !strcmp(op,"+") || !strcmp(op,"*") ) { + if ( a1->id == I_NARYOP && !strcmp(op,((ARF)FA0(a1))->name) ) { + for ( n = (NODE)FA1(a1); NEXT(n); n = NEXT(n) ); + if ( a2->id == I_NARYOP && !strcmp(op,((ARF)FA0(a2))->name) ) + NEXT(n) = (NODE)FA1(a2); + else + MKNODE(NEXT(n),a2,0); + return a1; + } else if ( a2->id == I_NARYOP && !strcmp(op,((ARF)FA0(a2))->name) ) { + MKNODE(t,a1,(NODE)FA1(a2)); + return mkfnode(2,I_NARYOP,FA0(f),t); + } else { + t = mknode(2,a1,a2); + return mkfnode(2,I_NARYOP,FA0(f),t); + } + } else + return mkfnode(3,f->id,FA0(f),a1,a2); + + case I_NOT: case I_PAREN: case I_MINUS: + case I_CAR: case I_CDR: + a0 = quote_to_nary((FNODE)FA0(f)); + return mkfnode(1,f->id,a0); + + case I_COP: case I_LOP: + a1 = quote_to_nary((FNODE)FA1(f)); + a2 = quote_to_nary((FNODE)FA2(f)); + return mkfnode(3,f->id,FA0(f),a1,a2); + + case I_AND: case I_OR: + a0 = quote_to_nary((FNODE)FA0(f)); + a1 = quote_to_nary((FNODE)FA1(f)); + return mkfnode(2,f->id,a0,a1); + + /* ternary operators */ + case I_CE: + a0 = quote_to_nary((FNODE)FA0(f)); + a1 = quote_to_nary((FNODE)FA1(f)); + a2 = quote_to_nary((FNODE)FA2(f)); + return mkfnode(3,f->id,a0,a1,a2); + break; + + /* function */ + case I_FUNC: + a1 = quote_to_nary((FNODE)FA1(f)); + return mkfnode(2,f->id,FA0(f),a1); + + case I_LIST: case I_EV: + n = quote_to_nary_node((NODE)FA0(f)); + return mkfnode(1,f->id,n); + + case I_STR: case I_FORMULA: case I_PVAR: + return f; + + default: + error("quote_to_nary : not implemented yet"); + } +} + +FNODE quote_to_bin(FNODE f,int dir) +{ + FNODE a0,a1,a2; + NODE n,t; + pointer val; + ARF fun; + int len,i; + FNODE *arg; + + if ( !f ) + return f; + switch ( f->id ) { + case I_NARYOP: + fun = (ARF)FA0(f); + len = length((NODE)FA1(f)); + arg = (FNODE *)ALLOCA(len*sizeof(FNODE)); + for ( i = 0, t = (NODE)FA1(f); i < len; i++, t = NEXT(t) ) + arg[i] = quote_to_bin((FNODE)BDY(t),dir); + if ( dir ) { + a2 = mkfnode(3,I_BOP,fun,arg[len-2],arg[len-1]); + for ( i = len-3; i >= 0; i-- ) + a2 = mkfnode(3,I_BOP,fun,arg[i],a2); + } else { + a2 = mkfnode(3,I_BOP,fun,arg[0],arg[1]); + for ( i = 2; i < len; i++ ) + a2 = mkfnode(3,I_BOP,fun,a2,arg[i]); + } + return a2; + + case I_NOT: case I_PAREN: case I_MINUS: + case I_CAR: case I_CDR: + a0 = quote_to_bin((FNODE)FA0(f),dir); + return mkfnode(1,f->id,a0); + + case I_BOP: case I_COP: case I_LOP: + a1 = quote_to_bin((FNODE)FA1(f),dir); + a2 = quote_to_bin((FNODE)FA2(f),dir); + return mkfnode(3,f->id,FA0(f),a1,a2); + + case I_AND: case I_OR: + a0 = quote_to_bin((FNODE)FA0(f),dir); + a1 = quote_to_bin((FNODE)FA1(f),dir); + return mkfnode(2,f->id,a0,a1); + + /* ternary operators */ + case I_CE: + a0 = quote_to_bin((FNODE)FA0(f),dir); + a1 = quote_to_bin((FNODE)FA1(f),dir); + a2 = quote_to_bin((FNODE)FA2(f),dir); + return mkfnode(3,f->id,a0,a1,a2); + break; + + /* function */ + case I_FUNC: + a1 = quote_to_bin((FNODE)FA1(f),dir); + return mkfnode(2,f->id,FA0(f),a1); + + case I_LIST: case I_EV: + n = quote_to_bin_node((NODE)FA0(f),dir); + return mkfnode(1,f->id,n); + + case I_STR: case I_FORMULA: case I_PVAR: + return f; + + default: + error("quote_to_bin : not implemented yet"); + } +} + +NODE partial_eval_node(NODE n); +FNODE partial_eval(FNODE f); + +FNODE partial_eval(FNODE f) +{ + FNODE a0,a1,a2; + NODE n; + pointer val; + + if ( !f ) + return f; + switch ( f->id ) { + case I_NOT: case I_PAREN: case I_MINUS: + case I_CAR: case I_CDR: + a0 = partial_eval((FNODE)FA0(f)); + return mkfnode(1,f->id,a0); + + case I_BOP: case I_COP: case I_LOP: + a1 = partial_eval((FNODE)FA1(f)); + a2 = partial_eval((FNODE)FA2(f)); + return mkfnode(3,f->id,FA0(f),a1,a2); + + case I_AND: case I_OR: + a0 = partial_eval((FNODE)FA0(f)); + a1 = partial_eval((FNODE)FA1(f)); + return mkfnode(2,f->id,a0,a1); + + /* ternary operators */ + case I_CE: + a0 = partial_eval((FNODE)FA0(f)); + a1 = partial_eval((FNODE)FA1(f)); + a2 = partial_eval((FNODE)FA2(f)); + return mkfnode(3,f->id,a0,a1,a2); + break; + + /* function */ + case I_FUNC: + a1 = partial_eval((FNODE)FA1(f)); + return mkfnode(2,f->id,FA0(f),a1); + + case I_LIST: case I_EV: + n = partial_eval_node((NODE)FA0(f)); + return mkfnode(1,f->id,n); + + case I_STR: case I_FORMULA: + return f; + + /* program variable */ + case I_PVAR: + val = eval(f); + if ( val && OID((Obj)val) == O_QUOTE ) + return partial_eval((FNODE)BDY((QUOTE)val)); + else + return mkfnode(1,I_FORMULA,val); + + default: + error("partial_eval : not implemented yet"); + } +} + +NODE partial_eval_node(NODE n) +{ + NODE r0,r,t; + + for ( r0 = 0, t = n; t; t = NEXT(t) ) { + NEXTNODE(r0,r); + BDY(r) = partial_eval((FNODE)BDY(t)); + } + if ( r0 ) NEXT(r) = 0; + return r0; +} + +NODE quote_to_nary_node(NODE n) +{ + NODE r0,r,t; + + for ( r0 = 0, t = n; t; t = NEXT(t) ) { + NEXTNODE(r0,r); + BDY(r) = quote_to_nary((FNODE)BDY(t)); + } + if ( r0 ) NEXT(r) = 0; + return r0; +} + +NODE quote_to_bin_node(NODE n,int dir) +{ + NODE r0,r,t; + + for ( r0 = 0, t = n; t; t = NEXT(t) ) { + NEXTNODE(r0,r); + BDY(r) = quote_to_bin((FNODE)BDY(t),dir); + } + if ( r0 ) NEXT(r) = 0; + return r0; +} + +V searchvar(char *name); + +pointer evalstat(SNODE f) +{ pointer val = 0,t,s,s1; P u; NODE tn; int i,ac; + V v; V *a; char *buf; + FUNC func; if ( !f ) return ( 0 ); @@ -335,13 +612,13 @@ SNODE f; case S_BP: if ( !nextbp && (!FA1(f) || eval((FNODE)FA1(f))) ) { if ( (FNODE)FA2(f) ) { -#if PARI +#if defined(PARI) pari_outfile = stderr; #endif asir_out = stderr; printexpr(CO,eval((FNODE)FA2(f))); putc('\n',asir_out); fflush(asir_out); -#if PARI +#if defined(PARI) pari_outfile = stdout; #endif asir_out = stdout; @@ -360,7 +637,13 @@ SNODE f; makevar(buf,&u); a[i] = VR(u); substr(CO,0,(Obj)s,VR((P)t),(Obj)u,(Obj *)&s1); s = s1; } - mkpf((char *)FA0(f),(Obj)s,ac,a,0,0,0,(PF *)&val); val = 0; break; + mkpf((char *)FA0(f),(Obj)s,ac,a,0,0,0,(PF *)&val); val = 0; + v = searchvar((char *)FA0(f)); + if ( v ) { + searchpf((char *)FA0(f),&func); + makesrvar(func,&u); + } + break; case S_SINGLE: val = eval((FNODE)FA0(f)); break; case S_CPLX: @@ -412,6 +695,13 @@ SNODE f; break; } f_break = 0; break; + case S_MODULE: + CUR_MODULE = (MODULE)FA0(f); + if ( CUR_MODULE ) + MPVS = CUR_MODULE->pvs; + else + MPVS = 0; + break; default: error("evalstat : unknown id"); break; @@ -419,8 +709,7 @@ SNODE f; return ( val ); } -pointer evalnode(node) -NODE node; +pointer evalnode(NODE node) { NODE tn; pointer val; @@ -434,20 +723,55 @@ NODE node; extern FUNC cur_binf; extern NODE PVSS; -pointer evalf(f,a,opt) -FUNC f; -FNODE a; -FNODE opt; +LIST eval_arg(FNODE a,unsigned int quote) { + LIST l; + FNODE fn; + NODE n,n0,tn; + QUOTE q; + int i; + + for ( tn = (NODE)FA0(a), n0 = 0, i = 0; tn; tn = NEXT(tn), i++ ) { + NEXTNODE(n0,n); + if ( quote & (1<id == I_FORMULA && FA0(fn) + && OID((Obj)FA0(fn))== O_QUOTE ) + BDY(n) = FA0(fn); + else { + MKQUOTE(q,(FNODE)BDY(tn)); + BDY(n) = (pointer)q; + } + } else + BDY(n) = eval((FNODE)BDY(tn)); + } + if ( n0 ) NEXT(n) = 0; + MKLIST(l,n0); + return l; +} + +pointer evalf(FUNC f,FNODE a,FNODE opt) +{ LIST args; pointer val; int i,n,level; - NODE tn,sn,opts; - VS pvs; + NODE tn,sn,opts,opt1,dmy; + VS pvs,prev_mpvs; char errbuf[BUFSIZ]; + static unsigned int stack_size; + static void *stack_base; + FUNC f1; if ( f->id == A_UNDEF ) { - sprintf(errbuf,"evalf : %s undefined",NAME(f)); + gen_searchf_searchonly(f->fullname,&f1); + if ( f1->id == A_UNDEF ) { + sprintf(errbuf,"evalf : %s undefined",NAME(f)); + error(errbuf); + } else + *f = *f1; + } + if ( getsecuremode() && !PVSS && !f->secure ) { + sprintf(errbuf,"evalf : %s not permitted",NAME(f)); error(errbuf); } if ( f->id != A_PARI ) { @@ -459,11 +783,26 @@ FNODE opt; } switch ( f->id ) { case A_BIN: + if ( opt ) { + opts = BDY((LIST)eval(opt)); + /* opts = ["opt1",arg1],... */ + opt1 = BDY((LIST)BDY(opts)); + if ( !strcmp(BDY((STRING)BDY(opt1)),"option_list") ) { + /* + * the special option specification: + * option_list=[["o1","a1"],...] + */ + asir_assert(BDY(NEXT(opt1)),O_LIST,"evalf"); + opts = BDY((LIST)BDY(NEXT(opt1))); + } + } else + opts = 0; if ( !n ) { cur_binf = f; (*f->f.binf)(&val); } else { - args = (LIST)eval(a); + args = (LIST)eval_arg(a,f->quote); + current_option = opts; cur_binf = f; (*f->f.binf)(args?BDY(args):0,&val); } @@ -476,10 +815,32 @@ FNODE opt; cur_binf = 0; break; case A_USR: - args = (LIST)eval(a); - if ( opt ) + /* stack check */ +#if !defined(VISUAL) && !defined(__CYGWIN__) + if ( !stack_size ) { + struct rlimit rl; + getrlimit(RLIMIT_STACK,&rl); + stack_size = rl.rlim_cur; + } + if ( !stack_base ) + stack_base = (void *)GC_get_stack_base(); + if ( (stack_base - (void *)&args) +0x100000 > stack_size ) + error("stack overflow"); +#endif + args = (LIST)eval_arg(a,f->quote); + if ( opt ) { opts = BDY((LIST)eval(opt)); - else + /* opts = ["opt1",arg1],... */ + opt1 = BDY((LIST)BDY(opts)); + if ( !strcmp(BDY((STRING)BDY(opt1)),"option_list") ) { + /* + * the special option specification: + * option_list=[["o1","a1"],...] + */ + asir_assert(BDY(NEXT(opt1)),O_LIST,"evalf"); + opts = BDY((LIST)BDY(NEXT(opt1))); + } + } else opts = 0; pvs = f->f.usrf->pvs; if ( PVSS ) { @@ -502,12 +863,18 @@ FNODE opt; for ( tn = f->f.usrf->args, sn = BDY(args); sn; tn = NEXT(tn), sn = NEXT(sn) ) ASSPV((int)FA0((FNODE)BDY(tn)),BDY(sn)); - val = evalstat((SNODE)BDY(f->f.usrf)); + if ( f->f.usrf->module ) { + prev_mpvs = MPVS; + MPVS = f->f.usrf->module->pvs; + val = evalstat((SNODE)BDY(f->f.usrf)); + MPVS = prev_mpvs; + } else + val = evalstat((SNODE)BDY(f->f.usrf)); f_return = f_break = f_continue = 0; poppvs(); break; case A_PURE: args = (LIST)eval(a); - val = evalpf(f->f.puref,args?BDY(args):0); + val = evalpf(f->f.puref,args?BDY(args):0,0); break; default: sprintf(errbuf,"evalf : %s undefined",NAME(f)); @@ -517,10 +884,30 @@ FNODE opt; return val; } -pointer evalmapf(f,a) -FUNC f; -FNODE a; +pointer evalf_deriv(FUNC f,FNODE a,FNODE deriv) { + LIST args,dargs; + pointer val; + char errbuf[BUFSIZ]; + + switch ( f->id ) { + case A_PURE: + args = (LIST)eval(a); + dargs = (LIST)eval(deriv); + val = evalpf(f->f.puref, + args?BDY(args):0,dargs?BDY(dargs):0); + break; + default: + sprintf(errbuf, + "evalf : %s is not a pure function",NAME(f)); + error(errbuf); + break; + } + return val; +} + +pointer evalmapf(FUNC f,FNODE a) +{ LIST args; NODE node,rest,t,n,r,r0; Obj head; @@ -530,7 +917,7 @@ FNODE a; int len,row,col,i,j; pointer val; - args = (LIST)eval(a); + args = (LIST)eval_arg(a,f->quote); node = BDY(args); head = (Obj)BDY(node); rest = NEXT(node); if ( !head ) { val = bevalf(f,node); @@ -569,21 +956,16 @@ FNODE a; return val; } -pointer eval_rec_mapf(f,a) -FUNC f; -FNODE a; +pointer eval_rec_mapf(FUNC f,FNODE a) { LIST args; - args = (LIST)eval(a); + args = (LIST)eval_arg(a,f->quote); return beval_rec_mapf(f,BDY(args)); } -pointer beval_rec_mapf(f,node) -FUNC f; -NODE node; +pointer beval_rec_mapf(FUNC f,NODE node) { - LIST args; NODE rest,t,n,r,r0; Obj head; VECT v,rv; @@ -632,22 +1014,22 @@ NODE node; return val; } -pointer bevalf(f,a) -FUNC f; -NODE a; +pointer bevalf(FUNC f,NODE a) { pointer val; int i,n; NODE tn,sn; - VS pvs; - struct oLIST list; - struct oFNODE fnode; + VS pvs,prev_mpvs; char errbuf[BUFSIZ]; if ( f->id == A_UNDEF ) { sprintf(errbuf,"bevalf : %s undefined",NAME(f)); error(errbuf); } + if ( getsecuremode() && !PVSS && !f->secure ) { + sprintf(errbuf,"bevalf : %s not permitted",NAME(f)); + error(errbuf); + } if ( f->id != A_PARI ) { for ( i = 0, tn = a; tn; i++, tn = NEXT(tn) ); if ( ((n = f->argc)>= 0 && i != n) || (n < 0 && i > -n) ) { @@ -689,11 +1071,17 @@ NODE a; for ( tn = f->f.usrf->args, sn = a; sn; tn = NEXT(tn), sn = NEXT(sn) ) ASSPV((int)FA0((FNODE)BDY(tn)),BDY(sn)); - val = evalstat((SNODE)BDY(f->f.usrf)); + if ( f->f.usrf->module ) { + prev_mpvs = MPVS; + MPVS = f->f.usrf->module->pvs; + val = evalstat((SNODE)BDY(f->f.usrf)); + MPVS = prev_mpvs; + } else + val = evalstat((SNODE)BDY(f->f.usrf)); f_return = f_break = f_continue = 0; poppvs(); break; case A_PURE: - val = evalpf(f->f.puref,a); + val = evalpf(f->f.puref,a,0); break; default: sprintf(errbuf,"bevalf : %s undefined",NAME(f)); @@ -703,36 +1091,43 @@ NODE a; return val; } -pointer evalif(f,a) -FNODE f,a; +pointer evalif(FNODE f,FNODE a) { Obj g; + FNODE t; g = (Obj)eval(f); if ( g && (OID(g) == O_P) && (VR((P)g)->attr == (pointer)V_SR) ) return evalf((FUNC)VR((P)g)->priv,a,0); - else { + else if ( g && OID(g) == O_QUOTEARG && ((QUOTEARG)g)->type == A_func ) { + t = mkfnode(2,I_FUNC,((QUOTEARG)g)->body,a); + return eval(t); + } else { error("invalid function pointer"); + /* NOTREACHED */ + return (pointer)-1; } } -pointer evalpf(pf,args) -PF pf; -NODE args; +pointer evalpf(PF pf,NODE args,NODE dargs) { Obj s,s1; int i; - NODE node; + NODE node,dnode; PFINS ins; PFAD ad; - char errbuf[BUFSIZ]; if ( !pf->body ) { ins = (PFINS)CALLOC(1,sizeof(PF)+pf->argc*sizeof(struct oPFAD)); ins->pf = pf; - for ( i = 0, node = args, ad = ins->ad; - node; node = NEXT(node), i++ ) { - ad[i].d = 0; ad[i].arg = (Obj)node->body; + for ( i = 0, node = args, dnode = dargs, ad = ins->ad; + node; i++ ) { + ad[i].arg = (Obj)node->body; + if ( !dnode ) ad[i].d = 0; + else + ad[i].d = QTOS((Q)dnode->body); + node = NEXT(node); + if ( dnode ) dnode = NEXT(dnode); } simplify_ins(ins,&s); } else { @@ -744,9 +1139,7 @@ NODE args; return (pointer)s; } -void evalnodebody(sn,dnp) -NODE sn; -NODE *dnp; +void evalnodebody(NODE sn,NODE *dnp) { NODE n,n0,tn; int line; @@ -764,11 +1157,87 @@ NODE *dnp; NEXT(n) = 0; *dnp = n0; } -void searchf(fn,name,r) -NODE fn; -char *name; -FUNC *r; +MODULE searchmodule(char *name) { + MODULE mod; + NODE m; + + for ( m = MODULE_LIST; m; m = NEXT(m) ) { + mod = (MODULE)BDY(m); + if ( !strcmp(mod->name,name) ) + return mod; + } + return 0; +} +/* + * xxx.yyy() is searched in the flist + * of the module xxx. + * yyy() is searched in the global flist. + */ + +void searchuf(char *name,FUNC *r) +{ + MODULE mod; + char *name0,*dot; + + if ( dot = strchr(name,'.') ) { + name0 = (char *)ALLOCA(strlen(name)+1); + strcpy(name0,name); + dot = strchr(name0,'.'); + *dot = 0; + mod = searchmodule(name0); + if ( mod ) + searchf(mod->usrf_list,dot+1,r); + } else + searchf(usrf,name,r); +} + +void gen_searchf(char *name,FUNC *r) +{ + FUNC val = 0; + int global = 0; + if ( *name == ':' ) { + global = 1; + name += 2; + } + if ( CUR_MODULE && !global ) + searchf(CUR_MODULE->usrf_list,name,&val); + if ( !val ) + searchf(sysf,name,&val); + if ( !val ) + searchf(ubinf,name,&val); + if ( !val ) + searchpf(name,&val); + if ( !val ) + searchuf(name,&val); + if ( !val ) + appenduf(name,&val); + *r = val; +} + +void gen_searchf_searchonly(char *name,FUNC *r) +{ + FUNC val = 0; + int global = 0; + if ( *name == ':' ) { + global = 1; + name += 2; + } + if ( CUR_MODULE && !global ) + searchf(CUR_MODULE->usrf_list,name,&val); + if ( !val ) + searchf(sysf,name,&val); + if ( !val ) + searchf(ubinf,name,&val); + if ( !val ) + searchpf(name,&val); + if ( !val ) + searchuf(name,&val); + *r = val; +} + +void searchf(NODE fn,char *name,FUNC *r) +{ NODE tn; for ( tn = fn; @@ -780,47 +1249,100 @@ FUNC *r; *r = 0; } -void appenduf(name,r) -char *name; -FUNC *r; +MODULE mkmodule(char *); + +void appenduf(char *name,FUNC *r) { NODE tn; FUNC f; + int len; + MODULE mod; + char *modname,*fname,*dot; f=(FUNC)MALLOC(sizeof(struct oFUNC)); - f->name = name; f->id = A_UNDEF; f->argc = 0; f->f.binf = 0; - MKNODE(tn,f,usrf); usrf = tn; + f->id = A_UNDEF; f->argc = 0; f->f.binf = 0; + if ( dot = strchr(name,'.') ) { + /* undefined function in a module */ + len = dot-name; + modname = (char *)MALLOC_ATOMIC(len+1); + strncpy(modname,name,len); modname[len] = 0; + fname = (char *)MALLOC_ATOMIC(strlen(name)-len+1); + strcpy(fname,dot+1); + f->name = fname; + f->fullname = name; + mod = searchmodule(modname); + if ( !mod ) + mod = mkmodule(modname); + MKNODE(tn,f,mod->usrf_list); mod->usrf_list = tn; + } else { + f->name = name; + f->fullname = name; + MKNODE(tn,f,usrf); usrf = tn; + } *r = f; } -void mkparif(name,r) -char *name; -FUNC *r; +void appenduf_local(char *name,FUNC *r) { + NODE tn; FUNC f; + MODULE mod; + for ( tn = CUR_MODULE->usrf_list; tn; tn = NEXT(tn) ) + if ( !strcmp(((FUNC)BDY(tn))->name,name) ) + break; + if ( tn ) + return; + + f=(FUNC)MALLOC(sizeof(struct oFUNC)); + f->id = A_UNDEF; f->argc = 0; f->f.binf = 0; + f->name = name; + f->fullname = + (char *)MALLOC_ATOMIC(strlen(CUR_MODULE->name)+strlen(name)+1); + sprintf(f->fullname,"%s.%s",CUR_MODULE->name,name); + MKNODE(tn,f,CUR_MODULE->usrf_list); CUR_MODULE->usrf_list = tn; + *r = f; +} + +void appenduflist(NODE n) +{ + NODE tn; + FUNC f; + + for ( tn = n; tn; tn = NEXT(tn) ) + appenduf_local((char *)BDY(tn),&f); +} + +void mkparif(char *name,FUNC *r) +{ + FUNC f; + *r = f =(FUNC)MALLOC(sizeof(struct oFUNC)); f->name = name; f->id = A_PARI; f->argc = 0; f->f.binf = 0; + f->fullname = name; } -void mkuf(name,fname,args,body,startl,endl,desc) -char *name,*fname; -NODE args; -SNODE body; -int startl,endl; -char *desc; +void mkuf(char *name,char *fname,NODE args,SNODE body,int startl,int endl,char *desc,MODULE module) { FUNC f; USRF t; - NODE sn,tn; + NODE usrf_list,sn,tn; FNODE fn; + char *longname; int argc; - searchf(sysf,name,&f); - if ( f ) { - fprintf(stderr,"def : builtin function %s() cannot be redefined.\n",name); - CPVS = GPVS; return; + if ( getsecuremode() ) { + error("defining function is not permitted in the secure mode"); } + if ( *name == ':' ) + name += 2; + if ( !module ) { + searchf(sysf,name,&f); + if ( f ) { + fprintf(stderr,"def : builtin function %s() cannot be redefined.\n",name); + CPVS = GPVS; return; + } + } for ( argc = 0, sn = args; sn; argc++, sn = NEXT(sn) ) { fn = (FNODE)BDY(sn); if ( !fn || ID(fn) != I_PVAR ) { @@ -828,24 +1350,37 @@ char *desc; CPVS = GPVS; return; } } - for ( sn = usrf; sn && strcmp(NAME((FUNC)BDY(sn)),name); sn = NEXT(sn) ); + usrf_list = module ? module->usrf_list : usrf; + for ( sn = usrf_list; sn && strcmp(NAME((FUNC)BDY(sn)),name); sn = NEXT(sn) ); if ( sn ) f = (FUNC)BDY(sn); else { f=(FUNC)MALLOC(sizeof(struct oFUNC)); f->name = name; - MKNODE(tn,f,usrf); usrf = tn; + MKNODE(tn,f,usrf_list); usrf_list = tn; + if ( module ) { + f->fullname = + (char *)MALLOC_ATOMIC(strlen(f->name)+strlen(module->name)+1); + sprintf(f->fullname,"%s.%s",module->name,f->name); + module->usrf_list = usrf_list; + } else { + f->fullname = f->name; + usrf = usrf_list; + } } - if ( Verbose && f->id != A_UNDEF ) - fprintf(stderr,"Warning : %s() redefined.\n",name); -/* else - fprintf(stderr,"%s() defined.\n",name); */ + if ( Verbose && f->id != A_UNDEF ) { + if ( module ) + fprintf(stderr,"Warning : %s.%s() redefined.\n",module->name,name); + else + fprintf(stderr,"Warning : %s() redefined.\n",name); + } t=(USRF)MALLOC(sizeof(struct oUSRF)); t->args=args; BDY(t)=body; t->pvs = CPVS; t->fname = fname; - t->startl = startl; t->endl = endl; t->vol = asir_infile->vol; + t->startl = startl; t->endl = endl; t->module = module; t->desc = desc; f->id = A_USR; f->argc = argc; f->f.usrf = t; CPVS = GPVS; + CUR_FUNC = 0; clearbp(f); } @@ -855,19 +1390,65 @@ char *desc; CVS->opt = BDY([[key,value],[key,value],...]) */ -Obj getopt_from_cpvs(key) -char *key; +Obj getopt_from_cpvs(char *key) { NODE opts,opt; - Obj value; + LIST r; extern Obj VOIDobj; opts = CPVS->opt; - for ( ; opts; opts = NEXT(opts) ) { - opt = BDY((LIST)BDY(opts)); - if ( !strcmp(key,BDY((STRING)BDY(opt))) ) - return (Obj)BDY(NEXT(opt)); + if ( !key ) { + MKLIST(r,opts); + return (Obj)r; + } else { + for ( ; opts; opts = NEXT(opts) ) { + asir_assert(BDY(opts),O_LIST,"getopt_from_cvps"); + opt = BDY((LIST)BDY(opts)); + if ( !strcmp(key,BDY((STRING)BDY(opt))) ) + return (Obj)BDY(NEXT(opt)); + } + return VOIDobj; } - return VOIDobj; +} + +MODULE mkmodule(char *name) +{ + MODULE mod; + NODE m; + int len; + VS mpvs; + + for ( m = MODULE_LIST; m; m = NEXT(m) ) { + mod = (MODULE)m->body; + if ( !strcmp(mod->name,name) ) + break; + } + if ( m ) + return mod; + else { + mod = (MODULE)MALLOC(sizeof(struct oMODULE)); + len = strlen(name); + mod->name = (char *)MALLOC_ATOMIC(len+1); + strcpy(mod->name,name); + mod->pvs = mpvs = (VS)MALLOC(sizeof(struct oVS)); + reallocarray((char **)&mpvs->va,(int *)&mpvs->asize, + (int *)&mpvs->n,(int)sizeof(struct oPV)); + mod->usrf_list = 0; + MKNODE(m,mod,MODULE_LIST); + MODULE_LIST = m; + return mod; + } +} + +void print_crossref(FUNC f) +{ + FUNC r; + if ( show_crossref && CUR_FUNC ) { + searchuf(f->fullname,&r); + if (r != NULL) { + fprintf(asir_out,"%s() at line %d in %s()\n", + f->fullname, asir_infile->ln, CUR_FUNC); + } + } }