From 8e9fdf40be24b1a5c742605339957a4000a291ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Wed, 4 Dec 1996 20:49:38 -0800
Subject: [PATCH] new functions: _next and _prev

Rev: doc/builtin/_next:1.1
Rev: doc/builtin/_prev:1.1
Rev: doc/builtin/zero_type:1.3
Rev: src/builtin_functions.c:1.18
Rev: src/testsuite.in:1.12
---
 doc/builtin/_next       | 14 +++++++++
 doc/builtin/_prev       | 14 +++++++++
 doc/builtin/zero_type   |  4 ++-
 src/builtin_functions.c | 68 +++++++++++++++++++++++++++++++++++++++--
 src/testsuite.in        |  8 ++++-
 5 files changed, 104 insertions(+), 4 deletions(-)
 create mode 100644 doc/builtin/_next
 create mode 100644 doc/builtin/_prev

diff --git a/doc/builtin/_next b/doc/builtin/_next
new file mode 100644
index 0000000000..3f9465795d
--- /dev/null
+++ b/doc/builtin/_next
@@ -0,0 +1,14 @@
+NAME
+	_next - find the next object/array/whatever
+
+SYNTAX
+	mixed _next(mixed p);
+
+DESCRIPTION
+	This function returns the 'next' object/array/mapping/string/etc
+	in the linked list. It is mainly meant for debugging Pike but
+	can also be used to control memory usage.
+
+SEE ALSO
+	next_object, _prev
+	
\ No newline at end of file
diff --git a/doc/builtin/_prev b/doc/builtin/_prev
new file mode 100644
index 0000000000..f39d649dd1
--- /dev/null
+++ b/doc/builtin/_prev
@@ -0,0 +1,14 @@
+NAME
+	_prev - find the previous object/array/whatever
+
+SYNTAX
+	mixed _next(mixed p);
+
+DESCRIPTION
+	This function returns the 'previous' object/array/mapping/etc
+	in the linked list. It is mainly meant for debugging Pike but
+	can also be used to control memory usage. Note that this function
+	does not work on strings.
+
+SEE ALSO
+	_next
diff --git a/doc/builtin/zero_type b/doc/builtin/zero_type
index 9c615153e4..5f55f8a0e0 100644
--- a/doc/builtin/zero_type
+++ b/doc/builtin/zero_type
@@ -11,7 +11,9 @@ DESCRIPTION
 	The only way to separate these two kinds of zeros is zero_type.
 	When doing a find_call_out or mapping lookup, zero_type on this value
 	will return 1 if there was no such thing present in the mappping, or
-	no such call_out could be found. Otherwize zero_type will return zero.
+	no such call_out could be found. If the argument to zero type is a
+	destructed object or a function in a destructed object, 2 will be
+	returned. Otherwize zero_type will return zero.
 
 	If the argument is not an int, zero will be returned.
 
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index b68fbdd0c8..71e7dd2f5e 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.17 1996/12/05 02:32:35 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.18 1996/12/05 04:49:38 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "macros.h"
@@ -515,7 +515,14 @@ void f_zero_type(INT32 args)
   {
     pop_n_elems(args);
     push_int(0);
-  }else{
+  }
+  else if((sp[-args].type==T_OBJECT || sp[-args].type==T_FUNCTION)
+	   && !sp[-args].u.object->prog)
+  {
+    pop_n_elems(args);
+    push_int(NUMBER_DESTRUCTED);
+  }
+  {
     pop_n_elems(args-1);
     sp[-1].u.integer=sp[-1].subtype;
     sp[-1].subtype=NUMBER_NUMBER;
@@ -1509,6 +1516,61 @@ void f__memory_usage(INT32 args)
   f_aggregate_mapping(sp-ss);
 }
 
+void f__next(INT32 args)
+{
+  struct svalue tmp;
+  if(!args)
+    error("Too few arguments to _next()\n");
+  
+  pop_n_elems(args-1);
+  tmp=sp[-1];
+  switch(tmp.type)
+  {
+  case T_OBJECT:  tmp.u.object=tmp.u.object->next; break;
+  case T_ARRAY:   tmp.u.array=tmp.u.array->next; break;
+  case T_MAPPING: tmp.u.mapping=tmp.u.mapping->next; break;
+  case T_MULTISET:tmp.u.multiset=tmp.u.multiset->next; break;
+  case T_PROGRAM: tmp.u.program=tmp.u.program->next; break;
+  case T_STRING:  tmp.u.string=tmp.u.string->next; break;
+  default:
+    error("Bad argument 1 to _next()\n");
+  }
+  if(tmp.u.refs)
+  {
+    assign_svalue(sp-1,&tmp);
+  }else{
+    pop_stack();
+    push_int(0);
+  }
+}
+
+void f__prev(INT32 args)
+{
+  struct svalue tmp;
+  if(!args)
+    error("Too few arguments to _next()\n");
+  
+  pop_n_elems(args-1);
+  tmp=sp[-1];
+  switch(tmp.type)
+  {
+  case T_OBJECT:  tmp.u.object=tmp.u.object->prev; break;
+  case T_ARRAY:   tmp.u.array=tmp.u.array->prev; break;
+  case T_MAPPING: tmp.u.mapping=tmp.u.mapping->prev; break;
+  case T_MULTISET:tmp.u.multiset=tmp.u.multiset->prev; break;
+  case T_PROGRAM: tmp.u.program=tmp.u.program->prev; break;
+  default:
+    error("Bad argument 1 to _prev()\n");
+  }
+  if(tmp.u.refs)
+  {
+    assign_svalue(sp-1,&tmp);
+  }else{
+    pop_stack();
+    push_int(0);
+  }
+}
+
 void init_builtin_efuns()
 {
   init_operators();
@@ -1547,6 +1609,8 @@ void init_builtin_efuns()
   add_efun("mappingp",f_mappingp,"function(mixed:int)",OPT_TRY_OPTIMIZE);
   add_efun("mkmapping",f_mkmapping,"function(mixed *,mixed *:mapping)",OPT_TRY_OPTIMIZE);
   add_efun("next_object",f_next_object,"function(void|object:object)",OPT_EXTERNAL_DEPEND);
+  add_efun("_next",f__next,"function(string:string)|function(object:object)|function(mapping:mapping)|function(multiset:multiset)|function(program:program)|function(array:array)",OPT_EXTERNAL_DEPEND);
+  add_efun("_prev",f__prev,"function(object:object)|function(mapping:mapping)|function(multiset:multiset)|function(program:program)|function(array:array)",OPT_EXTERNAL_DEPEND);
   add_efun("object_program",f_object_program,"function(mixed:program)",0);
   add_efun("objectp", f_objectp, "function(mixed:int)",0);
   add_efun("programp",f_programp,"function(mixed:int)",0);
diff --git a/src/testsuite.in b/src/testsuite.in
index d533b24b6f..b2cb49479b 100644
--- a/src/testsuite.in
+++ b/src/testsuite.in
@@ -1,4 +1,10 @@
-test_true([["$Id: testsuite.in,v 1.11 1996/12/02 07:02:57 hubbe Exp $"]])
+test_true(mappingp(_memory_usage()))
+test_true(objectp( _next(this_object()) || _prev(this_object())))
+test_true(arrayp( _next(({})) || _prev(({}))))
+test_any(object o=this_object(); while(o=_next(o)));
+test_any(object o=this_object(); while(o=_prev(o)));
+
+test_true([["$Id: testsuite.in,v 1.12 1996/12/05 04:49:38 hubbe Exp $"]])
 test_any([[object(File) o=File(); return objectp(o);]],1)
 test_any([[object o=Regexp("foo"); return objectp(o);]],1)
 test_any([[object o=Regexp("foo"); return object_program(o);]],Regexp)
-- 
GitLab