blob: 7b62d7363d09f1b72a35d28ca94dc4bc0fe2c13e [file] [log] [blame]
/* $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;
Tcl_DString dstr;
Tcl_DString convdstr;
Tcl_DStringInit(&dstr);
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_DStringAppend(&dstr, "\"\n", 2);
inside = 1;
p = 0;
continue;
} else {
ungetc(nextchar, openfile);
}
}
#endif
if (c == strstart[p])
{
if ((++p) == startseqlen)
{
Tcl_DStringAppend(&dstr, "\"\n", 2);
inside = 1;
p = 0;
continue;
}
} else {
if (p > 0)
Tcl_DStringAppend(&dstr, (char *)strstart, p);
/* or else just put the char in outbuf */
switch (c)
{
case '{':
Tcl_DStringAppend(&dstr, "\\{", -1);
break;
case '}':
Tcl_DStringAppend(&dstr, "\\}", -1);
break;
case '$':
Tcl_DStringAppend(&dstr, "\\$", -1);
break;
case '[':
Tcl_DStringAppend(&dstr, "\\[", -1);
break;
case ']':
Tcl_DStringAppend(&dstr, "\\]", -1);
break;
case '"':
Tcl_DStringAppend(&dstr, "\\\"", -1);
break;
case '\\':
Tcl_DStringAppend(&dstr, "\\\\", -1);
break;
default:
Tcl_DStringAppend(&dstr, &c, 1);
break;
}
p = 0;
continue;
}
} else {
/* INSIDE */
#if USE_OLD_TAGS == 1
if (c == '+')
{
int nextchar = getc(openfile);
if (nextchar == '>')
{
Tcl_DStringAppend(&dstr, "\n hputs \"", -1);
inside = 0;
p = 0;
continue;
} else {
ungetc(nextchar, openfile);
}
}
#endif
if (c == strend[p])
{
if ((++p) == endseqlen)
{
Tcl_DStringAppend(&dstr, "\n hputs \"", -1);
inside = 0;
p = 0;
continue;
}
}
else
{
/* plop stuff into outbuf, which we will then eval */
if (p > 0)
Tcl_DStringAppend(&dstr, (char *)strend, p);
Tcl_DStringAppend(&dstr, &c, 1);
p = 0;
}
}
}
Tcl_ExternalToUtfDString(NULL,
Tcl_DStringValue(&dstr),
Tcl_DStringLength(&dstr),
&convdstr);
Tcl_AppendToObj(outbuf, Tcl_DStringValue(&convdstr),
Tcl_DStringLength(&convdstr));
Tcl_DStringFree(&dstr);
Tcl_DStringFree(&convdstr);
return inside;
}