2001-05-19
2001-05-19 05:34:27 by Martin Stjernholm <mast@lysator.liu.se>
-
d52f8f0802db1a784de750d21272d688a92bfb8e
(732 lines)
(+339/-393)
[
Show
| Annotate
]
Branch: 5.2
Cleaned up _eval a bit to make it somewhat easier to grasp. Fixed bug
in Context.current_scope. Improved the debug messages somewhat.
Rev: server/etc/modules/RXML.pmod/module.pmod:1.159
1:
- // $Id: module.pmod,v 1.158 2001/05/18 19:49:27 mast Exp $
+ // $Id: module.pmod,v 1.159 2001/05/19 05:34:27 mast Exp $
// Kludge: Must use "RXML.refs" somewhere for the whole module to be
// loaded correctly.
120:
# define PROFILE_SWITCH(ctx, from, to) do ; while (0)
#endif
+ #ifdef RXML_VERBOSE
+ # define TAG_DEBUG_TEST(flags) 1
+ #elif defined (DEBUG)
+ # define TAG_DEBUG_TEST(flags) ((flags) & FLAG_DEBUG)
+ #else
+ # define TAG_DEBUG_TEST(flags) 0
+ #endif
+
#ifdef DEBUG
# define TAG_DEBUG(frame, msg, args...) \
- (frame)->tag_debug ("%O: " + (msg), (frame), args)
+ (TAG_DEBUG_TEST(frame->flags) && report_debug ("%O: " + (msg), (frame), args), 0)
# define DO_IF_DEBUG(code...) code
#else
# define TAG_DEBUG(frame, msg, args...) 0
# define DO_IF_DEBUG(code...)
#endif
-
+ #ifdef MODULE_DEBUG
+ # define DO_IF_MODULE_DEBUG(code...) code
+ #else
+ # define DO_IF_MODULE_DEBUG(code...)
+ #endif
+
#define HASH_INT2(m, n) (n < 65536 ? (m << 16) + n : sprintf ("%x,%x", m, n))
// Use defines since typedefs doesn't work in soft casts yet.
315:
#define EVAL_FRAME(frame, ctx, parser, type, args, content, result) \
eval_frame: do { \
mixed err = catch { \
- result = frame->_eval (parser, type, args, content); \
+ result = frame->_eval (ctx, parser, type, args, content); \
break eval_frame; \
}; \
\
324:
if (!ustate) ustate = ctx->unwind_state = ([]); \
DO_IF_DEBUG ( \
if (err != frame) \
- fatal_error ("Internal error: " \
- "Unexpected unwind object catched.\n"); \
+ fatal_error ("Unexpected unwind object catched.\n"); \
if (ustate[parser]) \
- fatal_error ("Internal error: " \
- "Clobbering unwind state for parser.\n"); \
+ fatal_error ("Clobbering unwind state for parser.\n"); \
); \
ustate[parser] = ({err}); \
throw (err = parser); \
1186: Inside #if defined(MODULE_DEBUG)
{
#ifdef MODULE_DEBUG
if (arrayp (var) ? !sizeof (var) : !stringp (var))
- error ("Invalid variable specifier.\n");
+ fatal_error ("Invalid variable specifier.\n");
#endif
if (!scope_name) scope_name = "_";
if (SCOPE_TYPE vars = scopes[scope_name])
1214: Inside #if defined(MODULE_DEBUG)
{
#ifdef MODULE_DEBUG
if (arrayp (var) ? !sizeof (var) : !stringp (var))
- error ("Invalid variable specifier.\n");
+ fatal_error ("Invalid variable specifier.\n");
#endif
if (!scope_name) scope_name = "_";
1273: Inside #if defined(MODULE_DEBUG)
{
#ifdef MODULE_DEBUG
if (arrayp (var) ? !sizeof (var) : !stringp (var))
- error ("Invalid variable specifier.\n");
+ fatal_error ("Invalid variable specifier.\n");
#endif
if (!scope_name) scope_name = "_";
1382:
else oldvars = scopes[scope_name];
}
#ifdef DEBUG
- if (!oldvars) fatal_error ("Internal error: I before e except after c.\n");
+ if (!oldvars) fatal_error ("I before e except after c.\n");
#endif
if (!mappingp(vars)) {
return 0;
1411:
//! Returns the name of the current scope, if it has any.
{
if (SCOPE_TYPE vars = scopes["_"]) {
- string scope_name;
- while (scope_name = search (scopes, vars, scope_name))
+ string scope_name = search (scopes, vars);
+ do
if (scope_name != "_") return scope_name;
-
+ while ((scope_name = search (scopes, vars, scope_name)));
}
return 0;
}
1508:
void enter_scope (Frame frame)
{
#ifdef DEBUG
- if (!frame->vars) fatal_error ("Internal error: Frame has no variables.\n");
+ if (!frame->vars) fatal_error ("Frame has no variables.\n");
#endif
if (string scope_name = [string] frame->scope_name) {
if (!hidden[frame])
1539:
}
}
- #define ENTER_SCOPE(ctx, frame) (frame->vars && ctx->enter_scope (frame))
- #define LEAVE_SCOPE(ctx, frame) (frame->vars && ctx->leave_scope (frame))
+ #define ENTER_SCOPE(ctx, frame) \
+ (frame->vars && frame->vars != ctx->scopes["_"] && ctx->enter_scope (frame))
+ #define LEAVE_SCOPE(ctx, frame) \
+ (frame->vars && ctx->leave_scope (frame))
mapping(string:Tag) runtime_tags = ([]);
// The active runtime tags. PI tags are stored in the same mapping
2367:
//(!) Internals:
#ifdef DEBUG
- # define THIS_TAG_TOP_DEBUG(msg, args...) tag_debug ("%O: " + (msg), this_object(), args)
- # define THIS_TAG_DEBUG(msg, args...) tag_debug ("%O: " + (msg), this_object(), args)
- # define THIS_TAG_DEBUG_ENTER_SCOPE(ctx, this, msg, args...) \
- if (this->vars && ctx->scopes["_"] != this->vars) THIS_TAG_DEBUG (msg, args)
- # define THIS_TAG_DEBUG_LEAVE_SCOPE(ctx, this, msg, args...) \
- if (this->vars && ctx->scopes["_"] == this->vars) THIS_TAG_DEBUG (msg, args)
+ # define THIS_TAG_TOP_DEBUG(msg, args...) \
+ (TAG_DEBUG_TEST (flags) && report_debug ("%O: " + (msg), this_object(), args), 0)
+ # define THIS_TAG_DEBUG(msg, args...) \
+ (TAG_DEBUG_TEST (flags) && report_debug ("%O: " + (msg), this_object(), args), 0)
+ # define THIS_TAG_DEBUG_ENTER_SCOPE(ctx, this) \
+ if (this->vars && ctx->scopes["_"] != this->vars) \
+ THIS_TAG_DEBUG ("(Re)entering scope %O\n", this->scope_name)
+ # define THIS_TAG_DEBUG_LEAVE_SCOPE(ctx, this) \
+ if (this->vars && ctx->scopes["_"] == this->vars) \
+ THIS_TAG_DEBUG ("Leaving scope %O\n", this->scope_name)
#else
# define THIS_TAG_TOP_DEBUG(msg, args...) 0
# define THIS_TAG_DEBUG(msg, args...) 0
- # define THIS_TAG_DEBUG_ENTER_SCOPE(ctx, this, msg, args...) 0
- # define THIS_TAG_DEBUG_LEAVE_SCOPE(ctx, this, msg, args...) 0
+ # define THIS_TAG_DEBUG_ENTER_SCOPE(ctx, this) 0
+ # define THIS_TAG_DEBUG_LEAVE_SCOPE(ctx, this) 0
#endif
- mixed _exec_array (TagSetParser parser, array exec, int parent_scope)
+ #define SET_SEQUENTIAL(from, to, desc) \
+ do { \
+ THIS_TAG_DEBUG ("Adding %s to " desc "\n", \
+ utils->format_short (from)); \
+ to += from; \
+ } while (0)
+
+ #define SET_NONSEQUENTIAL(from, to, to_type, desc) \
+ do { \
+ if (from != nil) { \
+ if (to != nil) \
+ parse_error ( \
+ "Cannot append another value %s to non-sequential " desc \
+ " of type %s.\n", utils->format_short (from), \
+ to_type->name); \
+ THIS_TAG_DEBUG ("Setting " desc " to %s\n", \
+ utils->format_short (from)); \
+ to = from; \
+ } \
+ } while (0)
+
+ #define CONV_RESULT(from, from_type, to, to_type) \
+ do { \
+ if (from_type->name != to_type->name) { \
+ THIS_TAG_DEBUG ("Converting result from %s to %s of " \
+ "surrounding content\n", \
+ from_type->name, to_type->name); \
+ to = to_type->encode (from, from_type); \
+ } \
+ else to = from; \
+ } while (0)
+
+ mixed _exec_array (Context ctx, TagSetParser|PCode evaler, array exec)
{
Frame this = this_object();
- Context ctx = parser->context;
- int i = 0;
+ int i = 0, parent_scope = flags & FLAG_PARENT_SCOPE;
mixed res = nil;
Parser subparser = 0;
mixed err = catch {
if (parent_scope) {
- THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this, "Exec: Temporary leaving scope\n");
+ THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this);
LEAVE_SCOPE (ctx, this);
}
2400:
switch (sprintf ("%t", elem)) {
case "string":
if (result_type->parser_prog == PNone) {
- THIS_TAG_DEBUG ("Exec[%d]: String\n", i);
+ THIS_TAG_DEBUG ("Exec[%d]: String %s\n", i, utils->format_short (elem));
piece = elem;
}
else {
- subparser = result_type->get_parser (ctx, 0, parser);
- if (parser->recover_errors && !(flags & FLAG_DONT_RECOVER))
+ subparser = result_type->get_parser (ctx, 0, evaler);
+ if (evaler->recover_errors && !(flags & FLAG_DONT_RECOVER))
subparser->recover_errors = 1;
- THIS_TAG_DEBUG ("Exec[%d]: Parsing string with %O\n", i, subparser);
+ THIS_TAG_DEBUG ("Exec[%d]: Parsing string %s with %O\n", i,
+ utils->format_short (elem), subparser);
subparser->finish ([string] elem); // Might unwind.
piece = subparser->eval(); // Might unwind.
subparser = 0;
2422:
case "multiset":
if (sizeof ([multiset] elem) == 1) {
piece = ((array) elem)[0];
- THIS_TAG_DEBUG ("Exec[%d]: Verbatim %t value\n", i, piece);
+ THIS_TAG_DEBUG ("Exec[%d]: Verbatim value %s\n", i,
+ utils->format_short (piece));
}
else if (sizeof ([multiset] elem) > 1)
fatal_error ("%d values in multiset in position %d in exec array.\n",
2437:
if (([object] elem)->is_RXML_Frame) {
THIS_TAG_DEBUG ("Exec[%d]: Evaluating frame %O\n", i, ([object] elem));
piece = ([object(Frame)] elem)->_eval (
- parser, result_type); // Might unwind.
+ ctx, evaler, result_type, 0, 0); // Might unwind.
}
else if (([object] elem)->is_RXML_Parser) {
// The subparser above unwound.
2452:
fatal_error ("Invalid type %t in position %d in exec array.\n", elem, i);
}
- if (result_type->sequential) {
- THIS_TAG_DEBUG ("Exec[%d]: Adding %t to result\n", i, piece);
- res += piece;
+ if (result_type->sequential) SET_SEQUENTIAL (piece, res, "result");
+ else SET_NONSEQUENTIAL (piece, result, result_type, "result");
}
- else if (piece != nil) {
- if (result != nil)
- parse_error (
- "Cannot append another value %s to non-sequential result type %s.\n",
- utils->format_short (piece), result_type->name);
- THIS_TAG_DEBUG ("Exec[%d]: Setting result to %t\n", i, piece);
- result = res = piece;
- }
- }
+
if (result_type->sequential) result += res;
-
+ else res = result;
+
if (parent_scope) {
- THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Exec: Reentering scope\n");
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this);
ENTER_SCOPE (ctx, this);
}
return res;
};
-
+ if (result_type->sequential) result += res;
if (parent_scope) {
- THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Exec: Reentering scope\n");
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this);
ENTER_SCOPE (ctx, this);
}
- if (result_type->sequential) result += res;
+
if (objectp (err) && ([object] err)->thrown_at_unwind) {
THIS_TAG_DEBUG ("Exec: Interrupted at position %d\n", i);
UNWIND_STATE ustate;
if ((ustate = ctx->unwind_state) && !zero_type (ustate->stream_piece)) {
// Subframe wants to stream. Update stream_piece and send it on.
- if (result_type->name != parser->type->name)
- res = parser->type->encode (res, result_type);
+ if (result_type->name != evaler->type->name)
+ res = evaler->type->encode (res, result_type);
if (result_type->sequential)
- ustate->stream_piece = res + ustate->stream_piece;
- else if (ustate->stream_piece == nil)
+ SET_SEQUENTIAL (ustate->stream_piece, res, "stream piece");
+ else
+ SET_NONSEQUENTIAL (ustate->stream_piece, res, result_type, "stream piece");
ustate->stream_piece = res;
}
ustate->exec_left = exec[i..]; // Left to execute.
2528:
ctx->new_runtime_tags = 0;
}
- mixed _eval (TagSetParser parser, Type type,
- void|mapping(string:string) raw_args,
- void|string raw_content)
- // Note: It might be somewhat tricky to override this function.
- // Note: Might be destructive on raw_args.
+ #define LOW_CALL_CALLBACK(res, cb, args...) \
+ do { \
+ THIS_TAG_DEBUG ("Calling " #cb "\n"); \
+ PROFILE_SWITCH (ctx, "rxml internal", "tag:" + tag->name); \
+ COND_PROF_ENTER(tag,tag->name,"tag"); \
+ res = ([function] cb) (args); /* Might unwind. */ \
+ COND_PROF_LEAVE(tag,tag->name,"tag"); \
+ PROFILE_SWITCH (ctx, "tag:" + tag->name, "rxml internal"); \
+ } while (0)
+
+ #define EXEC_CALLBACK(ctx, evaler, exec, cb, args...) \
+ do { \
+ if (!exec) \
+ if (arrayp (cb)) { \
+ THIS_TAG_DEBUG ("Getting exec array from " #cb "\n"); \
+ exec = [array] cb; \
+ } \
+ else { \
+ LOW_CALL_CALLBACK (exec, cb, args); \
+ THIS_TAG_DEBUG ((exec ? "Exec array of length " + \
+ sizeof (exec) : "Zero") + \
+ " returned from " #cb "\n"); \
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this); \
+ ENTER_SCOPE (ctx, this); \
+ if (evaler->is_RXML_Parser && ctx->new_runtime_tags) \
+ /* FIXME: When the evaler is a PCode object we should have a \
+ * debug check here that ensures that the same runtime tag \
+ * changes are done as in the first eval. */ \
+ _handle_runtime_tags (ctx, evaler); \
+ } \
+ } while (0)
+
+ #define EXEC_ARRAY(ctx, evaler, exec, cb) \
+ do { \
+ if (exec) { \
+ mixed res = _exec_array (ctx, evaler, exec); /* Might unwind. */ \
+ if (flags & FLAG_STREAM_RESULT) { \
+ DO_IF_DEBUG ( \
+ if (ctx->unwind_state) \
+ fatal_error ("Clobbering unwind_state to do streaming.\n"); \
+ if (piece != nil) \
+ fatal_error ("Thanks, we think about how nice it must be " \
+ "to play the harmonica...\n"); \
+ ); \
+ CONV_RESULT (res, result_type, res, type); \
+ ctx->unwind_state = (["stream_piece": res]); \
+ THIS_TAG_DEBUG ("Streaming %s from " #cb "\n", \
+ utils->format_short (res)); \
+ throw (this); \
+ } \
+ exec = 0; \
+ } \
+ } while (0)
+
+ mixed _eval (Context ctx, TagSetParser|PCode evaler, Type type,
+ mapping(string:string) raw_args, string raw_content)
+ // Note: It might be somewhat tricky to override this function,
+ // since it handles unwinding through exceptions. Note: Might be
+ // destructive on raw_args.
{
Frame this = this_object();
- Context ctx = parser->context;
+
RequestID id = ctx->id;
// Unwind state data:
2551:
#endif
Parser subparser;
mixed piece;
- array exec;
+ array exec = 0;
TagSet orig_tag_set; // Flags that we added additional_tags to ctx->tag_set.
//ctx->new_runtime_tags
2559: Inside #if defined(DEBUG)
#ifdef DEBUG
// Internal sanity checks.
if (ctx != get_context())
- PRE_INIT_ERROR ("Internal error: Context not current.\n");
- if (!parser->tag_set_eval)
- PRE_INIT_ERROR ("Internal error: Calling _eval() with non-tag set parser.\n");
+ PRE_INIT_ERROR ("Context not current.\n");
+ if (!evaler->tag_set_eval)
+ PRE_INIT_ERROR ("Calling _eval() with non-tag set parser.\n");
#endif
#ifdef MODULE_DEBUG
if (ctx->new_runtime_tags)
2572: Inside #if defined(DEBUG)
if (array state = ctx->unwind_state && ctx->unwind_state[this]) {
#ifdef DEBUG
if (!up)
- PRE_INIT_ERROR ("Internal error: Resuming frame without up pointer.\n");
+ PRE_INIT_ERROR ("Resuming frame without up pointer.\n");
if (raw_args || raw_content)
- PRE_INIT_ERROR ("Internal error: Can't feed new arguments or content "
- "when resuming parse.\n");
+ PRE_INIT_ERROR ("Can't feed new arguments or content when resuming parse.\n");
#endif
object ignored;
[ignored, eval_state, iter, raw_content, subparser, piece, exec, orig_tag_set,
2593: Inside #if defined(DEBUG)
if (flags & FLAG_UNPARSED) {
#ifdef DEBUG
if (raw_args || raw_content)
- PRE_INIT_ERROR ("Internal error: raw_args or raw_content given for "
- "unparsed frame.\n");
+ PRE_INIT_ERROR ("raw_args or raw_content given for unparsed frame.\n");
#endif
raw_args = args, args = 0;
raw_content = content, content = nil;
2622:
#undef PRE_INIT_ERROR
ctx->frame = this;
- mixed conv_result; // Result converted to the expected type.
+ mixed conv_result = nil; // Result converted to the expected type.
mixed err1 = 0;
process_tag: {
if ((err1 = catch {
2633:
TRACE_LEAVE ("");
THIS_TAG_TOP_DEBUG ("Reporting help - frame done\n");
ctx->handle_exception ( // Will throw if necessary.
- Backtrace ("help", help, ctx), parser);
+ Backtrace ("help", help, ctx), evaler);
break process_tag;
}
2671: Inside #if defined(DEBUG)
#ifdef DEBUG
Type t = atypes[arg] || tag->def_arg_type;
if (t->parser_prog != PNone) {
- Parser p = t->get_parser (ctx, 0, parser);
- THIS_TAG_DEBUG ("Evaluating argument %O with %O\n", arg, p);
+ Parser p = t->get_parser (ctx, 0, evaler);
+ THIS_TAG_DEBUG ("Evaluating argument %s with %O\n",
+ utils->format_short (arg), p);
p->finish (raw_args[arg]); // Should not unwind.
raw_args[arg] = p->eval(); // Should not unwind.
}
#else
raw_args[arg] = (atypes[arg] || tag->def_arg_type)->
- eval (raw_args[arg], ctx, 0, parser, 1); // Should not unwind.
+ eval (raw_args[arg], ctx, 0, evaler, 1); // Should not unwind.
#endif
}
#ifdef MODULE_DEBUG
2793:
case EVSTAT_BEGIN:
if (array|function(RequestID:array) do_enter =
[array|function(RequestID:array)] this->do_enter) {
- if (!exec) {
- if (arrayp (do_enter)) {
- THIS_TAG_DEBUG ("Getting exec array from do_enter\n");
- exec = [array] do_enter;
+ EXEC_CALLBACK (ctx, evaler, exec, do_enter, id);
+ EXEC_ARRAY (ctx, evaler, exec, do_enter);
}
else {
- THIS_TAG_DEBUG ("Calling do_enter\n");
- PROFILE_SWITCH (ctx, "rxml internal", "tag:" + tag->name);
- COND_PROF_ENTER(tag,tag->name,"tag");
- exec = ([function(RequestID:array)] do_enter) (id); // Might unwind.
- COND_PROF_LEAVE(tag,tag->name,"tag");
- PROFILE_SWITCH (ctx, "tag:" + tag->name, "rxml internal");
- THIS_TAG_DEBUG ((exec ? "Exec array of length " + sizeof (exec) :
- "Zero") + " returned from do_enter\n");
- }
- if (ctx->new_runtime_tags)
- _handle_runtime_tags (ctx, parser);
- }
-
- if (exec) {
- if (!(flags & FLAG_PARENT_SCOPE)) {
- THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Entering scope\n");
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this);
ENTER_SCOPE (ctx, this);
}
- mixed res = _exec_array (parser, exec, 0); // Might unwind.
-
- if (flags & FLAG_STREAM_RESULT) {
- #ifdef DEBUG
- if (ctx->unwind_state)
- fatal_error ("Internal error: Clobbering unwind_state "
- "to do streaming.\n");
- if (piece != nil)
- fatal_error ("Internal error: Thanks, we think about how nice "
- "it must be to play the harmonica...\n");
- #endif
- if (result_type->name != type->name) {
- THIS_TAG_DEBUG ("Converting result from %s to %s of "
- "surrounding content\n",
- result_type->name, type->name);
- res = type->encode (res, result_type);
- }
- ctx->unwind_state = (["stream_piece": res]);
- THIS_TAG_DEBUG ("Streaming %t from do_enter\n", res);
- throw (this);
- }
-
- exec = 0;
- }
- }
+
eval_state = EVSTAT_ENTERED;
/* Fall through. */
case EVSTAT_ENTERED:
case EVSTAT_LAST_ITER:
- do {
- if (eval_state != EVSTAT_LAST_ITER) {
+
int|function(RequestID:int) do_iterate =
[int|function(RequestID:int)] this->do_iterate;
-
+ array|function(RequestID:array) do_process =
+ [array|function(RequestID:array)] this->do_process;
+
+ do {
+ if (eval_state != EVSTAT_LAST_ITER) {
if (intp (do_iterate)) {
iter = [int] do_iterate || 1;
eval_state = EVSTAT_LAST_ITER;
2862:
#endif
}
else {
- THIS_TAG_DEBUG ("Calling do_iterate\n");
- PROFILE_SWITCH (ctx, "rxml internal", "tag:" + tag->name);
- COND_PROF_ENTER(tag,tag->name,"tag");
- iter = (/*[function(RequestID:int)]HMM*/ do_iterate) (
- id); // Might unwind.
- COND_PROF_LEAVE(tag,tag->name,"tag");
- PROFILE_SWITCH (ctx, "tag:" + tag->name, "rxml internal");
+ LOW_CALL_CALLBACK (iter, do_iterate, id);
THIS_TAG_DEBUG ("%O returned from do_iterate\n", iter);
- if (ctx->new_runtime_tags)
- _handle_runtime_tags (ctx, parser);
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this);
+ ENTER_SCOPE (ctx, this);
+ if (evaler->is_RXML_Parser && ctx->new_runtime_tags)
+ _handle_runtime_tags (ctx, evaler);
if (!iter) eval_state = EVSTAT_LAST_ITER;
}
}
- THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Entering scope\n");
- ENTER_SCOPE (ctx, this);
-
- for (; iter > 0;
- iter--
- #ifdef DEBUG
- , debug_iter++
- #endif
- ) {
+ for (; iter > 0; iter-- DO_IF_DEBUG (, debug_iter++)) {
if (raw_content && raw_content != "")
if (flags & FLAG_EMPTY_ELEMENT)
parse_error ("This tag doesn't handle content.\n");
2894:
if (!subparser) { // The nested content is not yet parsed.
if (this->local_tags) {
subparser = content_type->get_parser (
- ctx, [object(TagSet)] this->local_tags, parser);
+ ctx, [object(TagSet)] this->local_tags, evaler);
subparser->_local_tag_set = 1;
THIS_TAG_DEBUG ("Iter[%d]: Evaluating content with %O "
"from local_tags\n", debug_iter, subparser);
}
else {
- subparser = content_type->get_parser (ctx, 0, parser);
+ subparser = content_type->get_parser (ctx, 0, evaler);
#ifdef DEBUG
if (content_type->parser_prog != PNone)
THIS_TAG_DEBUG ("Iter[%d]: Evaluating content with %O\n",
debug_iter, subparser);
#endif
}
- if (parser->recover_errors && !(flags & FLAG_DONT_RECOVER))
+ if (evaler->recover_errors && !(flags & FLAG_DONT_RECOVER))
subparser->recover_errors = 1;
subparser->finish (raw_content); // Might unwind.
finished = 1;
2915:
process_subparser:
do {
- if (flags & FLAG_STREAM_CONTENT && subparser->read) {
+ if (flags & FLAG_STREAM_CONTENT && piece != nil) {
// Handle a stream piece.
- // Squeeze out any free text from the subparser first.
- mixed res = subparser->read();
- if (content_type->sequential) piece = res + piece;
- else if (piece == nil) piece = res;
- THIS_TAG_DEBUG ("Iter[%d]: Got %s %t stream piece\n",
- debug_iter, finished ? "ending" : "a", piece);
-
- if (piece != nil) {
- array|function(RequestID,void|mixed:array) do_process;
- if ((do_process =
- [array|function(RequestID,void|mixed:array)]
- this->do_process) &&
- !arrayp (do_process)) {
- if (!exec) {
- THIS_TAG_DEBUG ("Iter[%d]: Calling do_process in "
- "streaming mode\n", debug_iter);
- PROFILE_SWITCH (ctx, "rxml internal", "tag:" + tag->name);
- COND_PROF_ENTER(tag,tag->name,"tag");
- exec = do_process (id, piece); // Might unwind.
- COND_PROF_LEAVE(tag,tag->name,"tag");
- PROFILE_SWITCH (ctx, "tag:" + tag->name, "rxml internal");
- THIS_TAG_DEBUG ("Iter[%d]: %s returned from do_process\n",
- debug_iter, exec ? "Exec array of length " +
- sizeof (exec) : "Zero");
- if (ctx->new_runtime_tags)
- _handle_runtime_tags (ctx, parser);
- }
-
+ THIS_TAG_DEBUG ("Iter[%d]: Got %s stream piece %s\n",
+ debug_iter, finished ? "ending" : "a",
+ utils->format_short (piece));
+ if (!arrayp (do_process)) {
+ EXEC_CALLBACK (ctx, evaler, exec, do_process, id, piece);
if (exec) {
- THIS_TAG_DEBUG_ENTER_SCOPE (
- ctx, this, "Iter[%d]: Entering scope\n", debug_iter);
- ENTER_SCOPE (ctx, this);
- mixed res = _exec_array (
- parser, exec, flags & FLAG_PARENT_SCOPE); // Might unwind.
-
+ mixed res = _exec_array (ctx, evaler, exec); // Might unwind.
if (flags & FLAG_STREAM_RESULT) {
#ifdef DEBUG
if (!zero_type (ctx->unwind_state->stream_piece))
- fatal_error ("Internal error: Clobbering "
- "unwind_state->stream_piece.\n");
+ fatal_error ("Clobbering unwind_state->stream_piece.\n");
#endif
- if (result_type->name != type->name) {
- THIS_TAG_DEBUG (
- "Iter[%d]: Converting result from %s to %s"
- " of surrounding content\n", debug_iter,
- result_type->name, type->name);
- res = type->encode (res, result_type);
- }
+ CONV_RESULT (res, result_type, res, type);
ctx->unwind_state->stream_piece = res;
- THIS_TAG_DEBUG ("Iter[%d]: Streaming %t from "
- "do_process\n", debug_iter, res);
+ THIS_TAG_DEBUG ("Iter[%d]: Streaming %s from do_process\n",
+ debug_iter, utils->format_short (res));
throw (this);
}
-
+
exec = 0;
}
else if (flags & FLAG_STREAM_RESULT) {
2982:
}
}
piece = nil;
- }
+
if (finished) break process_subparser;
}
2990:
piece = nil;
if (finished) {
mixed res = subparser->eval(); // Might unwind.
- if (content_type->sequential) {
- THIS_TAG_DEBUG ("Iter[%d]: Adding %t to content\n",
- debug_iter, res);
- content += res;
- }
- else if (res != nil) {
- if (content != nil)
- parse_error (
- "Cannot append another value %s to non-sequential "
- "content type %s.\n", utils->format_short (res),
- content_type->name);
- THIS_TAG_DEBUG ("Iter[%d]: Setting content to %t\n",
- debug_iter, res);
- content = res;
- }
+ if (content_type->sequential)
+ SET_SEQUENTIAL (res, content, "content");
+ else if (res != nil)
+ SET_NONSEQUENTIAL (res, content, content_type, "content");
break process_subparser;
}
}
3016:
subparser = 0;
}
- if (array|function(RequestID,void|mixed:array) do_process =
- [array|function(RequestID,void|mixed:array)] this->do_process) {
- if (!exec) {
- if (arrayp (do_process)) {
- THIS_TAG_DEBUG ("Iter[%d]: Getting exec array from do_process\n",
- debug_iter);
- exec = [array] do_process;
+ if (do_process) {
+ EXEC_CALLBACK (ctx, evaler, exec, do_process, id);
+ EXEC_ARRAY (ctx, evaler, exec, do_process);
}
- else {
- THIS_TAG_DEBUG ("Iter[%d]: Calling do_process\n", debug_iter);
- PROFILE_SWITCH (ctx, "rxml internal", "tag:" + tag->name);
- COND_PROF_ENTER(tag,tag->name,"tag");
- exec = ([function(RequestID,void|mixed:array)] do_process) (
- id); // Might unwind.
- COND_PROF_LEAVE(tag,tag->name,"tag");
- PROFILE_SWITCH (ctx, "tag:" + tag->name, "rxml internal");
- THIS_TAG_DEBUG ("Iter[%d]: %s returned from do_process\n",
- debug_iter, exec ? "Exec array of length " +
- sizeof (exec) : "Zero");
+
}
- if (ctx->new_runtime_tags)
- _handle_runtime_tags (ctx, parser);
- }
-
- if (exec) {
- THIS_TAG_DEBUG_ENTER_SCOPE (
- ctx, this, "Iter[%d]: Entering scope\n", debug_iter);
- ENTER_SCOPE (ctx, this);
- mixed res = _exec_array (
- parser, exec, flags & FLAG_PARENT_SCOPE); // Might unwind.
-
- if (flags & FLAG_STREAM_RESULT) {
- #ifdef DEBUG
- if (ctx->unwind_state)
- fatal_error ("Internal error: Clobbering unwind_state "
- "to do streaming.\n");
- if (piece != nil)
- fatal_error ("Internal error: Thanks, we think about how nice "
- "it must be to play the harmonica...\n");
- #endif
- if (result_type->name != type->name) {
- THIS_TAG_DEBUG ("Iter[%d]: Converting result from "
- "type %s to type %s of surrounding content\n",
- debug_iter,
- result_type->name, type->name);
- res = type->encode (res, result_type);
- }
- ctx->unwind_state = (["stream_piece": res]);
- THIS_TAG_DEBUG ("Iter[%d]: Streaming %t from do_process\n",
- debug_iter, res);
- throw (this);
- }
-
- exec = 0;
- }
- }
-
- }
+
} while (eval_state != EVSTAT_LAST_ITER);
-
+ eval_state = EVSTAT_ITER_DONE;
/* Fall through. */
case EVSTAT_ITER_DONE:
if (array|function(RequestID:array) do_return =
[array|function(RequestID:array)] this->do_return) {
- eval_state = EVSTAT_ITER_DONE; // Only need to record this state here.
- if (!exec) {
- if (arrayp (do_return)) {
- THIS_TAG_DEBUG ("Getting exec array from do_return\n");
- exec = [array] do_return;
- }
- else {
- THIS_TAG_DEBUG ("Calling do_return\n");
- PROFILE_SWITCH (ctx, "rxml internal", "tag:" + tag->name);
- COND_PROF_ENTER(tag,tag->name,"tag");
- exec = ([function(RequestID:array)] do_return) (id); // Might unwind.
- COND_PROF_LEAVE(tag,tag->name,"tag");
- PROFILE_SWITCH (ctx, "tag:" + tag->name, "rxml internal");
- THIS_TAG_DEBUG ((exec ? "Exec array of length " + sizeof (exec) :
- "Zero") + " returned from do_return\n");
- }
- if (ctx->new_runtime_tags)
- _handle_runtime_tags (ctx, parser);
- }
-
+ EXEC_CALLBACK (ctx, evaler, exec, do_return, id);
if (exec) {
- THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Entering scope\n");
- ENTER_SCOPE (ctx, this);
- _exec_array (parser, exec, flags & FLAG_PARENT_SCOPE); // Might unwind.
+ // We don't use EXEC_ARRAY here since it's no idea to
+ // come back even if any streaming should be done.
+ _exec_array (ctx, evaler, exec); // Might unwind.
exec = 0;
}
}
3112:
if (result_type->parser_prog == PNone) {
if (content_type->name != result_type->name) {
THIS_TAG_DEBUG ("Assigning content to result after "
- "converting from %s to %s\n",
+ "conversion from %s to %s\n",
content_type->name, result_type->name);
result = result_type->encode (content, content_type);
}
3123:
}
else
if (stringp (content)) {
- eval_state = EVSTAT_ITER_DONE; // Only need to record this state here.
+
if (!exec) {
THIS_TAG_DEBUG ("Parsing content with exec array "
"for assignment to result\n");
exec = ({content});
}
- _exec_array (parser, exec, flags & FLAG_PARENT_SCOPE); // Might unwind.
+ _exec_array (ctx, evaler, exec); // Might unwind.
exec = 0;
}
}
-
+
+ if (result != nil)
+ CONV_RESULT (result, result_type, conv_result, type);
#ifdef DEBUG
- if (result == nil) THIS_TAG_DEBUG ("Skipping nil result\n");
+ else THIS_TAG_DEBUG ("Skipping nil result\n");
#endif
- if (result != nil && result_type->name != type->name) {
- THIS_TAG_DEBUG (
- "Converting result from %s to %s of surrounding content\n",
- result_type->name, type->name);
- conv_result = type->encode (result, result_type);
- }
- else conv_result = result;
-
- THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this, "Leaving scope\n");
+ THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this);
LEAVE_SCOPE (ctx, this);
- if (ctx->new_runtime_tags)
- _handle_runtime_tags (ctx, parser);
+ if (evaler->is_RXML_Parser && ctx->new_runtime_tags)
+ _handle_runtime_tags (ctx, evaler);
}
}) {
- THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this, "Leaving scope\n");
+ THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this);
LEAVE_SCOPE (ctx, this);
-
+
string action;
-
+ exception:
+ {
+ unwind:
if (objectp (err2) && ([object] err2)->thrown_at_unwind) {
UNWIND_STATE ustate = ctx->unwind_state;
if (!ustate) ustate = ctx->unwind_state = ([]);
#ifdef DEBUG
- if (ustate[this])
- fatal_error ("Internal error: Frame already has an unwind state.\n");
+ if (ustate[this]) fatal_error ("Frame already has an unwind state.\n");
#endif
if (ustate->exec_left) {
3171:
if (err2 == this || exec && sizeof (exec) && err2 == exec[0])
// This frame or a frame in the exec array wants to stream.
- if (parser->unwind_safe) {
+ if (evaler->read && evaler->unwind_safe) {
// Rethrow to continue in parent since we've already done
// the appropriate do_process stuff in this frame in
// either case.
-
+ mixed piece = evaler->read();
+ if (err2 = catch {
+ if (type->sequential)
+ SET_SEQUENTIAL (ustate->stream_piece, piece, "stream piece");
+ else
+ SET_NONSEQUENTIAL (ustate->stream_piece, piece, type, "stream piece");
+ }) break unwind;
if (err2 == this) err2 = 0;
if (orig_tag_set) ctx->tag_set = orig_tag_set, orig_tag_set = 0;
action = "break";
- THIS_TAG_TOP_DEBUG ("Interrupted for streaming - "
- "breaking to parent frame\n");
+ THIS_TAG_TOP_DEBUG ("Breaking to parent frame to do streaming\n");
}
else {
- // Can't stream since the parser isn't unwind safe. Just
- // continue.
+ // Can't stream since the parser doesn't allow that.
+ // Just continue.
m_delete (ustate, "stream_piece");
action = "continue";
- THIS_TAG_TOP_DEBUG ("Interrupted for streaming - "
- "continuing since parser isn't unwind safe\n");
+ THIS_TAG_TOP_DEBUG ("Not streaming since the parser "
+ "doesn't allow that\n");
}
else if (!zero_type (ustate->stream_piece)) {
// Got a stream piece from a subframe. We handle it above;
3208:
#endif
});
TRACE_LEAVE (action);
+ break exception;
}
- else {
+
THIS_TAG_TOP_DEBUG ("Exception\n");
TRACE_LEAVE ("exception");
- ctx->handle_exception (err2, parser); // Will rethrow unknown errors.
+ ctx->handle_exception (err2, evaler); // Will rethrow unknown errors.
result = nil;
action = "return";
}
3220:
switch (action) {
case "break": // Throw and handle in parent frame.
#ifdef MODULE_DEBUG
- if (!parser->unwind_state)
- fatal_error ("Trying to unwind inside a parser that isn't unwind safe.\n");
+ if (!evaler->unwind_state)
+ fatal_error ("Trying to unwind inside an evaluator "
+ "that isn't unwind safe.\n");
#endif
throw (this);
case "continue": // Continue in this frame through tail recursion.
- return _eval (parser, type);
+ return _eval (ctx, evaler, type, 0, 0);
case "return": // A normal return.
break process_tag;
default:
- fatal_error ("Internal error: Don't you come here and %O on me!\n", action);
+ fatal_error ("Don't you come here and %O on me!\n", action);
}
}
3372: Inside #if defined(MODULE_DEBUG)
{
#ifdef MODULE_DEBUG
if (arrayp (index) ? !sizeof (index) : !(stringp (index) || intp (index)))
- error ("Invalid index specifier.\n");
+ fatal_error ("Invalid index specifier.\n");
#endif
int scope_got_type = 0;
3410: Inside #if defined(MODULE_DEBUG)
!(objectp (val) && ([object] val)->rxml_var_eval) &&
catch (want_type->type_check (val)))
if (([object] err)->is_RXML_Backtrace)
- error ("%O->`[] didn't return a value of the correct type:\n%s",
+ fatal_error ("%O->`[] didn't return a value of the correct type:\n%s",
scope, err->msg);
else throw (err);
#endif
3440: Inside #if defined(MODULE_DEBUG)
// but we'll live with that. Besides, that situation ought to be
// solved internally in them anyway.
if (called[val])
- error ("Cyclic rxml_var_eval chain detected in %O.\n"
+ fatal_error ("Cyclic rxml_var_eval chain detected in %O.\n"
"All called objects:%{ %O%}\n", val, indices (called));
called[val] = 1;
#endif
3468: Inside #if defined(MODULE_DEBUG)
do {
#ifdef MODULE_DEBUG
if (called[val])
- error ("Cyclic rxml_var_eval chain detected in %O.\n"
+ fatal_error ("Cyclic rxml_var_eval chain detected in %O.\n"
"All called objects:%{ %O%}\n", val, indices (called));
called[val] = 1;
Value val_obj = [object(Value)] val;
3480: Inside #if defined(MODULE_DEBUG)
#ifdef MODULE_DEBUG
else if (mixed err = want_type && catch (want_type->type_check (val)))
if (([object] err)->is_RXML_Backtrace)
- error ("%O->rxml_var_eval didn't return a value of the correct type:\n%s",
+ fatal_error ("%O->rxml_var_eval didn't return a value of the correct type:\n%s",
val_obj, err->msg);
else throw (err);
#endif
3598: Inside #if defined(DEBUG)
#ifdef DEBUG
if (err != this_object()) {
LEAVE_CONTEXT();
- fatal_error ("Internal error: Unexpected unwind object catched.\n");
+ fatal_error ("Unexpected unwind object catched.\n");
}
#endif
if (!context->unwind_state) context->unwind_state = ([]);
3635: Inside #if defined(DEBUG)
#ifdef DEBUG
if (err != this_object()) {
LEAVE_CONTEXT();
- fatal_error ("Internal error: Unexpected unwind object catched.\n");
+ fatal_error ("Unexpected unwind object catched.\n");
}
#endif
if (!context->unwind_state) context->unwind_state = ([]);
3651:
#endif
}
- mixed handle_var (TagSetParser parser, string varref, Type want_type)
+ mixed handle_var (TagSetParser|PCode evaler, string varref, Type want_type)
// Parses and evaluates a possible variable reference, with the
// appropriate error handling.
{
3666:
parse_error (
"No scope in variable reference.\n"
"(Use ':' in front to quote a character reference containing dots.)\n");
+ #ifdef DEBUG
+ if (context->frame)
+ TAG_DEBUG (context->frame, " Looking up variable %s in context of type %s\n",
+ splitted * ".", (encoding ? t_string : want_type)->name);
+ #endif
mixed val;
PROFILE_SWITCH (context, "rxml internal", "var:" + varref);
COND_PROF_ENTER(mixed id=context->id,varref,"entity");
3675:
val = nil;
COND_PROF_LEAVE(mixed id=context->id,varref,"entity");
PROFILE_SWITCH (context, "var:" + varref, "rxml internal");
- if (encoding && !(val = Roxen->roxen_encode (val + "", encoding)))
+ if (encoding) {
+ if (!(val = Roxen->roxen_encode (val + "", encoding)))
parse_error ("Unknown encoding %O.\n", encoding);
-
+ #ifdef DEBUG
+ if (context->frame)
+ TAG_DEBUG (context->frame, " Got value %s after conversion "
+ "with encoding %s\n", utils->format_short (val), encoding);
+ #endif
+ }
+ #ifdef DEBUG
+ else
+ if (context->frame)
+ TAG_DEBUG (context->frame, " Got value %s\n", utils->format_short (val));
+ #endif
context->current_var = 0;
- if (parser->p_code)
- parser->p_code->add (VarRef (splitted[0], splitted[1..], encoding));
+ if (evaler->p_code)
+ evaler->p_code->add (VarRef (splitted[0], splitted[1..], encoding));
return val;
}) {
context->current_var = 0;
3738:
optional mixed read();
//! Define to allow streaming operation. Returns the evaluated
- //! result so far, but does not do any evaluation. Returns RXML.nil
- //! if there's no data (for sequential types the empty value is also
- //! ok).
+ //! result so far, but does not do any more evaluation. Returns
+ //! RXML.nil if there's no data.
mixed eval();
//! Evaluates the data fed so far and returns the result. The result
4428: Inside #if defined(MODULE_DEBUG)
else {
#ifdef MODULE_DEBUG
if (conversion_type->name == from->name)
- error ("This function shouldn't be used to convert "
+ fatal_error ("This function shouldn't be used to convert "
"from the conversion type %s to %s; use encode() for that.\n",
conversion_type->name, this_object()->name);
#endif
5047: Inside #if defined(DEBUG)
#ifdef DEBUG
if (err != this_object()) {
LEAVE_CONTEXT();
- fatal_error ("Internal error: Unexpected unwind object catched.\n");
+ fatal_error ("Unexpected unwind object catched.\n");
}
#endif
if (!context->unwind_state) context->unwind_state = ([]);
5094:
// FIXME
}
- PCode|Parser _parent;
- // The parent evaluator if this one is nested.
-
+
MARK_OBJECT;
string _sprintf() {return "RXML.PCode" + OBJ_COUNT;}
5135:
case "mapping":
return ([]);
default:
- error ("Cannot cast RXML.nil to "+type+".\n");
+ fatal_error ("Cannot cast RXML.nil to "+type+".\n");
}
}
};