Index: interpret.h
===================================================================
--- interpret.h	(Revision 2411)
+++ interpret.h	(Arbeitskopie)
@@ -80,6 +80,16 @@
        */
 };
 
+/* a general error handler structure. head is assigned as payload to an 
+ * T_LVALUE svalue of type T_ERROR_HANDLER and pushed onto the value stack.
+ * If the stack is unrolled during runtime errors the error_handler function
+ * is called and frees buff. */
+typedef struct errorhandler_s {
+  svalue_t head;        /* The T_ERROR_HANDLER structure */
+  char     * buff;      /* The allocated buffer to free. */
+} errorhandler_t;
+
+
 /* --- Macros --- */
 
 #define MAX_SHIFT ((sizeof(p_int) << 3) - 1)
@@ -147,6 +157,11 @@
 extern void push_svalue_block(int num, svalue_t *v);
 extern svalue_t *pop_n_elems (int n, svalue_t *sp);
 extern void pop_stack(void);
+extern void push_apply_value(void);
+extern void pop_apply_value (void);
+extern void push_referenced_mapping(mapping_t *m);
+extern void push_error_handler(void (*errorhandler)(svalue_t *), svalue_t *arg);
+extern void *alloc_with_error_handler(size_t size);
 
 extern void init_interpret(void);
 extern const char *typename(int type);
@@ -161,8 +176,7 @@
 extern Bool privilege_violation(string_t *what, svalue_t *arg, svalue_t *sp);
 extern Bool privilege_violation2(string_t *what, svalue_t *arg, svalue_t *arg2, svalue_t *sp);
 extern Bool privilege_violation4(string_t *what, object_t *whom, string_t *how_str, int how_num, svalue_t *sp);
-extern void push_apply_value(void);
-extern void pop_apply_value (void);
+
 extern svalue_t *sapply_int(string_t *fun, object_t *ob, int num_arg, Bool b_ign_prot, Bool b_use_default);
 #define sapply(f,o,n) sapply_int(f,o,n, MY_FALSE, MY_TRUE)
 #define sapply_ign_prot(f,o,n) sapply_int(f,o,n, MY_TRUE, MY_TRUE)
@@ -193,8 +207,6 @@
 extern inherit_t *adjust_variable_offsets(const inherit_t *inheritp, const program_t *prog, const object_t *obj);
 extern void free_interpreter_temporaries(void);
 extern void invalidate_apply_low_cache(void);
-extern void push_referenced_mapping(mapping_t *m);
-extern void push_error_handler(void (*errorhandler)(svalue_t *), svalue_t *arg);
 extern void m_indices_filter (svalue_t *key, svalue_t *data, void *extra);
 extern void m_values_filter (svalue_t *key, svalue_t *data, void *extra);
 extern void m_unmake_filter ( svalue_t *key, svalue_t *data, void *extra);
Index: interpret.c
===================================================================
--- interpret.c	(Revision 2426)
+++ interpret.c	(Arbeitskopie)
@@ -2720,6 +2720,7 @@
     return r;
 } /* inter_add_array() */
 
+
 /*=========================================================================*/
 
 /*                           S T A C K                                     */
@@ -6417,6 +6418,55 @@
 } /* test_efun_args() */
 
 
+/*-------------------------------------------------------------------------*/
+/* general errorhandler */
+static void
+general_error_handler( svalue_t * arg)
+/* The error handler: free the allocated buffer and the errorhandler structure.
+ * Note: it is static, but the compiler will have to emit a function and 
+ * symbol for this because the address of the function is taken and it is 
+ * therefore not suitable to be inlined.
+ */
+{
+  errorhandler_t *handler = (errorhandler_t *)arg;
+  if (handler->buff)
+    xfree(handler->buff);
+  xfree(handler);
+} /* general_error_handler() */
+
+/*-------------------------------------------------------------------------*/
+void *
+alloc_with_error_handler(size_t size)
+/* Allocates <size> bytes from the heap. Additionally an error handler is
+ * pushed onto the value stack so that the requested memory is safely freed,
+ * either by manually freeing the svalue on the stack or during stack 
+ * unwinding during errorf().
+ * inter_sp has to point to the top-of-stack before calling and is updated to
+ * point to the error handler svalue (new top-of-stack)!
+ */
+{
+  void *buffer;
+  errorhandler_t *handler;
+  /* get the memory for the handler first and fail if out-of-memory */
+  handler = xalloc(sizeof(*handler));
+  if (!handler)
+  {
+    return NULL;
+  }
+  /* then get the requested memory - upon error de-allocate the handler */
+  buffer = xalloc(size);
+  if (!buffer)
+  {
+    xfree(handler);
+    return NULL;
+  }
+  handler->buff = buffer;
+  /* now push error handler onto the value stack */
+  push_error_handler(general_error_handler, &(handler->head));
+  return buffer;
+} /* alloc_with_error_handler */
+
+
 /*=========================================================================*/
 /*-------------------------------------------------------------------------*/
 Bool
