2000-09-08
2000-09-08 03:23:58 by Martin Stjernholm <mast@lysator.liu.se>
-
ac6977fa98f5940bca20847a3f0b8fe1f5fa1312
(421 lines)
(+351/-70)
[
Show
| Annotate
]
Branch: 5.2
Added FLAG_DEBUG for assisting in tag debugging. It shows how the tag
and frame objects are handled. Fixed a bug where the content wasn't
converted before being assigned to the result when there's no
do_return. The t_text type is no longer a supertype over the formatted
text types; it's now named text/plain.
Rev: server/etc/modules/RXML.pmod/module.pmod:1.108
2:
//!
//! Created 1999-07-30 by Martin Stjernholm.
//!
- //! $Id: module.pmod,v 1.107 2000/09/07 20:26:14 mast Exp $
+ //! $Id: module.pmod,v 1.108 2000/09/08 03:23:58 mast Exp $
//! Kludge: Must use "RXML.refs" somewhere for the whole module to be
//! loaded correctly.
80:
# define OBJ_COUNT ""
#endif
+ #ifdef DEBUG
+ # define TAG_DEBUG(frame, msg) (frame)->tag_debug ("%O: %s", (frame), (msg))
+ #else
+ # define TAG_DEBUG(frame, msg) 0
+ #endif
+
#define HASH_INT2(m, n) (n < 65536 ? (m << 16) + n : sprintf ("%x,%x", m, n))
263:
}
object/*(Frame)HMM*/ frame;
+ do {
if (mapping(string:mixed)|mapping(object:array) ustate = ctx->unwind_state)
if (ustate[parser]) {
frame = [object/*(Frame)HMM*/] ustate[parser][0];
m_delete (ustate, parser);
if (!sizeof (ustate)) ctx->unwind_state = 0;
-
+ break;
}
- else frame = `() (args, nil);
- else frame = `() (args, nil);
+ frame = `() (args, nil);
+ TAG_DEBUG (frame, "New frame\n");
+ } while (0); // The break goes here.
if (!zero_type (frame->raw_tag_text)) {
if (splice_args)
285:
if ((res = frame->result) == nil) return ({});
if (frame->result_type->encoding_type ?
frame->result_type->encoding_type != parser->type->encoding_type :
- frame->result_type != parser->type)
+ frame->result_type != parser->type) {
+ TAG_DEBUG (frame, sprintf (
+ "Converting result from %s to %s of surrounding content\n",
+ frame->result_type->name, parser->type->name));
res = parser->type->encode (res, frame->result_type);
-
+ }
return ({res});
};
1473:
constant FLAG_NONE = 0x00000000;
//! The no-flags flag. In case you think 0 is too ugly. ;)
+ constant FLAG_DEBUG = 0x40000000;
+ //! Write a lot of debug during the execution of the tag, showing what
+ //! type conversions are done, what callbacks are being called etc.
+ //! Note that DEBUG must be defined for the debug printouts to be
+ //! compiled in (normally enabled with the --debug flag to Roxen).
+
//! Static flags (i.e. tested in the Tag object).
constant FLAG_PROC_INSTR = 0x00000010;
1784:
//! through the content. This will repeat until 0 is returned.
//!
//! If do_iterate is a positive integer, that many passes is done
- //! and then the tag exits. If do_iterate is zero no pass is done.
- //! If do_iterate is missing, one pass is done.
+ //! and then the tag exits. If do_iterate is zero or missing, one
+ //! pass is done. If do_iterate is negative, no pass is done.
//!int|function(RequestID:int) is_valid;
//! When defined, the frame may be cached. First the name of the tag
1833:
_parse_error (msg, @args);
}
+ local void tag_debug (string msg, mixed... args)
+ //! Writes the message to the debug log if this tag has FLAG_DEBUG
+ //! set.
+ {
+ if (flags & FLAG_DEBUG) werror (msg, @args);
+ }
+
void terminate()
//! Makes the parser abort. The data parsed so far will be returned.
//! Does not return; throws a special exception instead.
1939:
// Internals.
+ #ifdef DEBUG
+ # define THIS_TAG_TOP_DEBUG(msg) tag_debug ("%O: %s", this_object(), (msg))
+ # define THIS_TAG_DEBUG(msg) tag_debug ("%O: %s", this_object(), (msg))
+ # define THIS_TAG_DEBUG_ENTER_SCOPE(ctx, this, msg) \
+ if (this->vars && ctx->scopes["_"] != this->vars) THIS_TAG_DEBUG (msg)
+ # define THIS_TAG_DEBUG_LEAVE_SCOPE(ctx, this, msg) \
+ if (this->vars && ctx->scopes["_"] == this->vars) THIS_TAG_DEBUG (msg)
+ #else
+ # define THIS_TAG_TOP_DEBUG(msg) 0
+ # define THIS_TAG_DEBUG(msg) 0
+ # define THIS_TAG_DEBUG_ENTER_SCOPE(ctx, this, msg) 0
+ # define THIS_TAG_DEBUG_LEAVE_SCOPE(ctx, this, msg) 0
+ #endif
+
mixed _exec_array (TagSetParser parser, array exec, int parent_scope)
{
Frame this = this_object();
1948:
Parser subparser = 0;
mixed err = catch {
- if (parent_scope) LEAVE_SCOPE (ctx, this);
+ if (parent_scope) {
+ THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this, "Exec: Temporary leaving scope\n");
+ LEAVE_SCOPE (ctx, this);
+ }
for (; i < sizeof (exec); i++) {
mixed elem = exec[i], piece = nil;
switch (sprintf ("%t", elem)) {
case "string":
- if (result_type->_parser_prog == PNone)
+ if (result_type->_parser_prog == PNone) {
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: String\n", i));
piece = elem;
-
+ }
else {
subparser = result_type->get_parser (ctx, 0, parser);
if (flags & FLAG_DONT_REPORT_ERRORS)
subparser->disable_report_error = 1;
-
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: Parsing string with %O\n",
+ i, subparser));
subparser->finish ([string] elem); // Might unwind.
piece = subparser->eval(); // Might unwind.
subparser = 0;
}
break;
-
+
case "mapping":
-
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: Header mapping\n", i));
fatal_error ("Header mappings not yet implemented.\n");
break;
-
+
case "multiset":
- if (sizeof ([multiset] elem) == 1) piece = ((array) elem)[0];
+ if (sizeof ([multiset] elem) == 1) {
+ piece = ((array) elem)[0];
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: Verbatim %t value\n", i, piece));
+ }
else if (sizeof ([multiset] elem) > 1)
fatal_error (sizeof ([multiset] elem) +
" values in multiset in exec array.\n");
else fatal_error ("No value in multiset in exec array.\n");
break;
-
+
default:
if (objectp (elem))
// Can't count on that sprintf ("%t", ...) on an object
// returns "object".
if (([object] elem)->is_RXML_Frame) {
-
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: Evaluating frame %O\n",
+ i, ([object] elem)));
([object(Frame)] elem)->_eval (parser); // Might unwind.
piece = ([object(Frame)] elem)->result;
}
else if (([object] elem)->is_RXML_Parser) {
// The subparser above unwound.
-
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: Continuing eval of frame %O\n",
+ i, ([object] elem)));
([object(Parser)] elem)->finish(); // Might unwind.
piece = ([object(Parser)] elem)->eval(); // Might unwind.
}
1995:
fatal_error ("Invalid type %t in exec array.\n", elem);
}
- if (result_type->sequential) res += piece;
- else if (piece != nil) result = res = piece;
+ if (result_type->sequential) {
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: Adding %t to result\n", i, piece));
+ res += piece;
}
-
+ else if (piece != nil) {
+ THIS_TAG_DEBUG (sprintf ("Exec[%d]: Setting result to %t\n", i, piece));
+ result = res = piece;
+ }
+ }
if (result_type->sequential) result += res;
- if (parent_scope) ENTER_SCOPE (ctx, this);
+ if (parent_scope) {
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Exec: Reentering scope\n");
+ ENTER_SCOPE (ctx, this);
+ }
return res;
};
- if (parent_scope) ENTER_SCOPE (ctx, this);
+ if (parent_scope) {
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Exec: Reentering scope\n");
+ ENTER_SCOPE (ctx, this);
+ }
if (result_type->sequential) result += res;
if (objectp (err) && ([object] err)->thrown_at_unwind) {
-
+ THIS_TAG_DEBUG (sprintf ("Exec: Interrupted at position %d\n", i));
mapping(string:mixed)|mapping(object:array) ustate;
if ((ustate = ctx->unwind_state) && !zero_type (ustate->stream_piece)) {
// Subframe wants to stream. Update stream_piece and send it on.
2039:
array(string) arr_rem_pi_tags = ctx->new_runtime_tags->removed_pi_tags();
for (Parser p = parser; p; p = p->_parent)
if (p->tag_set_eval && !p->_local_tag_set && p->add_runtime_tag) {
- foreach (arr_add_tags, Tag tag)
+ foreach (arr_add_tags, Tag tag) {
+ THIS_TAG_DEBUG (sprintf ("Adding runtime tag %O\n", tag));
([object(TagSetParser)] p)->add_runtime_tag (tag);
- foreach (arr_rem_tags, string tag)
+ }
+ foreach (arr_rem_tags, string tag) {
+ THIS_TAG_DEBUG (sprintf ("Removing runtime tag %s\n", tag));
([object(TagSetParser)] p)->remove_runtime_tag (tag);
- foreach (arr_rem_pi_tags, string tag)
+ }
+ foreach (arr_rem_pi_tags, string tag) {
+ THIS_TAG_DEBUG (sprintf ("Removing runtime tag %s\n", tag));
([object(TagSetParser)] p)->remove_runtime_tag (tag, 1);
}
-
+ }
ctx->runtime_tags = ctx->new_runtime_tags->filter_tags (ctx->runtime_tags);
ctx->new_runtime_tags = 0;
}
2068:
#define EVSTAT_ITER_DONE 3
int eval_state = EVSTAT_BEGIN;
int iter;
+ #ifdef DEBUG
+ int debug_iter = 1;
+ #endif
Parser subparser;
mixed piece;
array exec;
2088:
"Context.remove_runtime_tag() was used outside any parser.\n");
#endif
- 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");
- #endif
- raw_args = args, args = 0;
- raw_content = content, content = nil;
- #ifdef MODULE_DEBUG
- if (!stringp (raw_content))
- PRE_INIT_ERROR ("Content is not a string in unparsed tag frame.\n");
- #endif
- }
-
+
if (array state = ctx->unwind_state && ctx->unwind_state[this]) {
#ifdef DEBUG
if (!up)
2112:
#endif
object ignored;
[ignored, eval_state, iter, raw_content, subparser, piece, exec, orig_tag_set,
- ctx->new_runtime_tags] = state;
+ ctx->new_runtime_tags
+ #ifdef DEBUG
+ , debug_iter
+ #endif
+ ] = state;
m_delete (ctx->unwind_state, this);
if (!sizeof (ctx->unwind_state)) ctx->unwind_state = 0;
-
+ THIS_TAG_TOP_DEBUG ("Continuing evaluation" +
+ (piece ? " with stream piece\n" : "\n"));
}
else {
-
+ 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");
+ #endif
+ raw_args = args, args = 0;
+ raw_content = content, content = nil;
#ifdef MODULE_DEBUG
-
+ if (!stringp (raw_content))
+ PRE_INIT_ERROR ("Content is not a string in unparsed tag frame.\n");
+ #endif
+ THIS_TAG_TOP_DEBUG ("Evaluating unparsed\n");
+ }
+ else THIS_TAG_TOP_DEBUG ("Evaluating\n");
+
+ #ifdef MODULE_DEBUG
if (up && up != ctx->frame)
PRE_INIT_ERROR ("Reuse of frame in different context.\n");
#endif
2140:
TRACE_ENTER ("tag <" + tag->name + " help>", tag);
string help = id->conf->find_tag_doc (tag->name, id);
TRACE_LEAVE ("");
+ THIS_TAG_TOP_DEBUG ("Reporting help - frame done\n");
ctx->handle_exception ( // Will throw if necessary.
Backtrace ("help", help, ctx), parser);
break;
2149: Inside #if defined(MODULE_LEVEL_SECURITY)
#ifdef MODULE_LEVEL_SECURITY
if (id->conf->check_security (tag, id, id->misc->seclevel)) {
+ THIS_TAG_TOP_DEBUG ("Access denied - exiting\n");
TRACE_LEAVE("access denied");
break;
}
2174: Inside #if defined(MODULE_DEBUG)
#ifdef MODULE_DEBUG
if (mixed err = catch {
#endif
- foreach (indices (raw_args), string arg)
+ foreach (indices (raw_args), string arg) {
+ #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 (sprintf ("Evaluating argument %O with %O\n", 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.
-
+ #endif
+ }
#ifdef MODULE_DEBUG
}) {
if (objectp (err) && ([object] err)->thrown_at_unwind)
2192:
#endif
if (!zero_type (this->parent_frame))
- if (up->local_tags && up->local_tags->has_tag (tag))
+ if (up->local_tags && up->local_tags->has_tag (tag)) {
+ THIS_TAG_DEBUG (sprintf ("Setting parent_frame to %O from local_tags\n", up));
this->parent_frame = up;
-
+ }
else
for (Frame f = up; f; f = f->up)
if (f->additional_tags && f->additional_tags->has_tag (tag)) {
-
+ THIS_TAG_DEBUG (sprintf ("Setting parent_frame to %O "
+ "from additional_tags\n", f));
this->parent_frame = f;
break;
}
2204:
if (TagSet add_tags = raw_content && [object(TagSet)] this->additional_tags) {
TagSet tset = ctx->tag_set;
if (!tset->has_effective_tags (add_tags)) {
+ THIS_TAG_DEBUG (sprintf ("Installing additional_tags %O\n", add_tags));
int hash = HASH_INT2 (tset->id_number, add_tags->id_number);
orig_tag_set = tset;
TagSet local_ts;
2214:
}
ctx->tag_set = local_ts;
}
+ else
+ THIS_TAG_DEBUG (sprintf ("Not installing additional_tags %O "
+ "since they're already in the tag set\n", add_tags));
}
if (!result_type) {
2232:
result_type = ptype (rtype->_parser_prog);
break;
}
- if (!result_type) // Sigh..
+ if (!result_type)
parse_error (
"Tag returns " +
String.implode_nicely ([array(string)] tag->result_types->name, "or") +
" but " + [string] parser->type->name + " is expected.\n");
-
+ THIS_TAG_DEBUG (sprintf ("Resolved result_type to %O from surrounding %O\n",
+ result_type, ptype));
}
-
+ else THIS_TAG_DEBUG (sprintf ("Keeping result_type %O\n", result_type));
+
if (!content_type) {
#ifdef MODULE_DEBUG
if (!tag) fatal_error ("content_type not set in Frame object %O, "
2245:
this_object());
#endif
content_type = tag->content_type;
- if (content_type == t_same)
+ if (content_type == t_same) {
content_type = result_type (content_type->_parser_prog);
-
+ THIS_TAG_DEBUG (sprintf ("Resolved t_same to content_type %O\n",
+ content_type));
}
- if (raw_content) content = content_type->empty_value;
+ else THIS_TAG_DEBUG (sprintf ("Setting content_type to %O from tag\n",
+ content_type));
+ }
+ else THIS_TAG_DEBUG (sprintf ("Keeping content_type %O\n", content_type));
-
+ if (raw_content) {
+ THIS_TAG_DEBUG ("Initializing the content variable to nil\n");
+ content = content_type->empty_value;
+ }
+
mixed err = catch {
switch (eval_state) {
case EVSTAT_BEGIN:
if (array|function(RequestID:array) do_enter =
[array|function(RequestID:array)] this->do_enter) {
if (!exec) {
- exec = arrayp (do_enter) ? [array] do_enter :
- ([function(RequestID:array)] do_enter) (
- id); // Might unwind.
+ if (arrayp (do_enter)) {
+ THIS_TAG_DEBUG ("Getting exec array from do_enter\n");
+ exec = [array] do_enter;
+ }
+ else {
+ THIS_TAG_DEBUG ("Calling do_enter\n");
+ exec = ([function(RequestID:array)] do_enter) (id); // Might unwind.
+ THIS_TAG_DEBUG ((exec ? "Exec array" : "Zero") +
+ " returned from do_enter\n");
+ }
if (ctx->new_runtime_tags)
_handle_runtime_tags (ctx, parser);
}
-
+
if (exec) {
- if (!(flags & FLAG_PARENT_SCOPE)) ENTER_SCOPE (ctx, this);
+ if (!(flags & FLAG_PARENT_SCOPE)) {
+ THIS_TAG_DEBUG_ENTER_SCOPE (ctx, this, "Entering scope\n");
+ ENTER_SCOPE (ctx, this);
+ }
mixed res = _exec_array (parser, exec, 0); // Might unwind.
-
+
if (flags & FLAG_STREAM_RESULT) {
#ifdef DEBUG
if (ctx->unwind_state)
2276:
#endif
if (result_type->encoding_type ?
result_type->encoding_type != parser->type->encoding_type :
- result_type != parser->type)
+ result_type != parser->type) {
+ THIS_TAG_DEBUG (sprintf ("Converting result from %s to %s of "
+ "surrounding content\n",
+ result_type->name, parser->type->name));
res = parser->type->encode (res, result_type);
-
+ }
ctx->unwind_state = (["stream_piece": res]);
-
+ THIS_TAG_DEBUG (sprintf ("Streaming %t from do_enter\n", res));
throw (this);
}
-
+
exec = 0;
}
}
2296:
if (intp (do_iterate)) {
iter = [int] do_iterate || 1;
eval_state = EVSTAT_LAST_ITER;
+ #ifdef DEBUG
+ if (iter > 1)
+ THIS_TAG_DEBUG (sprintf ("Getting %d iterations from do_iterate\n",
+ iter));
+ else if (iter < 0)
+ THIS_TAG_DEBUG ("Skipping to finish since do_iterate is negative\n");
+ #endif
}
else {
-
+ THIS_TAG_DEBUG ("Calling do_iterate\n");
iter = (/*[function(RequestID:int)]HMM*/ do_iterate) (
id); // Might unwind.
-
+ THIS_TAG_DEBUG (sprintf ("%O returned from do_iterate\n", iter));
if (ctx->new_runtime_tags)
_handle_runtime_tags (ctx, parser);
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--) {
+ for (; iter > 0;
+ iter--
+ #ifdef DEBUG
+ , debug_iter++
+ #endif
+ ) {
if (raw_content && raw_content != "")
if (flags & FLAG_EMPTY_ELEMENT)
parse_error ("This tag doesn't handle content.\n");
-
+
else { // Got nested parsing to do.
int finished = 0;
if (!subparser) { // The nested content is not yet parsed.
2318:
subparser = content_type->get_parser (
ctx, [object(TagSet)] this->local_tags, parser);
subparser->_local_tag_set = 1;
+ THIS_TAG_DEBUG (
+ sprintf ("Iter[%d]: Evaluating content with %O "
+ "from local_tags\n", debug_iter, subparser));
}
- else
+ else {
subparser = content_type->get_parser (ctx, 0, parser);
-
+ #ifdef DEBUG
+ if (content_type->_parser_prog != PNone)
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Evaluating content "
+ "with %O\n", debug_iter, subparser));
+ #endif
+ }
if (flags & FLAG_DONT_REPORT_ERRORS)
subparser->disable_report_error = 1;
subparser->finish (raw_content); // Might unwind.
2334:
mixed res = subparser->read();
if (content_type->sequential) piece = res + piece;
else if (piece == nil) piece = res;
+ THIS_TAG_DEBUG (
+ sprintf ("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 =
2341:
this->do_process) &&
!arrayp (do_process)) {
if (!exec) {
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Calling do_process in "
+ "streaming mode\n", debug_iter));
exec = do_process (id, piece); // Might unwind.
-
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: %s returned from "
+ "do_process\n", debug_iter,
+ exec ? "Exec array" : "Zero"));
if (ctx->new_runtime_tags)
_handle_runtime_tags (ctx, parser);
}
-
+
if (exec) {
-
+ THIS_TAG_DEBUG_ENTER_SCOPE (
+ ctx, this, sprintf ("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 (!zero_type (ctx->unwind_state->stream_piece))
2358:
if (result_type->encoding_type ?
result_type->encoding_type !=
parser->type->encoding_type :
- result_type != parser->type)
+ result_type != parser->type) {
+ THIS_TAG_DEBUG (
+ sprintf ("Iter[%d]: Converting result from %s to %s"
+ " of surrounding content\n", debug_iter,
+ result_type->name, parser->type->name));
res = parser->type->encode (res, result_type);
-
+ }
ctx->unwind_state->stream_piece = res;
-
+ THIS_TAG_DEBUG (
+ sprintf ("Iter[%d]: Streaming %t from "
+ "do_process\n", debug_iter, res));
throw (this);
}
-
+
exec = 0;
}
else if (flags & FLAG_STREAM_RESULT) {
- // do_process() finished the stream.
- // Ignore remaining content.
+ THIS_TAG_DEBUG (
+ sprintf ("Iter[%d]: do_process finished the stream; "
+ "ignoring remaining content\n", debug_iter));
ctx->unwind_state = 0;
piece = nil;
break;
2375:
}
piece = nil;
}
+
if (finished) break;
}
else { // The frame doesn't handle streamed content.
piece = nil;
if (finished) {
mixed res = subparser->eval(); // Might unwind.
- if (content_type->sequential) content += res;
- else if (res != nil) content = res;
+ if (content_type->sequential) {
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Adding %t to content\n",
+ debug_iter, res));
+ content += res;
+ }
+ else if (res != nil) {
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Setting content to %t\n",
+ debug_iter, res));
+ content = res;
+ }
break;
}
}
2396:
if (array|function(RequestID,void|mixed:array) do_process =
[array|function(RequestID,void|mixed:array)] this->do_process) {
if (!exec) {
- exec = arrayp (do_process) ? [array] do_process :
- ([function(RequestID,void|mixed:array)] do_process) (
+ if (arrayp (do_process)) {
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Getting exec array from "
+ "do_process\n", debug_iter));
+ exec = [array] do_process;
+ }
+ else {
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Calling do_process\n",
+ debug_iter));
+ exec = ([function(RequestID,void|mixed:array)] do_process) (
id); // Might unwind.
-
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: %s returned from do_process\n",
+ debug_iter, exec ? "Exec array" : "Zero"));
+ }
if (ctx->new_runtime_tags)
_handle_runtime_tags (ctx, parser);
}
-
+
if (exec) {
-
+ THIS_TAG_DEBUG_ENTER_SCOPE (
+ ctx, this, sprintf ("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)
2417:
#endif
if (result_type->encoding_type ?
result_type->encoding_type != parser->type->encoding_type :
- result_type != parser->type)
+ result_type != parser->type) {
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Converting result from "
+ "type %s to type %s of surrounding "
+ "content\n", debug_iter,
+ result_type->name, parser->type->name));
res = parser->type->encode (res, result_type);
-
+ }
ctx->unwind_state = (["stream_piece": res]);
-
+ THIS_TAG_DEBUG (sprintf ("Iter[%d]: Streaming %t from "
+ "do_process\n", debug_iter, res));
throw (this);
}
-
+
exec = 0;
}
}
2435:
[array|function(RequestID:array)] this->do_return) {
eval_state = EVSTAT_ITER_DONE; // Only need to record this state here.
if (!exec) {
- exec = arrayp (do_return) ? [array] do_return :
- ([function(RequestID:array)] do_return) (id); // Might unwind.
+ 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");
+ exec = ([function(RequestID:array)] do_return) (id); // Might unwind.
+ THIS_TAG_DEBUG ((exec ? "Exec array" : "Zero") +
+ " returned from do_return\n");
+ }
if (ctx->new_runtime_tags)
_handle_runtime_tags (ctx, parser);
}
-
+
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.
exec = 0;
}
}
- else if (result == nil && !(flags & FLAG_EMPTY_ELEMENT))
+
+ else if (result == nil && !(flags & FLAG_EMPTY_ELEMENT)) {
if (result_type->_parser_prog == PNone) {
- if (content_type->subtype_of (result_type))
+ if (content_type->encoding_type ?
+ content_type->encoding_type != result_type->encoding_type :
+ content_type != result_type) {
+ THIS_TAG_DEBUG (sprintf ("Assigning content to result after "
+ "converting from %s to %s\n",
+ content_type->name, result_type->name));
+ result = result_type->encode (content, content_type);
+ }
+ else {
+ THIS_TAG_DEBUG ("Assigning content to result\n");
result = content;
}
-
+ }
else
- if (stringp (content_type)) {
+ if (stringp (content)) {
eval_state = EVSTAT_ITER_DONE; // Only need to record this state here.
- if (!exec) exec = ({content});
+ 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 = 0;
}
-
+ }
+ else {
+ #ifdef DEBUG
+ if (!(flags & FLAG_EMPTY_ELEMENT))
+ THIS_TAG_DEBUG ("Skipping nil result\n");
+ #endif
+ }
+
+ THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this, "Leaving scope\n");
LEAVE_SCOPE (ctx, this);
}
2468:
ctx->frame_depth--;
if (err) {
+ THIS_TAG_DEBUG_LEAVE_SCOPE (ctx, this, "Leaving scope\n");
LEAVE_SCOPE (ctx, this);
string action;
if (objectp (err) && ([object] err)->thrown_at_unwind) {
2492:
if (err == this) err = 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");
}
else {
// Can't stream since the parser isn't unwind safe. Just
// continue.
m_delete (ustate, "stream_piece");
action = "continue";
-
+ THIS_TAG_TOP_DEBUG ("Interrupted for streaming - "
+ "continuing since parser isn't unwind safe\n");
}
else if (!zero_type (ustate->stream_piece)) {
// Got a stream piece from a subframe. We handle it above;
2506:
m_delete (ustate, "stream_piece");
action = "continue";
}
- else action = "break"; // Some other reason - back up to the top.
+ else {
+ action = "break"; // Some other reason - back up to the top.
+ THIS_TAG_TOP_DEBUG ("Interrupted\n");
+ }
ustate[this] = ({err, eval_state, iter, raw_content, subparser, piece,
- exec, orig_tag_set, ctx->new_runtime_tags});
+ exec, orig_tag_set, ctx->new_runtime_tags,
+ #ifdef DEBUG
+ debug_iter,
+ #endif
+ });
TRACE_LEAVE (action);
}
else {
-
+ THIS_TAG_TOP_DEBUG ("Exception\n");
TRACE_LEAVE ("exception");
ctx->handle_exception (err, parser); // Will rethrow unknown errors.
result = nil;
2535:
fatal_error ("Internal error: Don't you come here and %O on me!\n", action);
}
}
- else
+ else {
+ THIS_TAG_TOP_DEBUG ("Done\n");
TRACE_LEAVE ("");
-
+ }
} while (0); // Breaks go here.
if (orig_tag_set) ctx->tag_set = orig_tag_set;
2620:
throw (err);
}
+ local void tag_debug (string msg, mixed... args)
+ //! Writes the message to the debug log if the innermost tag being
+ //! executed has FLAG_DEBUG set.
+ {
+ if (Frame f = get_context()->frame) // It's intentional that this assumes a context.
+ if (f->flags & FLAG_DEBUG)
+ werror (msg, @args);
+ }
+
Frame make_tag (string name, mapping(string:mixed) args, void|mixed content,
void|Tag overridden_by)
//! Returns a frame for the specified tag, or 0 if no such tag exists.
2668:
content = to_parse;
}
- string _sprintf() {return sprintf ("parse_frame(%O)", content_type);}
+ string _sprintf() {return sprintf ("RXML.parse_frame(%O)", content_type);}
}
2903:
string _sprintf()
{
- return sprintf ("RXML.Parser(%O,%O)%s", context, type, OBJ_COUNT);
+ return sprintf ("RXML.Parser(%O)%s", type, OBJ_COUNT);
}
}
2970:
string _sprintf()
{
- return sprintf ("RXML.TagSetParser(%O,%O,%O)%s", context, type, tag_set, OBJ_COUNT);
+ return sprintf ("RXML.TagSetParser(%O,%O)%s", type, tag_set, OBJ_COUNT);
}
}
3400:
static class TText
{
inherit Type;
- constant name = "text/*";
+ constant name = "text/plain";
constant sequential = 1;
constant empty_value = "";
constant free_text = 1;