You are viewing a plain text version of this content. The canonical link for it is here.
Posted to rivet-dev@tcl.apache.org by mx...@apache.org on 2011/03/01 19:05:21 UTC

svn commit: r1075953 - in /tcl/rivet/branches/2.0: ChangeLog Makefile.in VERSION configure.ac src/apache-1/mod_rivet.c src/apache-1/mod_rivet.h src/apache-1/rivetCore.c src/apache-2/mod_rivet.c src/apache-2/mod_rivet.h src/apache-2/rivetCore.c

Author: mxmanghi
Date: Tue Mar  1 18:05:20 2011
New Revision: 1075953

URL: http://svn.apache.org/viewvc?rev=1075953&view=rev
Log:
2011-03-01 Massimo Manghi <mx...@apache.org>
    * src/apache-1/mod_rivet.[c|h]: Add handling of AbortScript and AfterEveryScript configuration parameters
    * src/apache-1/rivetCode.c:	Add code for apache_log_error,apache_table, abort_code and abort_page 
    * src/apache-2/mod_rivet.[c|h]: Add handling of AbortScript and AfterEveryScript configuration parameters
    * src/apache-1/rivetCode.c:	New code for abort_page and add new command abort_code
    * configure.ac: module version bumped up to 2.0.3


Modified:
    tcl/rivet/branches/2.0/ChangeLog
    tcl/rivet/branches/2.0/Makefile.in
    tcl/rivet/branches/2.0/VERSION
    tcl/rivet/branches/2.0/configure.ac
    tcl/rivet/branches/2.0/src/apache-1/mod_rivet.c
    tcl/rivet/branches/2.0/src/apache-1/mod_rivet.h
    tcl/rivet/branches/2.0/src/apache-1/rivetCore.c
    tcl/rivet/branches/2.0/src/apache-2/mod_rivet.c
    tcl/rivet/branches/2.0/src/apache-2/mod_rivet.h
    tcl/rivet/branches/2.0/src/apache-2/rivetCore.c

Modified: tcl/rivet/branches/2.0/ChangeLog
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/ChangeLog?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/ChangeLog (original)
+++ tcl/rivet/branches/2.0/ChangeLog Tue Mar  1 18:05:20 2011
@@ -1,3 +1,10 @@
+2011-03-01 Massimo Manghi <mx...@apache.org>
+    * src/apache-1/mod_rivet.[c|h]: Add handling of AbortScript and AfterEveryScript configuration parameters
+    * src/apache-1/rivetCode.c:	Add code for apache_log_error,apache_table, abort_code and abort_page 
+    * src/apache-2/mod_rivet.[c|h]: Add handling of AbortScript and AfterEveryScript configuration parameters
+    * src/apache-1/rivetCode.c:	New code for abort_page and add new command abort_code
+    * configure.ac: module version bumped up to 2.0.3
+
 2010-10-20 Massimo Manghi <mx...@apache.org>
     * debian/[clean,install,docs,dirs]: removed because not needed or redundant
     * debian/copyright: completed to include also the Tcl license. Added copyright notes for stuff in win/

Modified: tcl/rivet/branches/2.0/Makefile.in
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/Makefile.in?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/Makefile.in (original)
+++ tcl/rivet/branches/2.0/Makefile.in Tue Mar  1 18:05:20 2011
@@ -18,7 +18,7 @@
 #
 # top-level Makefile.am for Apache Rivet: gets turned into a Makefile.in by automake
 #
-# $Id: Makefile.am 1024313 2010-10-19 16:29:56Z mxmanghi $
+# $Id: Makefile.am 1074761 2011-02-26 00:27:56Z mxmanghi $
 #
 # 2007/12/25: Added target uninistall-local that removes the tcl stuff (mxmanghi)
 # 2010/06/22: target instal-data-local searches for pkgIndex.tcl files and deletes them

Modified: tcl/rivet/branches/2.0/VERSION
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/VERSION?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/VERSION (original)
+++ tcl/rivet/branches/2.0/VERSION Tue Mar  1 18:05:20 2011
@@ -1 +1 @@
-2.0.2
+2.0.3

Modified: tcl/rivet/branches/2.0/configure.ac
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/configure.ac?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/configure.ac (original)
+++ tcl/rivet/branches/2.0/configure.ac Tue Mar  1 18:05:20 2011
@@ -22,7 +22,7 @@ dnl
 # so you can encode the package version directly into the source files.
 #-----------------------------------------------------------------------
 
-AC_INIT([Rivet],[2.0.2])
+AC_INIT([Rivet],[2.0.3])
 TEA_INIT([3.9])
 
 AC_CONFIG_AUX_DIR(tclconfig)

Modified: tcl/rivet/branches/2.0/src/apache-1/mod_rivet.c
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/src/apache-1/mod_rivet.c?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/src/apache-1/mod_rivet.c (original)
+++ tcl/rivet/branches/2.0/src/apache-1/mod_rivet.c Tue Mar  1 18:05:20 2011
@@ -134,9 +134,19 @@ Rivet_ExecuteAndCheck(Tcl_Interp *interp
 	    ap_assert (Tcl_ListObjIndex (interp, errorCodeListObj, 1, &errorCodeElementObj) == TCL_OK);
 
 	    errorCodeSubString = Tcl_GetString (errorCodeElementObj);
-	    if (strcmp (errorCodeSubString, "ABORTPAGE") == 0) {
-		goto good;
-	    }
+            if (strcmp (errorCodeSubString, "ABORTPAGE") == 0) 
+            {
+                if (conf->rivet_abort_script) 
+                {
+                    if (Tcl_EvalObjEx(interp,conf->rivet_abort_script,0) == TCL_ERROR)
+                    {
+                        CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
+                        TclWeb_PrintError("<b>Rivet ErrorScript failed!</b>",1,globals->req);
+                        TclWeb_PrintError( errorinfo, 0, globals->req );
+                    }
+                }
+                goto good;
+            }
 	}
 
 	Tcl_SetVar( interp, "errorOutbuf",
@@ -145,7 +155,7 @@ Rivet_ExecuteAndCheck(Tcl_Interp *interp
 
 	/* If we don't have an error script, use the default error handler. */
 	if (conf->rivet_error_script ) {
-	    errscript = Tcl_NewStringObj(conf->rivet_error_script, -1);
+	    errscript = conf->rivet_error_script;
 	} else {
 	    errscript = conf->rivet_default_error_script;
 	}
@@ -164,7 +174,16 @@ Rivet_ExecuteAndCheck(Tcl_Interp *interp
     }
 
     /* Make sure to flush the output if buffer_add was the only output */
-    good:
+good:
+
+    if (conf->after_every_script) {
+        if (Tcl_EvalObjEx(interp,conf->after_every_script,0) == TCL_ERROR)
+        {
+            CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
+            TclWeb_PrintError("<b>Rivet AfterEveryScript failed!</b>",1,globals->req);
+            TclWeb_PrintError( errorinfo, 0, globals->req );
+        }
+    }
 
     if (!globals->req->headers_set && (globals->req->charset != NULL)) {
 	char* ct_header = ap_pstrcat(globals->req->req->pool,"text/html;",globals->req->charset,NULL);
@@ -281,7 +300,7 @@ Rivet_ParseExecFile(TclWebRequest *req, 
 
 	if (toplevel) {
 	    if (rsc->rivet_before_script) {
-		Tcl_AppendObjToObj(outbuf, Tcl_NewStringObj(rsc->rivet_before_script, -1));
+		Tcl_AppendObjToObj(outbuf, rsc->rivet_before_script);
 	    }
 	}
 
@@ -303,8 +322,7 @@ Rivet_ParseExecFile(TclWebRequest *req, 
 	}
 	if (toplevel) {
 	    if (rsc->rivet_after_script) {
-		Tcl_AppendObjToObj(outbuf,
-				   Tcl_NewStringObj(rsc->rivet_after_script, -1));
+		Tcl_AppendObjToObj(outbuf,rsc->rivet_after_script);
 	    }
 	}
 
@@ -633,6 +651,14 @@ Rivet_SendContent(request_rec *r)
     retval = OK;
 sendcleanup:
     globals->req->content_sent = 0;
+
+    globals->page_aborting = 0;
+    if (globals->abort_code != NULL)
+    {
+        Tcl_DecrRefCount(globals->abort_code);
+        globals->abort_code = NULL;
+    }
+
     Tcl_MutexUnlock(&sendMutex);
     return retval;
 }
@@ -767,8 +793,15 @@ Rivet_PerInterpInit(server_rec *s, rivet
     globals = ap_pcalloc(p, sizeof(rivet_interp_globals));
     Tcl_SetAssocData(interp, "rivet", NULL, globals);
 
+    /* abort_page status variables in globals are set here and then 
+     * reset in Rivet_SendContent just before the request processing is 
+     * completed */
+
+    globals->page_aborting = 0;
+    globals->abort_code = NULL;
+
     /* Eval Rivet's init.tcl file to load in the Tcl-level
-    commands. */
+	commands. */
 
     /* We call Tcl_EvalFile on init.tcl. This call sets up
      * some variables and adds RIVETLIB_DESTDIR to auto_path.
@@ -954,6 +987,45 @@ Rivet_InitTclStuff(server_rec *s, pool *
     }
 }
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * Rivet_AssignStringtoConf --
+ *
+ *  Assign a string to a Tcl_Obj valued configuration parameter
+ *
+ * Arguments:
+ *
+ *  - objPnt: Pointer to a pointer to a Tcl_Obj. If the pointer *objPnt
+ *  is NULL (configuration script obj pointers are initialized to NULL)
+ *      a new Tcl_Obj is created
+ *  - string_value: a string to be assigned to the Tcl_Obj
+ *
+ * Results:
+ *  
+ *  - Pointer to a Tcl_Obj containing the parameter value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj* 
+Rivet_AssignStringToConf (Tcl_Obj** objPnt, const char* string_value)
+{
+    Tcl_Obj *objarg = NULL;
+    
+    if (*objPnt == NULL)
+    {
+        objarg = Tcl_NewStringObj(string_value,-1);
+        Tcl_IncrRefCount(objarg);
+        *objPnt = objarg;
+    } else {
+        objarg = *objPnt;
+        Tcl_AppendToObj(objarg, string_value, -1);
+    }
+    Tcl_AppendToObj( objarg, "\n", 1 );
+    return objarg;
+}
+
 
 /*
  *----------------------------------------------------------------------
@@ -980,44 +1052,21 @@ Rivet_SetScript( ap_pool *pool, rivet_se
     Tcl_Obj *objarg = NULL;
 
     if( STREQU( script, "GlobalInitScript" ) ) {
-	if( rsc->rivet_global_init_script == NULL ) {
-	    objarg = Tcl_NewStringObj( string, -1 );
-	    Tcl_IncrRefCount( objarg );
-	    Tcl_AppendToObj( objarg, "\n", 1 );
-	    rsc->rivet_global_init_script = objarg;
-	} else {
-	    objarg = rsc->rivet_global_init_script;
-	    Tcl_AppendToObj( objarg, string, -1 );
-	    Tcl_AppendToObj( objarg, "\n", 1 );
-	}
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_global_init_script),string);
     } else if( STREQU( script, "ChildInitScript" ) ) {
-	if( rsc->rivet_child_init_script == NULL ) {
-	    objarg = Tcl_NewStringObj( string, -1 );
-	    Tcl_IncrRefCount( objarg );
-	    Tcl_AppendToObj( objarg, "\n", 1 );
-	    rsc->rivet_child_init_script = objarg;
-	} else {
-	    objarg = rsc->rivet_child_init_script;
-	    Tcl_AppendToObj( objarg, string, -1 );
-	    Tcl_AppendToObj( objarg, "\n", 1 );
-	}
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_child_init_script),string);
     } else if( STREQU( script, "ChildExitScript" ) ) {
-	if( rsc->rivet_child_exit_script == NULL ) {
-	    objarg = Tcl_NewStringObj( string, -1 );
-	    Tcl_IncrRefCount( objarg );
-	    Tcl_AppendToObj( objarg, "\n", 1 );
-	    rsc->rivet_child_exit_script = objarg;
-	} else {
-	    objarg = rsc->rivet_child_exit_script;
-	    Tcl_AppendToObj( objarg, string, -1 );
-	    Tcl_AppendToObj( objarg, "\n", 1 );
-	}
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_child_exit_script),string);
     } else if( STREQU( script, "BeforeScript" ) ) {
-	rsc->rivet_before_script = ap_pstrcat(pool, string, "\n", NULL);
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_before_script),string);
     } else if( STREQU( script, "AfterScript" ) ) {
-	rsc->rivet_after_script = ap_pstrcat(pool, string, "\n", NULL);
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_after_script),string);
     } else if( STREQU( script, "ErrorScript" ) ) {
-	rsc->rivet_error_script = ap_pstrcat(pool, string, "\n", NULL);
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_error_script),string);
+    } else if( STREQU( script, "AbortScript" ) ) {
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_abort_script),string);
+    } else if( STREQU( script, "AfterEveryScript" ) ) {
+        objarg = Rivet_AssignStringToConf(&(rsc->after_every_script),string);
     }
 
     if( !objarg ) return string;
@@ -1151,6 +1200,10 @@ Rivet_MergeDirConfigVars( pool *p, rivet
 	add->rivet_after_script : base->rivet_after_script;
     new->rivet_error_script = add->rivet_error_script ?
 	add->rivet_error_script : base->rivet_error_script;
+    new->rivet_abort_script = add->rivet_abort_script ?
+        add->rivet_abort_script : base->rivet_abort_script;
+    new->after_every_script = add->after_every_script ?
+        add->after_every_script : base->after_every_script;
 
     new->user_scripts_updated = add->user_scripts_updated ?
 	add->user_scripts_updated : base->user_scripts_updated;
@@ -1227,6 +1280,8 @@ Rivet_CopyConfig( rivet_server_conf *old
     newrsc->rivet_before_script = oldrsc->rivet_before_script;
     newrsc->rivet_after_script = oldrsc->rivet_after_script;
     newrsc->rivet_error_script = oldrsc->rivet_error_script;
+    newrsc->rivet_abort_script = oldrsc->rivet_abort_script;
+    newrsc->after_every_script = oldrsc->after_every_script;
 
     newrsc->user_scripts_updated = oldrsc->user_scripts_updated;
 
@@ -1259,13 +1314,15 @@ Rivet_CreateConfig( pool *p, server_rec 
 
     FILEDEBUGINFO;
 
-    rsc->server_interp = NULL;
-    rsc->rivet_global_init_script = NULL;
-    rsc->rivet_child_init_script = NULL;
-    rsc->rivet_child_exit_script = NULL;
-    rsc->rivet_before_script = NULL;
-    rsc->rivet_after_script = NULL;
-    rsc->rivet_error_script = NULL;
+    rsc->server_interp		    = NULL;
+    rsc->rivet_global_init_script   = NULL;
+    rsc->rivet_child_init_script    = NULL;
+    rsc->rivet_child_exit_script    = NULL;
+    rsc->rivet_before_script	    = NULL;
+    rsc->rivet_after_script	    = NULL;
+    rsc->rivet_error_script	    = NULL;
+    rsc->rivet_abort_script         = NULL;
+    rsc->after_every_script         = NULL;
 
     rsc->user_scripts_updated = 0;
 
@@ -1374,6 +1431,12 @@ Rivet_MergeConfig(pool *p, void *basev, 
     rsc->rivet_error_script = overrides->rivet_error_script ?
 	overrides->rivet_error_script : base->rivet_error_script;
 
+    rsc->rivet_abort_script = overrides->rivet_abort_script ?
+	overrides->rivet_abort_script : base->rivet_abort_script;
+
+    rsc->after_every_script = overrides->after_every_script ?
+	overrides->after_every_script : base->after_every_script;
+
     rsc->rivet_default_error_script = overrides->rivet_default_error_script ?
 	overrides->rivet_default_error_script : base->rivet_default_error_script;
 

Modified: tcl/rivet/branches/2.0/src/apache-1/mod_rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/src/apache-1/mod_rivet.h?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/src/apache-1/mod_rivet.h (original)
+++ tcl/rivet/branches/2.0/src/apache-1/mod_rivet.h Tue Mar  1 18:05:20 2011
@@ -58,9 +58,11 @@ typedef struct {
     Tcl_Obj *rivet_global_init_script;   /* run once when apache is started */
     Tcl_Obj *rivet_child_init_script;
     Tcl_Obj *rivet_child_exit_script;
-    char *rivet_before_script;        /* script run before each page */
-    char *rivet_after_script;         /*            after            */
-    char *rivet_error_script;         /*            for errors */
+    Tcl_Obj *rivet_before_script;     /* script run before each page */
+    Tcl_Obj *rivet_after_script;      /*            after            */
+    Tcl_Obj *rivet_error_script;      /*            for errors */
+    Tcl_Obj *rivet_abort_script;      /* script run upon abort_page call  */
+    Tcl_Obj *after_every_script;      /* script to be run always	    */
 
     /* This flag is used with the above directives.  If any of them
        have changed, it gets set. */
@@ -90,8 +92,11 @@ typedef struct {
    'de-globalize' them */
 
 typedef struct {
-    request_rec *r;             /* request rec */
-    TclWebRequest *req;         /* TclWeb API request */
+    request_rec *r;         /* request rec */
+    TclWebRequest *req;     /* TclWeb API request */
+    int page_aborting;	    /* set by abort_page. */
+			    /* to be reset by Rivet_SendContent */
+    Tcl_Obj* abort_code;
 } rivet_interp_globals;
 
 int Rivet_ParseExecFile(TclWebRequest *req, char *filename, int toplevel);

Modified: tcl/rivet/branches/2.0/src/apache-1/rivetCore.c
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/src/apache-1/rivetCore.c?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/src/apache-1/rivetCore.c (original)
+++ tcl/rivet/branches/2.0/src/apache-1/rivetCore.c Tue Mar  1 18:05:20 2011
@@ -36,6 +36,8 @@
 
 #include <tcl.h>
 #include <string.h>
+#include <apr_tables.h>
+#include <apr_errno.h>
 
 #include "apache_request.h"
 #include "mod_rivet.h"
@@ -536,6 +538,257 @@ TCL_CMD_HEADER ( Rivet_Var )
 /*
 */
 
+static int append_key_callback (void *data, const char *key, const char *val)
+{
+    Tcl_Obj *list = data;
+
+    Tcl_ListObjAppendElement (NULL, list, Tcl_NewStringObj (key, -1));
+    return 1;
+}
+
+static int
+append_key_value_callback (void *data, const char *key, const char *val)
+{
+    Tcl_Obj *list = data;
+
+    Tcl_ListObjAppendElement (NULL, list, Tcl_NewStringObj (key, -1));
+    Tcl_ListObjAppendElement (NULL, list, Tcl_NewStringObj (val, -1));
+    return 1;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Rivet_ApacheTable --
+ *
+ * 	Deals with Rivet key-value tables in the request structure
+ *
+ *	apache_table get tablename key
+ *      apache_table set tablename key value
+ *      apache_table set tablename list
+ *      apache_table exists tablename key
+ *      apache_table unset tablename key
+ *      apache_table names tablename
+ *      apache_table array_get tablename
+ *      apache_table clear tablename
+ *
+ *      Table names can be "notes", "headers_in", "headers_out",
+ *      "err_headers_out", and "subprocess_env".
+ *
+ * Results:
+ *	A standard Tcl result.
+ *
+ * Side Effects:
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+TCL_CMD_HEADER( Rivet_ApacheTable )
+{
+    table *table = NULL;
+    int subcommandindex;
+
+    static CONST84 char *SubCommand[] = {
+	"get",
+	"set",
+	"exists",
+	"unset",
+	"names",
+	"array_get",
+	"clear",
+	NULL
+    };
+
+    enum subcommand {
+	SUB_GET,
+	SUB_SET,
+	SUB_EXISTS,
+	SUB_UNSET,
+	SUB_NAMES,
+	SUB_ARRAY_GET,
+	SUB_CLEAR
+    };
+
+    static CONST84 char *tableNames[] = {
+	"notes",
+	"headers_in",
+	"headers_out",
+	"err_headers_out",
+	"subprocess_env",
+	NULL
+    };
+
+    int tableindex;
+
+    enum tablename {
+	TABLE_NOTES,
+	TABLE_HEADERS_IN,
+	TABLE_HEADERS_OUT,
+	TABLE_ERR_HEADERS_OUT,
+	TABLE_SUBPROCESS_ENV
+    };
+
+    rivet_interp_globals *globals = Tcl_GetAssocData(interp, "rivet", NULL);
+
+    if ((objc < 3) || (objc > 5)) {
+	Tcl_WrongNumArgs(interp, 1, objv, "option tablename ?args?");
+	return TCL_ERROR;
+    }
+
+    if (Tcl_GetIndexFromObj(interp, objv[1], SubCommand,
+			"get|set|unset|list",
+			0, &subcommandindex) == TCL_ERROR) {
+	return TCL_ERROR;
+    }
+
+    if (Tcl_GetIndexFromObj (interp, objv[2], tableNames,
+			"notes|headers_in|headers_out|err_header_out|subprocess_env",
+			0, &tableindex) == TCL_ERROR) {
+	return TCL_ERROR;
+    }
+
+    switch ((enum tablename)tableindex)
+    {
+	case TABLE_NOTES: {
+	    table = globals->r->notes;
+	    break;
+	}
+
+	case TABLE_HEADERS_IN: {
+	    table = globals->r->headers_in;
+	    break;
+	}
+
+	case TABLE_HEADERS_OUT: {
+	    table = globals->r->headers_out;
+	    break;
+	}
+
+	case TABLE_ERR_HEADERS_OUT: {
+	    table = globals->r->err_headers_out;
+	    break;
+	}
+
+	case TABLE_SUBPROCESS_ENV: {
+	    table = globals->r->subprocess_env;
+	    break;
+	}
+    }
+
+    switch ((enum subcommand)subcommandindex)
+    {
+	case SUB_GET: {
+	    const char *key;
+	    const char *value;
+
+	    if (objc != 4) {
+		Tcl_WrongNumArgs(interp, 2, objv, "tablename key");
+		return TCL_ERROR;
+	    }
+
+	    key = Tcl_GetString (objv[3]);
+	    value = ap_table_get (table, key);
+
+	    if (value != NULL) {
+		Tcl_SetObjResult (interp, Tcl_NewStringObj (value, -1));
+	    }
+	    break;
+	}
+
+	case SUB_EXISTS: {
+	    const char *key;
+	    const char *value;
+
+	    if (objc != 4) {
+		Tcl_WrongNumArgs(interp, 2, objv, "tablename key");
+		return TCL_ERROR;
+	    }
+
+	    key = Tcl_GetString (objv[3]);
+	    value = ap_table_get (table, key);
+
+	    Tcl_SetObjResult (interp, Tcl_NewBooleanObj (value != NULL));
+	    break;
+	}
+
+
+	case SUB_SET: {
+	    int i;
+	    char *key;
+	    char *value;
+
+	    if (objc == 4) {
+		int listObjc;
+		Tcl_Obj **listObjv;
+
+		if (Tcl_ListObjGetElements (interp, objv[3], &listObjc, &listObjv) == TCL_ERROR) {
+		    return TCL_ERROR;
+		}
+
+		if (listObjc % 2 == 1) {
+		    Tcl_SetObjResult (interp, Tcl_NewStringObj ("list must have even number of elements", -1));
+		    return TCL_ERROR;
+		}
+
+		for (i = 0; i < listObjc; i += 2) {
+		    ap_table_set (table, Tcl_GetString (listObjv[i]), Tcl_GetString (listObjv[i+1]));
+		}
+
+		break;
+	    }
+
+	    if (objc != 5) {
+		Tcl_WrongNumArgs(interp, 2, objv, "tablename key value");
+		return TCL_ERROR;
+	    }
+
+	    key = Tcl_GetString (objv[3]);
+	    value = Tcl_GetString (objv[4]);
+
+	    ap_table_set (table, key, value);
+	    break;
+	}
+
+	case SUB_UNSET: {
+	    char *key;
+
+	    if (objc != 4) {
+		Tcl_WrongNumArgs(interp, 2, objv, "tablename key");
+		return TCL_ERROR;
+	    }
+
+	    key = Tcl_GetString (objv[3]);
+	    ap_table_unset (table, key);
+	    break;
+	}
+
+	case SUB_NAMES: {
+            Tcl_Obj *list = Tcl_NewObj ();
+
+	    ap_table_do(append_key_callback, (void*)list, table, NULL);
+
+	    Tcl_SetObjResult (interp, list);
+	    break;
+	}
+
+	case SUB_ARRAY_GET: {
+            Tcl_Obj *list = Tcl_NewObj ();
+
+	    ap_table_do(append_key_value_callback, (void*)list, table, NULL);
+
+	    Tcl_SetObjResult (interp, list);
+	    break;
+	}
+
+	case SUB_CLEAR: {
+	    ap_clear_table (table);
+	}
+    }
+
+    return TCL_OK;
+}
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -784,14 +1037,52 @@ TCL_CMD_HEADER( Rivet_NoBody )
 
 TCL_CMD_HEADER( Rivet_AbortPageCmd )
 {
+    rivet_interp_globals *globals = Tcl_GetAssocData( interp, "rivet", NULL );
     static char *errorMessage = "Page generation terminated by abort_page directive";
 
-    if (objc != 1)
+    if (objc > 2)
     {
-	Tcl_WrongNumArgs(interp, 1, objv, "");
-	return TCL_ERROR;
+        Tcl_WrongNumArgs(interp, 1, objv, "");
+        return TCL_ERROR;
     }
 
+    if (objc == 2)
+    {
+        char* cmd_arg = Tcl_GetStringFromObj(objv[1],NULL);
+        
+        if (strcmp(cmd_arg,"-aborting") == 0)
+        {
+            Tcl_SetObjResult (interp,Tcl_NewBooleanObj(globals->page_aborting));
+            return TCL_OK;
+        }
+ 
+    /* 
+     * we assume abort_code to be null, as abort_page shouldn't run twice while
+     * processing the same request 
+     */
+       
+        if (globals->abort_code == NULL)
+        {
+            globals->abort_code = objv[1];
+            Tcl_IncrRefCount(globals->abort_code);
+        }
+    }
+
+    /* 
+     * If page_aborting is true then this is the second call to abort_page
+     * processing the same request: we ignore it and return a normal
+     * completion code
+     */
+
+    if (globals->page_aborting)
+    {
+        return TCL_OK;
+    }
+
+    /* this is the first (and supposedly unique) abort_page call during this request */
+
+    globals->page_aborting = 1;
+
     Tcl_AddErrorInfo (interp, errorMessage);
     Tcl_SetErrorCode (interp, "RIVET", "ABORTPAGE", errorMessage, (char *)NULL);
     return TCL_ERROR;
@@ -799,6 +1090,28 @@ TCL_CMD_HEADER( Rivet_AbortPageCmd )
 
 /*
  *-----------------------------------------------------------------------------
+ * Rivet_AbortCodeCmd -- 
+ *
+ * Returns the abort code stored internally by passing a user defined parameter 
+ * to the command 'abort_page'.
+ *
+ *
+ *-----------------------------------------------------------------------------
+ */
+TCL_CMD_HEADER( Rivet_AbortCodeCmd )
+{
+    rivet_interp_globals *globals = Tcl_GetAssocData( interp, "rivet", NULL );
+    
+    if (globals->abort_code != NULL)
+    {
+        Tcl_SetObjResult(interp,globals->abort_code);
+    }
+
+    return TCL_OK;
+}
+
+/*
+ *-----------------------------------------------------------------------------
  *
  * Rivet_EnvCmd --
  *
@@ -868,6 +1181,116 @@ TCL_CMD_HEADER( Rivet_VirtualFilenameCmd
     return TCL_OK;
 }
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Rivet_LogError --
+ *
+ * 	Log an error from Rivet
+ *
+ *	log_error priority message
+ *
+ *        priority can be one of "emerg", "alert", "crit", "err",
+ *            "warning", "notice", "info", "debug"
+ *
+ * Results:
+ *      A message is logged to the Apache error log.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+TCL_CMD_HEADER( Rivet_LogErrorCmd )
+{
+    char *loglevel = NULL;
+    char *message = NULL;
+
+    server_rec *serverRec;
+
+    int loglevelindex;
+    int  apLogLevel = 0;
+
+    static CONST84 char *logLevel[] = {
+	"emerg",
+	"alert",
+	"crit",
+	"err",
+	"warning",
+	"notice",
+	"info",
+	"debug",
+	NULL
+    };
+
+    enum loglevel {
+	EMERG,
+	ALERT,
+	CRIT,
+	ERR,
+	WARNING,
+	NOTICE,
+	INFO,
+	DEBUG
+    };
+
+    rivet_interp_globals *globals = Tcl_GetAssocData(interp, "rivet", NULL);
+
+    if( objc != 3 ) {
+	Tcl_WrongNumArgs( interp, 1, objv, "loglevel message" );
+	return TCL_ERROR;
+    }
+
+    loglevel = Tcl_GetString(objv[1]);
+    message = Tcl_GetString (objv[2]);
+    if (Tcl_GetIndexFromObj(interp, objv[1], logLevel,
+			"emerg|alert|crit|err|warning|notice|info|debug",
+			0, &loglevelindex) == TCL_ERROR) {
+	return TCL_ERROR;
+    }
+
+    switch ((enum loglevel)loglevelindex)
+    {
+      case EMERG:
+        apLogLevel = APLOG_EMERG;
+	break;
+
+      case ALERT:
+        apLogLevel = APLOG_ALERT;
+        break;
+
+      case CRIT:
+        apLogLevel = APLOG_CRIT;
+        break;
+
+      case ERR:
+        apLogLevel = APLOG_ERR;
+        break;
+
+      case WARNING:
+        apLogLevel = APLOG_WARNING;
+        break;
+
+      case NOTICE:
+        apLogLevel = APLOG_NOTICE;
+        break;
+
+      case INFO:
+        apLogLevel = APLOG_INFO;
+        break;
+
+      case DEBUG:
+      default:
+        apLogLevel = APLOG_DEBUG;
+        break;
+    }
+
+    /* if we are serving a page, we know our server, 
+     * else send null for server
+     */
+    serverRec = (globals->r == NULL) ? NULL : globals->r->server;
+
+    ap_log_error (APLOG_MARK, apLogLevel, serverRec, "%s", message);
+    return TCL_OK;
+}
 #define TESTPANIC 0
 
 #ifdef TESTPANIC
@@ -993,13 +1416,23 @@ Rivet_InitCore( Tcl_Interp *interp )
 			 Rivet_EnvCmd,
 			 NULL,
 			 (Tcl_CmdDeleteProc *)NULL);
-
+    Tcl_CreateObjCommand(interp,
+			 "apache_log_error",
+			 Rivet_LogErrorCmd,
+			 NULL,
+			 (Tcl_CmdDeleteProc *)NULL);
+    Tcl_CreateObjCommand(interp,
+			 "apache_table",
+			 Rivet_ApacheTable,
+			 NULL,
+			 (Tcl_CmdDeleteProc *)NULL);
 #ifdef TESTPANIC
     Tcl_CreateCommand(interp, "testpanic", TestpanicCmd, (ClientData) 0,
             (Tcl_CmdDeleteProc *) NULL);
 #endif
 
     TCL_OBJ_CMD( "abort_page", Rivet_AbortPageCmd );
+    TCL_OBJ_CMD( "abort_code", Rivet_AbortCodeCmd );
     TCL_OBJ_CMD( "virtual_filename", Rivet_VirtualFilenameCmd );
 
 /*

Modified: tcl/rivet/branches/2.0/src/apache-2/mod_rivet.c
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/src/apache-2/mod_rivet.c?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/src/apache-2/mod_rivet.c (original)
+++ tcl/rivet/branches/2.0/src/apache-2/mod_rivet.c Tue Mar  1 18:05:20 2011
@@ -345,6 +345,15 @@ Rivet_ExecuteAndCheck(Tcl_Interp *interp
 
             errorCodeSubString = Tcl_GetString (errorCodeElementObj);
             if (strcmp (errorCodeSubString, "ABORTPAGE") == 0) {
+                if (conf->rivet_abort_script) 
+                {
+                    if (Tcl_EvalObjEx(interp,conf->rivet_abort_script,0) == TCL_ERROR)
+                    {
+                        CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
+                        TclWeb_PrintError("<b>Rivet ErrorScript failed!</b>",1,globals->req);
+                        TclWeb_PrintError( errorinfo, 0, globals->req );
+                    }
+                }
                 goto good;
             }
         }
@@ -355,7 +364,7 @@ Rivet_ExecuteAndCheck(Tcl_Interp *interp
 
         /* If we don't have an error script, use the default error handler. */
         if (conf->rivet_error_script ) {
-            errscript = Tcl_NewStringObj(conf->rivet_error_script, -1);
+            errscript = conf->rivet_error_script;
         } else {
             errscript = conf->rivet_default_error_script;
         }
@@ -376,6 +385,15 @@ Rivet_ExecuteAndCheck(Tcl_Interp *interp
     /* Make sure to flush the output if buffer_add was the only output */
 good:
 
+    if (conf->after_every_script) {
+        if (Tcl_EvalObjEx(interp,conf->after_every_script,0) == TCL_ERROR)
+        {
+            CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
+            TclWeb_PrintError("<b>Rivet AfterEveryScript failed!</b>",1,globals->req);
+            TclWeb_PrintError( errorinfo, 0, globals->req );
+        }
+    }
+
     if (!globals->req->headers_set && (globals->req->charset != NULL)) {
     	TclWeb_SetHeaderType (apr_pstrcat(globals->req->req->pool,"text/html;",globals->req->charset,NULL),globals->req);
     }
@@ -476,8 +494,7 @@ Rivet_ParseExecFile(TclWebRequest *req, 
 
         if (toplevel) {
             if (rsc->rivet_before_script) {
-                Tcl_AppendObjToObj(outbuf,
-                        Tcl_NewStringObj(rsc->rivet_before_script, -1));
+                Tcl_AppendObjToObj(outbuf,rsc->rivet_before_script);
             }
         }
 
@@ -504,7 +521,7 @@ Rivet_ParseExecFile(TclWebRequest *req, 
         }
         if (toplevel) {
             if (rsc->rivet_after_script) {
-                Tcl_AppendObjToObj(outbuf,Tcl_NewStringObj(rsc->rivet_after_script, -1));
+                Tcl_AppendObjToObj(outbuf,rsc->rivet_after_script);
             }
         }
 
@@ -623,10 +640,11 @@ Rivet_CopyConfig( rivet_server_conf *old
 
     newrsc->server_interp = oldrsc->server_interp;
     newrsc->rivet_global_init_script = oldrsc->rivet_global_init_script;
-
     newrsc->rivet_before_script = oldrsc->rivet_before_script;
     newrsc->rivet_after_script = oldrsc->rivet_after_script;
     newrsc->rivet_error_script = oldrsc->rivet_error_script;
+    newrsc->rivet_abort_script = oldrsc->rivet_abort_script;
+    newrsc->after_every_script = oldrsc->after_every_script;
 
     newrsc->user_scripts_updated = oldrsc->user_scripts_updated;
 
@@ -667,6 +685,10 @@ Rivet_MergeDirConfigVars(apr_pool_t *p, 
         add->rivet_after_script : base->rivet_after_script;
     new->rivet_error_script = add->rivet_error_script ?
         add->rivet_error_script : base->rivet_error_script;
+    new->rivet_abort_script = add->rivet_abort_script ?
+        add->rivet_abort_script : base->rivet_abort_script;
+    new->after_every_script = add->after_every_script ?
+        add->after_every_script : base->after_every_script;
 
     new->user_scripts_updated = add->user_scripts_updated ?
         add->user_scripts_updated : base->user_scripts_updated;
@@ -722,13 +744,15 @@ Rivet_CreateConfig(apr_pool_t *p, server
 
     FILEDEBUGINFO;
 
-    rsc->server_interp = NULL;
-    rsc->rivet_global_init_script = NULL;
-    rsc->rivet_child_init_script = NULL;
-    rsc->rivet_child_exit_script = NULL;
-    rsc->rivet_before_script = NULL;
-    rsc->rivet_after_script = NULL;
-    rsc->rivet_error_script = NULL;
+    rsc->server_interp		    = NULL;
+    rsc->rivet_global_init_script   = NULL;
+    rsc->rivet_child_init_script    = NULL;
+    rsc->rivet_child_exit_script    = NULL;
+    rsc->rivet_before_script	    = NULL;
+    rsc->rivet_after_script	    = NULL;
+    rsc->rivet_error_script	    = NULL;
+    rsc->rivet_abort_script         = NULL;
+    rsc->after_every_script         = NULL;
 
     rsc->user_scripts_updated = 0;
 
@@ -858,6 +882,13 @@ Rivet_PerInterpInit(server_rec *s, rivet
     globals = apr_pcalloc(p, sizeof(rivet_interp_globals));
     Tcl_SetAssocData(interp, "rivet", NULL, globals);
 
+    /* abort_page status variables in globals are set here and then 
+     * reset in Rivet_SendContent just before the request processing is 
+     * completed */
+
+    globals->page_aborting = 0;
+    globals->abort_code = NULL;
+
     /* Eval Rivet's init.tcl file to load in the Tcl-level
        commands. */
 
@@ -888,6 +919,45 @@ Rivet_PerInterpInit(server_rec *s, rivet
     Tcl_Release(interp);
 }
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * Rivet_AssignStringtoConf --
+ *
+ *  Assign a string to a Tcl_Obj valued configuration parameter
+ *
+ * Arguments:
+ *
+ *  - objPnt: Pointer to a pointer to a Tcl_Obj. If the pointer *objPnt
+ *  is NULL (configuration script obj pointers are initialized to NULL)
+ *      a new Tcl_Obj is created
+ *  - string_value: a string to be assigned to the Tcl_Obj
+ *
+ * Results:
+ *  
+ *  - Pointer to a Tcl_Obj containing the parameter value.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static Tcl_Obj* 
+Rivet_AssignStringToConf (Tcl_Obj** objPnt, const char* string_value)
+{
+    Tcl_Obj *objarg = NULL;
+    
+    if (*objPnt == NULL)
+    {
+        objarg = Tcl_NewStringObj(string_value,-1);
+        Tcl_IncrRefCount(objarg);
+        *objPnt = objarg;
+    } else {
+        objarg = *objPnt;
+        Tcl_AppendToObj(objarg, string_value, -1);
+    }
+    Tcl_AppendToObj( objarg, "\n", 1 );
+    return objarg;
+}
+
 
 /*
  *----------------------------------------------------------------------
@@ -915,46 +985,24 @@ Rivet_SetScript(apr_pool_t *pool, rivet_
     Tcl_Obj *objarg = NULL;
 
     if( STREQU( script, "GlobalInitScript" ) ) {
-        if( rsc->rivet_global_init_script == NULL ) {
-            objarg = Tcl_NewStringObj( string, -1 );
-            Tcl_IncrRefCount( objarg );
-            Tcl_AppendToObj( objarg, "\n", 1 );
-            rsc->rivet_global_init_script = objarg;
-        } else {
-            objarg = rsc->rivet_global_init_script;
-            Tcl_AppendToObj( objarg, string, -1 );
-            Tcl_AppendToObj( objarg, "\n", 1 );
-        }
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_global_init_script),string);
     } else if( STREQU( script, "ChildInitScript" ) ) {
-        if( rsc->rivet_child_init_script == NULL ) {
-            objarg = Tcl_NewStringObj( string, -1 );
-            Tcl_IncrRefCount( objarg );
-            Tcl_AppendToObj( objarg, "\n", 1 );
-            rsc->rivet_child_init_script = objarg;
-        } else {
-            objarg = rsc->rivet_child_init_script;
-            Tcl_AppendToObj( objarg, string, -1 );
-            Tcl_AppendToObj( objarg, "\n", 1 );
-        }
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_child_init_script),string);
     } else if( STREQU( script, "ChildExitScript" ) ) {
-        if( rsc->rivet_child_exit_script == NULL ) {
-            objarg = Tcl_NewStringObj( string, -1 );
-            Tcl_IncrRefCount( objarg );
-            Tcl_AppendToObj( objarg, "\n", 1 );
-            rsc->rivet_child_exit_script = objarg;
-        } else {
-            objarg = rsc->rivet_child_exit_script;
-            Tcl_AppendToObj( objarg, string, -1 );
-            Tcl_AppendToObj( objarg, "\n", 1 );
-        }
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_child_exit_script),string);
     } else if( STREQU( script, "BeforeScript" ) ) {
-        rsc->rivet_before_script = apr_pstrcat(pool, string, "\n", NULL);
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_before_script),string);
     } else if( STREQU( script, "AfterScript" ) ) {
-        rsc->rivet_after_script = apr_pstrcat(pool, string, "\n", NULL);
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_after_script),string);
     } else if( STREQU( script, "ErrorScript" ) ) {
-        rsc->rivet_error_script = apr_pstrcat(pool, string, "\n", NULL);
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_error_script),string);
+    } else if( STREQU( script, "AbortScript" ) ) {
+        objarg = Rivet_AssignStringToConf(&(rsc->rivet_abort_script),string);
+    } else if( STREQU( script, "AfterEveryScript" ) ) {
+        objarg = Rivet_AssignStringToConf(&(rsc->after_every_script),string);
     }
 
+
     if( !objarg ) return string;
 
     return Tcl_GetStringFromObj( objarg, NULL );
@@ -1173,6 +1221,12 @@ Rivet_MergeConfig(apr_pool_t *p, void *b
     rsc->rivet_default_error_script = overrides->rivet_default_error_script ?
         overrides->rivet_default_error_script : base->rivet_default_error_script;
 
+    rsc->rivet_abort_script = overrides->rivet_abort_script ?
+        overrides->rivet_abort_script : base->rivet_abort_script;
+
+    rsc->after_every_script = overrides->after_every_script ?
+        overrides->after_every_script : base->after_every_script;
+
     /* cache_size is global, and set up later. */
     /* cache_free is not set up at this point. */
 
@@ -1719,6 +1773,15 @@ Rivet_SendContent(request_rec *r)
     retval = OK;
 sendcleanup:
     globals->req->content_sent = 0;
+
+    /* page_aborting and abort_code are reset at every request */
+
+    globals->page_aborting = 0;
+    if (globals->abort_code != NULL)
+    {
+        Tcl_DecrRefCount(globals->abort_code);
+        globals->abort_code = NULL;
+    }
     Tcl_MutexUnlock(&sendMutex);
     return retval;
 }

Modified: tcl/rivet/branches/2.0/src/apache-2/mod_rivet.h
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/src/apache-2/mod_rivet.h?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/src/apache-2/mod_rivet.h (original)
+++ tcl/rivet/branches/2.0/src/apache-2/mod_rivet.h Tue Mar  1 18:05:20 2011
@@ -55,9 +55,11 @@ typedef struct _rivet_server_conf {
     Tcl_Obj *rivet_global_init_script;	/* run once when apache is started */
     Tcl_Obj *rivet_child_init_script;
     Tcl_Obj *rivet_child_exit_script;
-    char *rivet_before_script;		/* script run before each page	*/
-    char *rivet_after_script;		/*            after		*/
-    char *rivet_error_script;		/*            for errors	*/
+    Tcl_Obj *rivet_before_script;	/* script run before each page	*/
+    Tcl_Obj *rivet_after_script;	/*            after		*/
+    Tcl_Obj *rivet_error_script;	/*            for errors	*/
+    Tcl_Obj *rivet_abort_script;	/* script run upon abort_page call  */
+    Tcl_Obj *after_every_script;	/* script to be run always	    */
 
     /* This flag is used with the above directives.  If any of them
        have changed, it gets set. */
@@ -85,8 +87,11 @@ typedef struct _rivet_server_conf {
    'de-globalize' them */
 
 typedef struct _rivet_interp_globals {
-    request_rec *r;			    /* request rec */
-    TclWebRequest *req;			    /* TclWeb API request */
+    request_rec	    *r;		    /* request rec */
+    TclWebRequest   *req;	    /* TclWeb API request */
+    int             page_aborting;  /* set by abort_page. */
+				    /* to be reset by Rivet_SendContent */
+    Tcl_Obj*        abort_code;
 } rivet_interp_globals;
 
 int Rivet_ParseExecFile(TclWebRequest *req, char *filename, int toplevel);

Modified: tcl/rivet/branches/2.0/src/apache-2/rivetCore.c
URL: http://svn.apache.org/viewvc/tcl/rivet/branches/2.0/src/apache-2/rivetCore.c?rev=1075953&r1=1075952&r2=1075953&view=diff
==============================================================================
--- tcl/rivet/branches/2.0/src/apache-2/rivetCore.c (original)
+++ tcl/rivet/branches/2.0/src/apache-2/rivetCore.c Tue Mar  1 18:05:20 2011
@@ -1043,14 +1043,52 @@ TCL_CMD_HEADER( Rivet_NoBody )
 
 TCL_CMD_HEADER( Rivet_AbortPageCmd )
 {
+    rivet_interp_globals *globals = Tcl_GetAssocData( interp, "rivet", NULL );
     static char *errorMessage = "Page generation terminated by abort_page directive";
 
-    if (objc != 1)
+    if (objc > 2)
     {
-	Tcl_WrongNumArgs(interp, 1, objv, "");
-	return TCL_ERROR;
+        Tcl_WrongNumArgs(interp, 1, objv, "");
+        return TCL_ERROR;
+    }
+
+    if (objc == 2)
+    {
+        char* cmd_arg = Tcl_GetStringFromObj(objv[1],NULL);
+        
+        if (strcmp(cmd_arg,"-aborting") == 0)
+        {
+            Tcl_SetObjResult (interp,Tcl_NewBooleanObj(globals->page_aborting));
+            return TCL_OK;
+        }
+ 
+    /* 
+     * we assume abort_code to be null, as abort_page shouldn't run twice while
+     * processing the same request 
+     */
+       
+        if (globals->abort_code == NULL)
+        {
+            globals->abort_code = objv[1];
+            Tcl_IncrRefCount(globals->abort_code);
+        }
+    }
+
+    /* 
+     * If page_aborting is true then this is the second call to abort_page
+     * processing the same request: we ignore it and return a normal
+     * completion code
+     */
+
+    if (globals->page_aborting)
+    {
+        return TCL_OK;
     }
 
+    /* this is the first (and supposedly unique) abort_page call during this request */
+
+    globals->page_aborting = 1;
+
     Tcl_AddErrorInfo (interp, errorMessage);
     Tcl_SetErrorCode (interp, "RIVET", "ABORTPAGE", errorMessage, (char *)NULL);
     return TCL_ERROR;
@@ -1058,6 +1096,28 @@ TCL_CMD_HEADER( Rivet_AbortPageCmd )
 
 /*
  *-----------------------------------------------------------------------------
+ * Rivet_AbortCodeCmd -- 
+ *
+ * Returns the abort code stored internally by passing a user defined parameter 
+ * to the command 'abort_page'.
+ *
+ *
+ *-----------------------------------------------------------------------------
+ */
+TCL_CMD_HEADER( Rivet_AbortCodeCmd )
+{
+    rivet_interp_globals *globals = Tcl_GetAssocData( interp, "rivet", NULL );
+    
+    if (globals->abort_code != NULL)
+    {
+        Tcl_SetObjResult(interp,globals->abort_code);
+    }
+
+    return TCL_OK;
+}
+
+/*
+ *-----------------------------------------------------------------------------
  *
  * Rivet_EnvCmd --
  *
@@ -1393,6 +1453,7 @@ Rivet_InitCore( Tcl_Interp *interp )
 #endif
 
     TCL_OBJ_CMD( "abort_page", Rivet_AbortPageCmd );
+    TCL_OBJ_CMD( "abort_code", Rivet_AbortCodeCmd );
     TCL_OBJ_CMD( "virtual_filename", Rivet_VirtualFilenameCmd );
 
     return TCL_OK;



---------------------------------------------------------------------
To unsubscribe, e-mail: rivet-cvs-unsubscribe@tcl.apache.org
For additional commands, e-mail: rivet-cvs-help@tcl.apache.org