Branch: Tag:

2000-02-15

2000-02-15 01:17:52 by Martin Stjernholm <mast@lysator.liu.se>

Fixed bugs in runtime tags.

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

2:   //!   //! Created 1999-07-30 by Martin Stjernholm.   //! - //! $Id: module.pmod,v 1.54 2000/02/13 18:25:56 mast Exp $ + //! $Id: module.pmod,v 1.55 2000/02/15 01:17:52 mast Exp $      //! Kludge: Must use "RXML.refs" somewhere for the whole module to be   //! loaded correctly.
832:       void add_runtime_tag (Tag tag)    //! Adds a tag that will exist from this point forward in the -  //! current context only. It will have effect in the current parser -  //! and parent parsers up to the point where tag_set changes. +  //! current context only.    { -  if (!new_runtime_tags) new_runtime_tags = RuntimeTags(); +  if (!new_runtime_tags) new_runtime_tags = NewRuntimeTags();    new_runtime_tags->add_tags[tag] = 1;    // By doing the following, we can let remove_tags take precedence.    new_runtime_tags->remove_tags[tag] = 0;
843:    }       void remove_runtime_tag (string|Tag tag) -  //! Removes a tag added by add_runtime_tag(). It will have effect in -  //! the current parser and parent parsers up to the point where -  //! tag_set changes. +  //! Removes a tag added by add_runtime_tag().    { -  if (!new_runtime_tags) new_runtime_tags = RuntimeTags(); +  if (!new_runtime_tags) new_runtime_tags = NewRuntimeTags();    new_runtime_tags->remove_tags[tag] = 1;    }    -  +  array(Tag) get_runtime_tags() +  //! Returns all currently active runtime tags. +  { +  array(Tag) tags = runtime_tags; +  if (new_runtime_tags) { +  tags |= indices (new_runtime_tags->add_tags); +  tags -= indices (new_runtime_tags->remove_tags); +  } +  return tags; +  } +     void handle_exception (mixed err, PCode|Parser evaluator)    //! This function gets any exception that is catched during    //! evaluation. evaluator is the object that catched the error.
955:    }    }    -  class RuntimeTags +  array(Tag) runtime_tags = ({}); +  +  class NewRuntimeTags    {    multiset(Tag) add_tags = (<>);    multiset(Tag|string) remove_tags = (<>);    } -  RuntimeTags new_runtime_tags; +  NewRuntimeTags new_runtime_tags;    // Used to record the result of any add_runtime_tag() and    // remove_runtime_tag() calls since the last time the parsers ran.   
1003:    constant is_generic_error = 1;    constant is_RXML_Backtrace = 1;    -  string type; // Currently "run", "parse" or "fatal". +  string type; // Currently "run" or "parse".    string msg;    Context context;    Frame frame;
1445:    if (result_type->_parser_prog == PNone)    piece = elem;    else { -  subparser = result_type->get_parser (ctx); -  subparser->_parent = parser; +  subparser = result_type->get_parser (ctx, 0, parser);    subparser->finish ([string] elem); // Might unwind.    piece = subparser->eval(); // Might unwind.    subparser = 0;
1513:    throw_fatal (err);    }    -  private void _handle_runtime_tags (TagSetParser parser, -  Context.RuntimeTags runtime_tags) +  private void _handle_runtime_tags (Context ctx, TagSetParser parser)    {    // FIXME: PCode handling. -  multiset(string|Tag) rem_tags = runtime_tags->remove_tags; -  multiset(Tag) add_tags = runtime_tags->add_tags - rem_tags; +  multiset(string|Tag) rem_tags = ctx->new_runtime_tags->remove_tags; +  multiset(Tag) add_tags = ctx->new_runtime_tags->add_tags - rem_tags;    if (sizeof (rem_tags))    foreach (indices (add_tags), Tag tag)    if (rem_tags[tag->name]) add_tags[tag] = 0;
1531:    foreach (arr_rem_tags, string|object(Tag) tag)    ([object(TagSetParser)] p)->remove_runtime_tag (tag);    } +  ctx->runtime_tags |= add_tags; +  ctx->runtime_tags -= rem_tags; +  ctx->new_runtime_tags = 0;    }       void _eval (TagSetParser parser,
1688:    case EVSTAT_BEGIN:    if (array|function(RequestID,void|mixed:array) do_enter =    [array|function(RequestID,void|mixed:array)] this->do_enter) { -  if (!exec) exec = do_enter (ctx->id); // Might unwind. +  if (!exec) { +  exec = do_enter (ctx->id); // Might unwind. +  if (ctx->new_runtime_tags) +  _handle_runtime_tags (ctx, parser); +  }    if (exec) {    mixed res = _exec_array (parser, exec); // Might unwind.    if (flags & FLAG_STREAM_RESULT) {
1719:    iter = [int] do_iterate || 1;    eval_state = EVSTAT_LAST_ITER;    } -  else -  if (!(iter = (/*[function(RequestID:int)]HMM*/ do_iterate -  ) (ctx->id))) // Might unwind. -  eval_state = EVSTAT_LAST_ITER; +  else { +  iter = (/*[function(RequestID:int)]HMM*/ do_iterate) ( +  ctx->id); // Might unwind. +  if (ctx->new_runtime_tags) +  _handle_runtime_tags (ctx, parser); +  if (!iter) eval_state = EVSTAT_LAST_ITER;    } -  +  }    ENTER_SCOPE (ctx, this);    for (; iter > 0; iter--) {       if (raw_content) { // Got nested parsing to do. -  if (ctx->new_runtime_tags) { -  // Empty this first in case do_enter() set it. -  _handle_runtime_tags (parser, ctx->new_runtime_tags); -  ctx->new_runtime_tags = 0; -  } -  +     int finished = 0;    if (!subparser) { // The nested content is not yet parsed.    subparser = content_type->get_parser ( -  ctx, [object(TagSet)] this->local_tags); -  subparser->_parent = parser; +  ctx, [object(TagSet)] this->local_tags, parser);    subparser->finish (raw_content); // Might unwind.    finished = 1;    }
1756:    [array|function(RequestID,void|mixed:array)]    this->do_return) &&    functionp (do_return)) { -  if (!exec) exec = do_return (ctx->id, piece); // Might unwind. +  if (!exec) { +  exec = do_return (ctx->id, piece); // Might unwind. +  if (ctx->new_runtime_tags) +  _handle_runtime_tags (ctx, parser); +  }    if (exec) {    mixed res = _exec_array (parser, exec); // Might unwind.    if (flags & FLAG_STREAM_RESULT) {
1802:       if (array|function(RequestID,void|mixed:array) do_return =    [array|function(RequestID,void|mixed:array)] this->do_return) { -  if (!exec) +  if (!exec) {    exec = functionp (do_return) ?    ([function(RequestID,void|mixed:array)] do_return) (    ctx->id) : // Might unwind.    [array] do_return; -  +  if (ctx->new_runtime_tags) +  _handle_runtime_tags (ctx, parser); +  }    if (exec) {    mixed res = _exec_array (parser, exec); // Might unwind.    if (flags & FLAG_STREAM_RESULT) {
1846:    }    }    -  if (ctx->new_runtime_tags) { -  _handle_runtime_tags (parser, ctx->new_runtime_tags); -  ctx->new_runtime_tags = 0; -  } +  if (ctx->new_runtime_tags) +  _handle_runtime_tags (ctx, parser);    };       if (err) {
2216:    optional Parser clone (Context ctx, Type type, mixed... args);    //! Define to create new parser objects by cloning instead of    //! creating from scratch. It returns a new instance of this parser -  //! with the same static configuration, i.e. the type. The instance -  //! this function is called in is never actually used for parsing. +  //! with the same static configuration, i.e. the type and tag set +  //! (when used in TagSetParser).       static void create (Context ctx, Type _type, mixed... args)    {
2461:    return newtype;    }    -  inline Parser get_parser (Context ctx, void|TagSet tag_set) +  inline Parser get_parser (Context ctx, void|TagSet tag_set, void|Parser|PCode parent)    //! Returns a parser instance initialized with the given context.    {    Parser p;    if (_p_cache) { // It's a tag set parser. -  TagSet tset; +  TagSet tset = tag_set || ctx->tag_set; +  +  if (parent && parent->is_RXML_Parser && +  tset == ctx->tag_set && sizeof (ctx->runtime_tags) && +  parent->clone && parent->type == this_object()) { +  // There are runtime tags. Try to clone the parent parser if +  // all conditions are met. +  p = parent->clone (ctx, this_object(), tset, @_parser_args); +  p->_parent = parent; +  return p; +  } +     // vvv Using interpreter lock from here. -  PCacheObj pco = _p_cache[tset = tag_set || ctx->tag_set]; +  PCacheObj pco = _p_cache[tset];    if (pco && pco->tag_set_gen == tset->generation) {    if ((p = pco->free_parser)) {    pco->free_parser = p->_next_free;
2476:    p->data_callback = p->compile = 0;    p->reset (ctx, this_object(), tset, @_parser_args);    } +     else    // ^^^ Using interpreter lock to here.    if (pco->clone_parser)
2485:    // to race, but that doesn't matter.    p = (pco->clone_parser = p)->clone (ctx, this_object(), tset, @_parser_args);    } +     else {    // ^^^ Using interpreter lock to here.    pco = PCacheObj();
2495:    // to race, but that doesn't matter.    p = (pco->clone_parser = p)->clone (ctx, this_object(), tset, @_parser_args);    } +  +  if (ctx->tag_set == tset) +  foreach (ctx->runtime_tags, Tag tag) +  p->add_runtime_tag (tag);    } -  +     else {    if ((p = free_parser)) {    // Relying on interpreter lock here.
2503:    p->data_callback = p->compile = 0;    p->reset (ctx, this_object(), @_parser_args);    } +     else if (clone_parser)    // Relying on interpreter lock here.    p = clone_parser->clone (ctx, this_object(), @_parser_args); -  +     else if ((p = _parser_prog (0, this_object(), @_parser_args))->clone)    // clone_parser might already be initialized here due to race,    // but that doesn't matter.    p = (clone_parser = p)->clone (ctx, this_object(), @_parser_args);    } -  +  +  p->_parent = parent;    return p;    }   
2525:    if (!ctx) ctx = get_context();    if (_parser_prog == PNone) res = in;    else { -  Parser p = get_parser (ctx, tag_set); +  Parser p = get_parser (ctx, tag_set, parent);    p->_parent = parent;    if (dont_switch_ctx) p->finish (in); // Optimize the job in p->write_end().    else p->write_end (in);