From 81b84ef106277b67b22a344f05921e04b6c183d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Tue, 3 Dec 1996 13:41:19 -0800
Subject: [PATCH] callbacks modified to handle recursive calls better

Rev: src/backend.c:1.7
Rev: src/builtin_functions.c:1.15
Rev: src/callback.c:1.3
Rev: src/callback.h:1.2
Rev: src/gc.h:1.5
Rev: src/interpret.c:1.15
Rev: src/interpret.h:1.5
Rev: src/main.c:1.12
---
 src/backend.c           |  4 +--
 src/builtin_functions.c |  4 +--
 src/callback.c          | 57 +++++++++++++++++++++++++++++++++++------
 src/callback.h          | 12 ++++++---
 src/gc.h                |  2 +-
 src/interpret.c         |  4 +--
 src/interpret.h         |  2 +-
 src/main.c              |  4 +--
 8 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/src/backend.c b/src/backend.c
index f7cfb922c8..a951c59bca 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: backend.c,v 1.6 1996/11/22 00:05:41 hubbe Exp $");
+RCSID("$Id: backend.c,v 1.7 1996/12/03 21:41:15 hubbe Exp $");
 #include "backend.h"
 #include <errno.h>
 #ifdef HAVE_SYS_TYPES_H
@@ -45,7 +45,7 @@ static int max_fd;
 struct timeval current_time;
 struct timeval next_timeout;
 
-static struct callback *backend_callbacks = 0;
+static struct callback_list backend_callbacks;
 
 struct callback *add_backend_callback(callback_func call,
 				      void *arg,
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 8b422b2431..6b1615cd6e 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.14 1996/12/02 07:02:25 hubbe Exp $");
+RCSID("$Id: builtin_functions.c,v 1.15 1996/12/03 21:41:15 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "macros.h"
@@ -595,7 +595,7 @@ void f_throw(INT32 args)
   throw();
 }
 
-static struct callback *exit_callbacks=0;
+static struct callback_list exit_callbacks;
 
 struct callback *add_exit_callback(callback_func call,
 				   void *arg,
diff --git a/src/callback.c b/src/callback.c
index e900dd4530..ff150380d4 100644
--- a/src/callback.c
+++ b/src/callback.c
@@ -33,6 +33,30 @@ static struct callback_block *callback_chunks=0;
 static struct callback *first_callback =0;
 static struct callback *free_callbacks =0;
 
+#ifdef DEBUG
+static void check_callback_chain(struct callback_list *lst)
+{
+  int len=0;
+  struct callback *foo;
+  for(foo=lst->callbacks;foo;foo=foo->next)
+  {
+    if((len & 1024)==1023)
+    {
+      int len2=0;
+      struct callback *tmp;
+      for(tmp=foo->next;tmp && len2<=len;tmp=tmp->next)
+      {
+	if(tmp==foo)
+	  fatal("Callback list is cyclic!!!\n");
+      }
+    }
+    len++;
+  }
+}
+#else
+#define check_callback_chain(X)
+#endif
+
 /* Return the first free callback struct, allocate more if needed */
 static struct callback *get_free_callback()
 {
@@ -58,12 +82,24 @@ static struct callback *get_free_callback()
 /* Traverse a linked list of callbacks and call all the active callbacks
  * in the list. Deactivated callbacks are freed and placed in the free list.
  */
-void call_callback(struct callback **ptr, void *arg)
+void call_callback(struct callback_list *lst, void *arg)
 {
-  struct callback *l;
+  int this_call;
+  struct callback *l,**ptr;
+
+  lst->num_calls++;
+  this_call=lst->num_calls;
+
+  check_callback_chain(lst);
+  ptr=&lst->callbacks;
   while(l=*ptr)
   {
-    if(l->call) l->call(l,l->arg, arg);
+    if(l->call)
+    {
+      l->call(l,l->arg, arg);
+      if(lst->num_calls != this_call) return;
+    }
+    check_callback_chain(lst);
 
     if(!l->call)
     {
@@ -73,11 +109,12 @@ void call_callback(struct callback **ptr, void *arg)
     }else{
       ptr=& l->next;
     }
+    check_callback_chain(lst);
   }
 }
 
 /* Add a callback to the linked list pointed to by ptr. */
-struct callback *add_to_callback(struct callback **ptr,
+struct callback *add_to_callback(struct callback_list *lst,
 				 callback_func call,
 				 void *arg,
 				 callback_func free_func)
@@ -87,8 +124,10 @@ struct callback *add_to_callback(struct callback **ptr,
   l->call=call;
   l->arg=arg;
 
-  l->next=*ptr;
-  *ptr=l;
+  l->next=lst->callbacks;
+  lst->callbacks=l;
+
+  check_callback_chain(lst);
 
   return l;
 }
@@ -103,9 +142,11 @@ void *remove_callback(struct callback *l)
 }
 
 /* Free all the callbacks in a linked list of callbacks */
-void free_callback(struct callback **ptr)
+void free_callback(struct callback_list *lst)
 {
-  struct callback *l;
+  struct callback *l,**ptr;
+  check_callback_chain(lst);
+  ptr=& lst->callbacks;
   while(l=*ptr)
   {
     if(l->arg && l->free_func)
diff --git a/src/callback.h b/src/callback.h
index 29c36594be..104847cf2d 100644
--- a/src/callback.h
+++ b/src/callback.h
@@ -10,18 +10,24 @@
 
 struct callback;
 
+struct callback_list
+{
+  struct callback *callbacks;
+  int num_calls;
+};
+
 typedef void (*callback_func)(struct callback *, void *,void *);
 
 /* Prototypes begin here */
 struct callback;
 struct callback_block;
-void call_callback(struct callback **ptr, void *arg);
-struct callback *add_to_callback(struct callback **ptr,
+void call_callback(struct callback_list *lst, void *arg);
+struct callback *add_to_callback(struct callback_list *lst,
 				 callback_func call,
 				 void *arg,
 				 callback_func free_func);
 void *remove_callback(struct callback *l);
-void free_callback(struct callback **ptr);
+void free_callback(struct callback_list *ptr);
 void cleanup_callbacks();
 /* Prototypes end here */
 
diff --git a/src/gc.h b/src/gc.h
index 927d1a5e05..9f6cb70743 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -11,7 +11,7 @@ extern INT32 num_allocs;
 extern INT32 alloc_threshold;
 
 extern struct callback *gc_evaluator_callback;
-extern struct callback *evaluator_callbacks;
+extern struct callback_list evaluator_callbacks;
 
 #define ADD_GC_CALLBACK() gc_evaluator_callback=add_to_callback(&evaluator_callbacks,(callback_func)do_gc,0,0)
 
diff --git a/src/interpret.c b/src/interpret.c
index 2901c77bcc..1cb4bc837b 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.14 1996/12/01 13:03:55 hubbe Exp $");
+RCSID("$Id: interpret.c,v 1.15 1996/12/03 21:41:18 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -307,7 +307,7 @@ void pop_n_elems(INT32 x)
 }
 
 
-struct callback *evaluator_callbacks =0;
+struct callback_list evaluator_callbacks;
 
 /* This function is called 'every now and then'. (1-10000 / sec or so)
  * It should do anything that needs to be done fairly often.
diff --git a/src/interpret.h b/src/interpret.h
index 0733429568..618d7b3de7 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -103,6 +103,6 @@ extern struct frame *fp; /* frame pointer */
 extern int stack_size;
 extern int evaluator_stack_malloced, mark_stack_malloced;
 struct callback;
-extern struct callback *evaluator_callbacks;
+extern struct callback_list evaluator_callbacks;
 #endif
 
diff --git a/src/main.c b/src/main.c
index 725f4b5c78..0938c231df 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,7 +4,7 @@
 ||| See the files COPYING and DISCLAIMER for more information.
 \*/
 #include "global.h"
-RCSID("$Id: main.c,v 1.11 1996/11/22 20:58:23 hubbe Exp $");
+RCSID("$Id: main.c,v 1.12 1996/12/03 21:41:19 hubbe Exp $");
 #include "types.h"
 #include "backend.h"
 #include "module.h"
@@ -40,7 +40,7 @@ int a_flag=0;
 int l_flag=0;
 int p_flag=0;
 
-static struct callback *post_master_callbacks =0;
+static struct callback_list post_master_callbacks;
 
 struct callback *add_post_master_callback(callback_func call,
 					  void *arg,
-- 
GitLab