Split out parser into its own file.
Added configuration option for seperate interpreters for virtual hosts.
PR:
Obtained from:
Submitted by:
Reviewed by:

diff --git a/Makefile b/Makefile
index ee24c8f..523a23d 100644
--- a/Makefile
+++ b/Makefile
@@ -14,7 +14,7 @@
 SHLIB=mod_dtcl$(TCL_SHLIB_SUFFIX)
 
 APREQ_OBJECTS=apache_cookie.o apache_multipart_buffer.o apache_request.o
-OBJECTS=mod_dtcl.o tcl_commands.o $(APREQ_OBJECTS)
+OBJECTS=mod_dtcl.o tcl_commands.o parser.o $(APREQ_OBJECTS)
 
 # The following TCL_* variables are all exported from builddtcl.sh
 
@@ -37,10 +37,12 @@
 	$(COMPILE)
 apache_request.o: apache_request.c apache_request.h
 	$(COMPILE)
-mod_dtcl.o: mod_dtcl.c mod_dtcl.h tcl_commands.h apache_request.h
+mod_dtcl.o: mod_dtcl.c mod_dtcl.h tcl_commands.h apache_request.h parser.h
 	$(COMPILE) -DDTCL_VERSION=`cat VERSION`
 tcl_commands.o: tcl_commands.c tcl_commands.h mod_dtcl.h
 	$(COMPILE)
+parser.o: parser.c mod_dtcl.h parser.h
+	$(COMPILE)
 
 clean: 
 	-rm -f $(STATICLIB) $(SHLIB) *.o *~ docs/documentation.txt
diff --git a/docs/directives.html b/docs/directives.html
index da1ba5a..efbde26 100644
--- a/docs/directives.html
+++ b/docs/directives.html
@@ -56,12 +56,16 @@
 	MaxRequestsPerChild is 0.
       </li>
 
+      <li>
+	<code><b>Dtcl_UploadFilesToVar <i>on/off</i></b></code><br> If
+	on, files will be uploaded to the variable UPLOAD(data).  Be
+	careful with this, as large files could use up your memory.
+      </li>
 
       <li>
-	<code><b>Dtcl_UploadFilesToVar <i>1/0</i></b></code><br> 
-	If set to 1, files will be uploaded to the variable
-	UPLOAD(data).  Be careful with this, as large files could
-	use up your memory.
+	<code><b>Dtcl_SeperateVirtualInterps
+	<i>on/off</i></b></code><br> If on, each VirtualHost will have
+	its own Tcl interpreter.
       </li>
 
     </ul>
diff --git a/mod_dtcl.c b/mod_dtcl.c
index 1088983..5d7955f 100644
--- a/mod_dtcl.c
+++ b/mod_dtcl.c
@@ -76,6 +76,7 @@
 #include <string.h>
 
 #include "tcl_commands.h"
+#include "parser.h"
 #include "apache_request.h"
 #include "mod_dtcl.h"
 
@@ -368,14 +369,8 @@
 static int get_ttml_file(request_rec *r, dtcl_server_conf *dsc, Tcl_Interp *interp, char *filename, int toplevel, Tcl_Obj *outbuf)
 {
     /* BEGIN PARSER  */
-    char inside = 0;	/* are we inside the starting/ending delimiters  */
+    int inside = 0;	/* are we inside the starting/ending delimiters  */
 
-    const char *strstart = STARTING_SEQUENCE;
-    const char *strend = ENDING_SEQUENCE;
-
-    char c;
-    int ch;
-    int endseqlen = strlen(ENDING_SEQUENCE), startseqlen = strlen(STARTING_SEQUENCE), p = 0;
 
     FILE *f = NULL;
 
@@ -386,7 +381,6 @@
 	return HTTP_FORBIDDEN;
     }
 
-    /* Beginning of the file parser */
     if (toplevel)
     {
 	Tcl_SetStringObj(outbuf, "namespace eval request {\n", -1);
@@ -397,109 +391,22 @@
     else
 	Tcl_SetStringObj(outbuf, "hputs \"\n", -1);
 
-    while ((ch = getc(f)) != EOF)
+    /* if inside < 0, it's an error  */
+    inside = dtcl_parser(outbuf, f);
+    if (inside < 0)
     {
-	if (ch == -1)
-	    if (ferror(f))
-	    {
-		ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
-			     "Encountered error in mod_dtcl getchar routine while reading %s",
-			     r->uri);
-		ap_pfclose( r->pool, f);
-	    }
-	c = ch;
-	if (!inside)
+	if (ferror(f))
 	{
-	    /* OUTSIDE  */
-
-#if USE_OLD_TAGS == 1
-	    if (c == '<')
-	    {
-		int nextchar = getc(f);
-		if (nextchar == '+')
-		{
-		    Tcl_AppendToObj(outbuf, "\"\n", 2);
-		    inside = 1;
-		    p = 0;
-		    continue;
-		} else {
-		    ungetc(nextchar, f);
-		}
-	    }
-#endif
-
-	    if (c == strstart[p])
-	    {
-		if ((++p) == endseqlen)
-		{
-		    /* ok, we have matched the whole ending sequence - do something  */
-		    Tcl_AppendToObj(outbuf, "\"\n", 2);
-		    inside = 1;
-		    p = 0;
-		    continue;
-		}
-	    } else {
-		if (p > 0)
-		    Tcl_AppendToObj(outbuf, (char *)strstart, p);
-		/* or else just put the char in outbuf  */
-		if (c == '$')
-		    Tcl_AppendToObj(outbuf, "\\$", -1);
-		else if ( c == '[')
-		    Tcl_AppendToObj(outbuf, "\\[", -1);
-		else if ( c == ']')
-		    Tcl_AppendToObj(outbuf, "\\]", -1);
-		else if ( c == '"')
-		    Tcl_AppendToObj(outbuf, "\\\"", -1);
-		else if ( c == '\\')
-		    Tcl_AppendToObj(outbuf, "\\\\", -1);
-		else
-		    Tcl_AppendToObj(outbuf, &c, 1);
-
-		p = 0;
-		continue;
-	    }
-	} else {
-	    /* INSIDE  */
-
-#if USE_OLD_TAGS == 1
-	    if (c == '+')
-	    {
-		int nextchar = getc(f);
-		if (nextchar == '>')
-		{
-		    Tcl_AppendToObj(outbuf, "\n hputs \"", -1);
-		    inside = 0;
-		    p = 0;
-		    continue;
-		} else {
-		    ungetc(nextchar, f);
-		}
-	    }
-#endif
-
-	    if (c == strend[p])
-	    {
-		if ((++p) == startseqlen)
-		{
-		    Tcl_AppendToObj(outbuf, "\n hputs \"", -1);
-		    inside = 0;
-		    p = 0;
-		    continue;
-		}
-	    }
-	    else
-	    {
-		/*  plop stuff into outbuf, which we will then eval   */
-		if (p > 0)
-		    Tcl_AppendToObj(outbuf, (char *)strend, p);
-		Tcl_AppendToObj(outbuf, &c, 1);
-		p = 0;
-	    }
+	    ap_log_error(APLOG_MARK, APLOG_ERR, r->server,
+			 "Encountered error in mod_dtcl getchar routine while reading %s",
+			 r->uri);
+	    ap_pfclose( r->pool, f);
 	}
     }
+
     ap_pfclose(r->pool, f);
 
-    if (!inside)
+    if (inside == 0)
     {
 	Tcl_AppendToObj(outbuf, "\"\n", 2);
     }
@@ -892,7 +799,8 @@
 	    mydsc = ap_pcalloc(p, sizeof(dtcl_server_conf));	    
 	    ap_set_module_config(sr->module_config, &dtcl_module, mydsc);
 	    copy_dtcl_config(p, dsc, mydsc);
-	    mydsc->server_interp = NULL;
+	    if (dsc->seperate_virtual_interps != 0)
+		mydsc->server_interp = NULL;
 	} else {
 	    mydsc = (dtcl_server_conf *) ap_get_module_config(sr->module_config, &dtcl_module);
 	}
@@ -975,18 +883,34 @@
     dsc->upload_dir = arg;
     return NULL;
 }
-const char *set_uploadmax(cmd_parms *cmd, void *dummy, char *arg)
+
+static const char *set_uploadmax(cmd_parms *cmd, void *dummy, char *arg)
 {
     server_rec *s = cmd->server;
     dtcl_server_conf *dsc = (dtcl_server_conf *)ap_get_module_config(s->module_config, &dtcl_module);
     dsc->upload_max = strtol(arg, NULL, 10);
     return NULL;
 }
-const char *set_filestovar(cmd_parms *cmd, void *dummy, char *arg)
+
+static const char *set_filestovar(cmd_parms *cmd, void *dummy, char *arg)
 {
     server_rec *s = cmd->server;
     dtcl_server_conf *dsc = (dtcl_server_conf *)ap_get_module_config(s->module_config, &dtcl_module);
-    dsc->upload_files_to_var = strtol(arg, NULL, 10);
+    if (!strcmp(arg, "on"))
+	dsc->upload_files_to_var = 1;
+    else
+	dsc->upload_files_to_var = 0;
+    return NULL;
+}
+
+static const char *set_seperatevirtinterps(cmd_parms *cmd, void *dummy, char *arg)
+{
+    server_rec *s = cmd->server;
+    dtcl_server_conf *dsc = (dtcl_server_conf *)ap_get_module_config(s->module_config, &dtcl_module);
+    if (!strcmp(arg, "on"))
+	dsc->seperate_virtual_interps = 1;
+    else 
+	dsc->seperate_virtual_interps = 0;
     return NULL;
 }
 
@@ -1033,6 +957,7 @@
     newdsc->cache_free = olddsc->cache_free;
     newdsc->upload_max = olddsc->upload_max;
     newdsc->upload_files_to_var = olddsc->upload_files_to_var;
+    newdsc->seperate_virtual_interps = olddsc->seperate_virtual_interps;
     newdsc->server_name = olddsc->server_name;
     newdsc->upload_dir = olddsc->upload_dir;
     newdsc->objCacheList = olddsc->objCacheList;
@@ -1069,6 +994,7 @@
     *(dsc->cache_free) = 0;
     dsc->upload_max = 0;
     dsc->upload_files_to_var = 0;
+    dsc->seperate_virtual_interps = 0;
     dsc->server_name = NULL;
     dsc->upload_dir = "/tmp";
     dsc->objCacheList = NULL;
@@ -1099,6 +1025,7 @@
     dtcl_server_conf *base = (dtcl_server_conf *) basev;
     dtcl_server_conf *overrides = (dtcl_server_conf *) overridesv;
 
+    fprintf(stderr, __FUNCTION__ "\n");
     dsc->server_interp = overrides->server_interp ? overrides->server_interp : base->server_interp;
 
 #if 0 /* this stuff should only be done once at the top level  */
@@ -1119,7 +1046,6 @@
 /*     dsc->cache_size = overrides->cache_size ? overrides->cache_size : base->cache_size;
     dsc->cache_free = overrides->cache_free ? overrides->cache_free : base->cache_free;  */
     dsc->upload_max = overrides->upload_max ? overrides->upload_max : base->upload_max;
-/*     dsc->upload_files_to_var = overrides->upload_files_to_var ? overrides->upload_files_to_var : base->upload_files_to_var;  */
 
     dsc->server_name = overrides->server_name ? overrides->server_name : base->server_name;
     dsc->upload_dir = overrides->upload_dir ? overrides->upload_dir : base->upload_dir;
@@ -1171,7 +1097,8 @@
     {"Dtcl_CacheSize", set_cachesize, NULL, RSRC_CONF, TAKE1, "Dtcl_Cachesize cachesize"},
     {"Dtcl_UploadDirectory", set_uploaddir, NULL, RSRC_CONF, TAKE1, "Dtcl_UploadDirectory dirname"},
     {"Dtcl_UploadMaxSize", set_uploadmax, NULL, RSRC_CONF, TAKE1, "Dtcl_UploadMaxSize size"},
-    {"Dtcl_UploadFilesToVar", set_filestovar, NULL, RSRC_CONF, TAKE1, "Dtcl_UploadFilesToVar 1/0"},
+    {"Dtcl_UploadFilesToVar", set_filestovar, NULL, RSRC_CONF, TAKE1, "Dtcl_UploadFilesToVar on/off"},
+    {"Dtcl_SeperateVirtualInterps", set_seperatevirtinterps, NULL, RSRC_CONF, TAKE1, "Dtcl_SeperateVirtualInterps on/off"},
     {NULL}
 };
 
diff --git a/mod_dtcl.h b/mod_dtcl.h
index c218142..d0edc33 100644
--- a/mod_dtcl.h
+++ b/mod_dtcl.h
@@ -70,6 +70,7 @@
     int *cache_free;
     int upload_max;
     int upload_files_to_var;
+    int seperate_virtual_interps;
     char *server_name;
     char *upload_dir;
 
diff --git a/parser.c b/parser.c
new file mode 100644
index 0000000..afccfd2
--- /dev/null
+++ b/parser.c
@@ -0,0 +1,131 @@
+/* $Id$
+
+   Dtcl parser - doesn't really need any of the includes besides
+   tcl.h.
+  */
+#include <tcl.h>
+#include "httpd.h"
+#include "apache_request.h"
+#include "mod_dtcl.h"
+
+/* 
+   accepts an 'outbuf' to be filled, and an open file descritptor
+
+   returns 'inside', letting the caller know whether the parser was
+   inside a block of Tcl or not when it stopped.
+  */
+
+int dtcl_parser(Tcl_Obj *outbuf, FILE *openfile)
+{
+    const char *strstart = STARTING_SEQUENCE;
+    const char *strend = ENDING_SEQUENCE;
+
+    char c;
+    int ch;
+    int endseqlen = strlen(ENDING_SEQUENCE), startseqlen = strlen(STARTING_SEQUENCE), p = 0;
+    int inside = 0;
+
+    while ((ch = getc(openfile)) != EOF)
+    {
+	if (ch == -1)
+	    return -1;
+	c = ch;
+	if (!inside)
+	{
+	    /* OUTSIDE  */
+
+#if USE_OLD_TAGS == 1
+	    if (c == '<')
+	    {
+		int nextchar = getc(openfile);
+		if (nextchar == '+')
+		{
+		    Tcl_AppendToObj(outbuf, "\"\n", 2);
+		    inside = 1;
+		    p = 0;
+		    continue;
+		} else {
+		    ungetc(nextchar, openfile);
+		}
+	    }
+#endif
+
+	    if (c == strstart[p])
+	    {
+		if ((++p) == endseqlen)
+		{
+		    /* ok, we have matched the whole ending sequence - do something  */
+		    Tcl_AppendToObj(outbuf, "\"\n", 2);
+		    inside = 1;
+		    p = 0;
+		    continue;
+		}
+	    } else {
+		if (p > 0)
+		    Tcl_AppendToObj(outbuf, (char *)strstart, p);
+		/* or else just put the char in outbuf  */
+		switch (c)
+		{
+		case '$':
+		    Tcl_AppendToObj(outbuf, "\\$", -1);
+		    break;
+		case '[':
+		    Tcl_AppendToObj(outbuf, "\\[", -1);
+		    break;
+		case ']':
+		    Tcl_AppendToObj(outbuf, "\\]", -1);
+		    break;
+		case '"':
+		    Tcl_AppendToObj(outbuf, "\\\"", -1);
+		    break;
+		case '\\':
+		    Tcl_AppendToObj(outbuf, "\\\\", -1);
+		    break;
+		default:
+		    Tcl_AppendToObj(outbuf, &c, 1);
+		    break;
+		}
+		p = 0;
+		continue;
+	    }
+	} else {
+	    /* INSIDE  */
+
+#if USE_OLD_TAGS == 1
+	    if (c == '+')
+	    {
+		int nextchar = getc(openfile);
+		if (nextchar == '>')
+		{
+		    Tcl_AppendToObj(outbuf, "\n hputs \"", -1);
+		    inside = 0;
+		    p = 0;
+		    continue;
+		} else {
+		    ungetc(nextchar, openfile);
+		}
+	    }
+#endif
+
+	    if (c == strend[p])
+	    {
+		if ((++p) == startseqlen)
+		{
+		    Tcl_AppendToObj(outbuf, "\n hputs \"", -1);
+		    inside = 0;
+		    p = 0;
+		    continue;
+		}
+	    }
+	    else
+	    {
+		/*  plop stuff into outbuf, which we will then eval   */
+		if (p > 0)
+		    Tcl_AppendToObj(outbuf, (char *)strend, p);
+		Tcl_AppendToObj(outbuf, &c, 1);
+		p = 0;
+	    }
+	}
+    }
+    return inside;
+}
diff --git a/parser.h b/parser.h
new file mode 100644
index 0000000..582ccc2
--- /dev/null
+++ b/parser.h
@@ -0,0 +1 @@
+int dtcl_parser(Tcl_Obj *outbuf, FILE *openfile);