diff --git a/src/Makefile.in b/src/Makefile.in index a80a14d09b99305943e36046fa9abba0b428f5ff..5d5b002114e6f67b567be5bd2c44793ab9a73ac4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -67,6 +67,7 @@ MAKE_FLAGS = "prefix=$(prefix)" "exec_prefix=$(exec_prefix)" "CC=$(CC)" "OTHERFL OBJ= \ language.o \ constants.o \ + cyclic.o \ array.o \ backend.o \ builtin_functions.o \ diff --git a/src/array.c b/src/array.c index db9d2e1acb1441ebb128f71ed58d15acba12a171..202c61c614824235435f02b554a12769af8924f9 100644 --- a/src/array.c +++ b/src/array.c @@ -27,6 +27,7 @@ struct array empty_array= 0, /* Size = 0 */ 0, /* malloced Size = 0 */ 0, /* no types */ + 0, /* no flags */ }; @@ -143,8 +144,8 @@ void array_index(struct svalue *s,struct array *v,INT32 index) free_array(v); } - -void simple_array_index_no_free(struct svalue *s,struct array *a,struct svalue *ind) +void simple_array_index_no_free(struct svalue *s, + struct array *a,struct svalue *ind) { INT32 i; switch(ind->type) @@ -164,7 +165,7 @@ void simple_array_index_no_free(struct svalue *s,struct array *a,struct svalue * s[0]=sp[-1]; sp--; break; - + default: error("Index is not an integer.\n"); } diff --git a/src/array.h b/src/array.h index 96f97c20bcb97827c696e36da74e817fe5b1918d..009bccf099f1088f25fd22c0f82a000ae19f286f 100644 --- a/src/array.h +++ b/src/array.h @@ -20,9 +20,11 @@ struct array * Bits can be set that don't exist in the array * though. */ + INT16 flags; /* ARRAY_* flags */ struct svalue item[1]; }; +#define ARRAY_CYCLIC 1 extern struct array empty_array; diff --git a/src/builtin_functions.c b/src/builtin_functions.c index b61d3f0cda196637643833b0756164c0446b2e28..dbf0874dc5cdcd042531bb36e4248586965af107 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.45 1997/09/11 02:13:10 hubbe Exp $"); +RCSID("$Id: builtin_functions.c,v 1.46 1997/10/03 02:25:35 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -35,6 +35,7 @@ RCSID("$Id: builtin_functions.c,v 1.45 1997/09/11 02:13:10 hubbe Exp $"); #include "module_support.h" #include "module.h" #include "opcodes.h" +#include "cyclic.h" #ifdef HAVE_CRYPT_H #include <crypt.h> @@ -1294,6 +1295,7 @@ void f_column(INT32 args) { INT32 e; struct array *a,*tmp; + DECLARE_CYCLIC(); if(args < 2) error("Too few arguments to column().\n"); @@ -1302,14 +1304,23 @@ void f_column(INT32 args) error("Bad argument 1 to column().\n"); tmp=sp[-args].u.array; - push_array(a=allocate_array(tmp->size)); + if((a=(struct array *)BEGIN_CYCLIC(tmp,0))) + { + a->refs++; + pop_n_elems(args); + push_array(a); + }else{ + push_array(a=allocate_array(tmp->size)); + SET_CYCLIC_RET(a); - for(e=0;e<a->size;e++) - index_no_free(ITEM(a)+e, ITEM(tmp)+e, sp-args); + for(e=0;e<a->size;e++) + index_no_free(ITEM(a)+e, ITEM(tmp)+e, sp-args); - a->refs++; - pop_n_elems(args+1); - push_array(a); + END_CYCLIC(); + a->refs++; + pop_n_elems(args+1); + push_array(a); + } } #ifdef DEBUG diff --git a/src/cyclic.c b/src/cyclic.c new file mode 100644 index 0000000000000000000000000000000000000000..cb8a7395a25d5a26914efeb647a2cc8732808403 --- /dev/null +++ b/src/cyclic.c @@ -0,0 +1,65 @@ +#include "cyclic.h" + +#define CYCLIC_HASH_SIZE 4711 + +CYCLIC *cyclic_hash[CYCLIC_HASH_SIZE]; + +void unlink_cyclic(CYCLIC *c) +{ + unsigned int h; + CYCLIC **p; + h=(int)c->id; + h*=33; + h|=(int)c->a; + h*=33; + h|=(int)c->b; + h*=33; + h|=(int)c->th; + h*=33; + h%=CYCLIC_HASH_SIZE; + + for(p=cyclic_hash+h;*p;p=&(p[0]->next)) + { + if(c == *p) + { + *p=c->next; + UNSET_ONERROR(c->onerr); + return; + } + } + fatal("Unlink cyclic on lost cyclic struct.\n"); +} + +void *begin_cyclic(CYCLIC *c, + void *id, + void *th, + void *a, + void *b) +{ + unsigned int h; + CYCLIC *p; + + h=(int)id; + h*=33; + h|=(int)a; + h*=33; + h|=(int)b; + h*=33; + h|=(int)th; + h*=33; + h%=CYCLIC_HASH_SIZE; + + for(p=cyclic_hash[h];p;p=p->next) + if(a == p->a && b==p->b && id==p->id) + return p->ret; + + c->ret=(void *)1; + c->a=a; + c->b=b; + c->id=id; + c->th=th; + c->next=cyclic_hash[h]; + cyclic_hash[h]=c; + SET_ONERROR(c->onerr, unlink_cyclic, &c); + return 0; +} diff --git a/src/cyclic.h b/src/cyclic.h new file mode 100644 index 0000000000000000000000000000000000000000..374948d5f174ca1af5103b10706b4439ef30286e --- /dev/null +++ b/src/cyclic.h @@ -0,0 +1,39 @@ +#ifndef CYCLIC_H +#define CYCLIC_H + +#include "error.h" +#include "threads.h" + +typedef struct CYCLIC +{ + ONERROR onerr; + void *th; + void *id,*a,*b; + void *ret; + struct CYCLIC *next; +} CYCLIC; + + +#define DECLARE_CYCLIC() \ + static char cyclic_identifier__; \ + CYCLIC cyclic_struct__ + +#define BEGIN_CYCLIC(A,B) \ + begin_cyclic(&cyclic_struct__, &cyclic_identifier__, th_self(), (void *)(A), (void *)(B)) + +#define SET_CYCLIC_RET(RET) \ + cyclic_struct__.ret=(void *)(RET) + +#define END_CYCLIC() unlink_cyclic(&cyclic_struct__) + +/* Prototypes begin here */ +void unlink_cyclic(CYCLIC *c); +void *begin_cyclic(CYCLIC *c, + void *id, + void *thread, + void *a, + void *b); +/* Prototypes end here */ + +#endif /* CYCLIC_H */ + diff --git a/src/testsuite.in b/src/testsuite.in index 2b901081da4c8a23c48010e93239614da0dc9ab4..4c55135a4dda8a55ce78053c14c9a3010419ba07 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -1,4 +1,4 @@ -test_true([["$Id: testsuite.in,v 1.55 1997/09/29 00:57:55 hubbe Exp $"]]) +test_true([["$Id: testsuite.in,v 1.56 1997/10/03 02:25:37 hubbe Exp $"]]) test_eq(1e1,10.0) test_eq(1E1,10.0) test_eq(1e+1,10.0) @@ -10,7 +10,7 @@ test_eq("\x20","\040") test_eq(class { static int foo=17; }()->foo,0) test_eval_error(class { static int foo=17; }()->foo=18;) test_equal( [[ ({ (["foo":"bar"]), (<"foo">), ([]) })->foo ]], [[ ({"bar",1,0}) ]]) -test_eval_error([[mixed a=({([]),0}); a[1]=a; return a->foo;]]) +test_any([[mixed a=({([]),0}); a[1]=a; return a->foo[0];]],0) test_any([[ class p1 { int foo() { return 1; }}; diff --git a/src/threads.h b/src/threads.h index 0f223848e36bdd9460c264d6f1d638336b738525..cfe2e395298567e2fd1878dab481f4b30a36ade1 100644 --- a/src/threads.h +++ b/src/threads.h @@ -279,6 +279,7 @@ void th_cleanup(void); #define th_init() #define th_cleanup() #define th_init_programs() +#define th_self() ((void*)0) #endif /* _REENTRANT */