Branch: Tag:

2000-10-19

2000-10-19 01:51:10 by Martin Stjernholm <mast@lysator.liu.se>

Fixed design flaw in error handling: Errors now abort execution up to
the level where the rxml backtrace is reported. (Previously the error
was just reported on that level, while execution resumed right after
the tag or entity reference that failed.) This changes the behavior of
FLAG_DONT_REPORT_ERRORS, which now have the preferred name
FLAG_DONT_RECOVER. Fixes [bug 442 (#442)].

Rev: server/etc/modules/RXML.pmod/module.pmod:1.118

2:   //!   //! Created 1999-07-30 by Martin Stjernholm.   //! - //! $Id: module.pmod,v 1.117 2000/10/17 23:02:30 mast Exp $ + //! $Id: module.pmod,v 1.118 2000/10/19 01:51:10 mast Exp $      //! Kludge: Must use "RXML.refs" somewhere for the whole module to be   //! loaded correctly.
1172:    {    error_count++;    if (objectp (err) && err->is_RXML_Backtrace) { +  evaluator->error_count++; +  if (evaluator->report_error && evaluator->recover_errors && +  evaluator->type->free_text) {    string msg; -  for (object(PCode)|object(Parser) e = evaluator->_parent; e; e = e->_parent) -  e->error_count++; +     if (id && id->conf) -  while (evaluator) { -  object(PCode)|object(Parser) reporter = 0; -  for (; evaluator; evaluator = evaluator->_parent) -  if (evaluator->report_error && evaluator->type->free_text) -  if (evaluator->disable_report_error) reporter = 0; -  else if (!reporter) reporter = evaluator; -  if (reporter) { -  string msg = err->type == "help" ? err->msg : +  msg = err->type == "help" ? err->msg :    (err->type == "run" ?    ([function(Backtrace,Type:string)]    ([object] id->conf)->handle_run_error) :    ([function(Backtrace,Type:string)]    ([object] id->conf)->handle_parse_error) -  ) ([object(Backtrace)] err, reporter->type); -  if (reporter->report_error (msg)) -  break; +  ) ([object(Backtrace)] err, evaluator->type); +  else +  msg = err->msg; +  if (evaluator->report_error (msg)) +  return;    } -  evaluator = reporter->_parent; +  throw (err);    } -  else { - #ifdef MODULE_DEBUG -  report_notice (describe_backtrace (err)); - #else -  report_notice (err->msg); - #endif -  } -  } +     else throw_fatal (err);    }   
1567:   //! never be set in Tag.flags, but it's useful when creating frames   //! directly.    - constant FLAG_DONT_REPORT_ERRORS = 0x00002000; - //! This flag avoids RXML errors which occurs when parsing the content - //! in the tag to be reported in it, instead the error report will be - //! propagated to the parent tag. + constant FLAG_DONT_RECOVER = 0x00002000; + //! If set, RXML errors are never recovered when parsing the content + //! in the tag. If any occurs, it will instead abort the execution of + //! this tag too to propagate the error to the parent tag.   //! - //! When an error occurs, the parser searches upward in the frame + //! When an error occurs, the parser aborts tags upward in the frame   //! stack until it comes to one which looks like it can accept an - //! error report in its content. + //! error report in its content. The parser then reports the error + //! there and continues.   //! - //! The criteria for the frame which will get the error report is that - //! its content type has the free_text property, and that the parser - //! that parses it has an report_error function (which e.g. RXML.PXml - //! has). With this flag, a frame can declare that it isn't suitable - //! to receive error reports even if it satisfies this. + //! The criteria for the frame which will handle the error recovery is + //! that its content type has the free_text property, and that the + //! parser that parses it has an report_error function (which e.g. + //! RXML.PXml has). With this flag, a frame can declare that it isn't + //! suitable to receive error reports even if it satisfies this.    -  + constant FLAG_DONT_REPORT_ERRORS = FLAG_DONT_RECOVER; // For compatibility. +    constant FLAG_RAW_ARGS = 0x00004000;   //! Special flag to TXml.format_tag(); only defined here as a   //! placeholder. When this is given to TXml.format_tag(), it only
2014:    }    else {    subparser = result_type->get_parser (ctx, 0, parser); -  if (flags & FLAG_DONT_REPORT_ERRORS) -  subparser->disable_report_error = 1; +  if (parser->recover_errors && !(flags & FLAG_DONT_RECOVER)) +  subparser->recover_errors = 1;    THIS_TAG_DEBUG (sprintf ("Exec[%d]: Parsing string with %O\n",    i, subparser));    subparser->finish ([string] elem); // Might unwind.
2498:    "with %O\n", debug_iter, subparser));   #endif    } -  if (flags & FLAG_DONT_REPORT_ERRORS) -  subparser->disable_report_error = 1; +  if (parser->recover_errors && !(flags & FLAG_DONT_RECOVER)) +  subparser->recover_errors = 1;    subparser->finish (raw_content); // Might unwind.    finished = 1;    }
3111:    //! it should be able to call that function again with identical    //! arguments the next time it continues.    -  int disable_report_error; -  //! Set to nonzero to avoid reporting errors in this parser. I.e. -  //! report_error() will never be called if this is nonzero. +  int recover_errors; +  //! Set to nonzero to allow error recovery in this parser. +  //! report_error() will never be called if this is zero.       mixed feed (string in);    //! Feeds some source data to the parse stream. The parser may do
3129:    optional int report_error (string msg);    //! Used to report errors to the end user through the output. This    //! is only called when type->free_text is nonzero and -  //! disable_report_error is zero. msg should be stored in the output +  //! recover_errors is nonzero. msg should be stored in the output    //! queue to be returned by eval(). If the context is bad for an -  //! error message, do nothing and return zero. Return nonzero if a -  //! message was written. +  //! error message, do nothing and return zero. The parser will then +  //! be aborted and the error will be propagated instead. Return +  //! nonzero if a message was written.       optional mixed read();    //! Define to allow streaming operation. Returns the evaluated
3574:    else p->write_end (in);    res = p->eval();    if (p->reset) { -  p->context = p->disable_report_error = p->_parent = 0; +  p->context = p->recover_errors = p->_parent = 0;   #ifdef RXML_OBJ_DEBUG    p->__object_marker->create (p);   #endif