Branch: Tag:

2001-07-24

2001-07-24 22:35:41 by Martin Stjernholm <mast@lysator.liu.se>

Extended the variable change tracking in compiled results to
delete_var, add_scope, extend_scope and remove_scope. A couple of
other cleanups.

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

2:   //   // Created 1999-07-30 by Martin Stjernholm.   // - // $Id: module.pmod,v 1.210 2001/07/21 14:23:24 mast Exp $ + // $Id: module.pmod,v 1.211 2001/07/24 22:35:41 mast Exp $      // Kludge: Must use "RXML.refs" somewhere for the whole module to be   // loaded correctly.
508:    Parser parser = t->get_parser (ctx, ctx->tag_set, 0);    TAG_DEBUG (RXML_CONTEXT->frame,    "Evaluating argument value %s with %O\n", -  utils->format_short (raw_args[arg]), parser); +  format_short (raw_args[arg]), parser);    parser->finish (raw_args[arg]); // Should not unwind.    raw_args[arg] = parser->eval(); // Should not unwind.    TAG_DEBUG (RXML_CONTEXT->frame,    "Setting dynamic argument %s to %s\n", -  utils->format_short (arg), -  utils->format_short (raw_args[arg])); +  format_short (arg), +  format_short (raw_args[arg]));    t->give_back (parser, ctx->tag_set);    }    }
1440:    vars = rxml_index (vars, path, scope_name, this_object());    scope_name += "." + (array(string)) path * ".";    if (mapping(string:mixed) var_chg = misc->variable_changes) -  var_chg[encode_value_canonic (({scope_name}) + var, val)] = val; +  var_chg[encode_value_canonic (({scope_name}) + var)] = val;    }    else {    index = var[0];
1467:    else    return vars[index - 1] = val;    else -  parse_error( "Cannot index the array in %s with %O.\n", scope_name, index ); +  parse_error( "Cannot index the array in %s with %s.\n", +  scope_name, format_short (index) );    else -  parse_error ("%s is %O which cannot be indexed with %O.\n", -  scope_name, vars, index); +  parse_error ("%s is %s which cannot be indexed with %s.\n", +  scope_name, format_short (vars), format_short (index));    }       else if (scope_name == "_") parse_error ("No current scope.\n");
1509:    if (SCOPE_TYPE vars = scopes[scope_name]) {    if (arrayp (var))    if (sizeof (var) > 1) { -  string|int last = var[-1]; -  var = var[..sizeof (var) - 1]; -  vars = rxml_index (vars, var, scope_name, this_object()); -  scope_name += "." + (array(string)) var * "."; -  var = last; +  array(string|int) path = var[..sizeof (var) - 1]; +  vars = rxml_index (vars, path, scope_name, this_object()); +  scope_name += "." + (array(string)) path * "."; +  if (mapping(string:mixed) var_chg = misc->variable_changes) +  var_chg[encode_value_canonic (({scope_name}) + var)] = nil; +  var = var[-1];    } -  else var = var[0]; +  else { +  var = var[0]; +  if (mapping(string:mixed) var_chg = misc->variable_changes) +  var_chg[encode_value_canonic (({scope_name, var}))] = nil; +  } +  else { +  if (mapping(string:mixed) var_chg = misc->variable_changes) +  var_chg[encode_value_canonic (({scope_name, var}))] = nil; +  }       if (objectp (vars) && vars->_m_delete)    ([object(Scope)] vars)->_m_delete (var, this_object(), scope_name);
1524:    else if (multisetp (vars))    vars[var] = 0;    else -  parse_error ("Cannot remove the index %O from the %t in %s.\n", -  var, vars, scope_name); +  parse_error ("Cannot remove the index %s from the %t in %s.\n", +  format_short (var), vars, scope_name);    }       else if (scope_name == "_") parse_error ("No current scope.\n");
1577:    //! Adds or replaces the specified scope at the global level. A    //! scope can be a mapping or an @[RXML.Scope] object. A global    //! @tt{"_"@} scope may also be defined this way. -  //! -  //! @note -  //! Does not track variable changes for caching purposes like -  //! @[set_var] does. +     {    if (scopes[scope_name])    if (scope_name == "_") {
1598:    else scopes[scope_name] = vars;    }    else scopes[scope_name] = vars; +  +  if (mapping(string:mixed) var_chg = misc->variable_changes) { +  foreach (indices (var_chg), string encoded_var) { +  array var = decode_value (encoded_var); +  if (var[0] == scope_name) m_delete (var_chg, encoded_var);    } -  +  var_chg[encode_value_canonic (({scope_name}))] = +  mappingp (vars) ? vars + ([]) : vars; +  } +  }    -  int extend_scope (string scope_name, SCOPE_TYPE vars) +  void extend_scope (string scope_name, SCOPE_TYPE vars)    //! Adds or extends the specified scope at the global level. -  //! Returns 1 on success and 0 on failure. -  //! -  //! @note -  //! Does not track variable changes for caching purposes like -  //! @[set_var] does. +     {    if (scopes[scope_name]) {    SCOPE_TYPE oldvars;
1627: Inside #if defined(DEBUG)
  #ifdef DEBUG    if (!oldvars) fatal_error ("I before e except after c.\n");   #endif -  if (!mappingp(vars)) { -  return 0; -  } +     foreach (indices(vars), string var)    set_var(var, vars[var], scope_name);    } -  else scopes[scope_name] = vars; -  return 1; +  +  else { +  scopes[scope_name] = vars; +  +  if (mapping(string:mixed) var_chg = misc->variable_changes) { +  foreach (indices (var_chg), string encoded_var) { +  array var = decode_value (encoded_var); +  if (var[0] == scope_name) m_delete (var_chg, encoded_var);    } -  +  var_chg[encode_value_canonic (({scope_name}))] = +  mappingp (vars) ? vars + ([]) : vars; +  } +  } +  }       void remove_scope (string scope_name)    //! Removes the named scope from the global level, if it exists. -  //! -  //! @note -  //! Does not track variable changes for caching purposes like -  //! @[set_var] does. +     {   #ifdef MODULE_DEBUG    if (scope_name == "_") fatal_error ("Cannot remove current scope.\n");
1652:    if (f->scope_name == scope_name) outermost = f;    if (outermost) m_delete (hidden, outermost);    else m_delete (scopes, scope_name); +  +  if (mapping(string:mixed) var_chg = misc->variable_changes) { +  foreach (indices (var_chg), string encoded_var) { +  array var = decode_value (encoded_var); +  if (var[0] == scope_name) m_delete (var_chg, encoded_var);    } -  +  var_chg[encode_value_canonic (({scope_name}))] = 0; +  } +  }       string current_scope()    //! Returns the name of the current scope, if it has any.
2841:      #define SET_SEQUENTIAL(from, to, desc) \    do { \ -  THIS_TAG_DEBUG ("Adding %s to " desc "\n", \ -  utils->format_short (from)); \ +  THIS_TAG_DEBUG ("Adding %s to " desc "\n", format_short (from)); \    /* Keep only one ref to to to allow destructive change. */ \    to = to + (to = 0, from); \    } while (0)
2853:    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)); \ +  " of type %s.\n", format_short (from), to_type->name); \ +  THIS_TAG_DEBUG ("Setting " desc " to %s\n", format_short (from)); \    to = from; \    } \    } while (0)
2895:    switch (sprintf ("%t", elem)) {    case "string":    if (result_type->parser_prog == PNone) { -  THIS_TAG_DEBUG ("Exec[%d]: String %s\n", i, utils->format_short (elem)); +  THIS_TAG_DEBUG ("Exec[%d]: String %s\n", i, format_short (elem));    piece = elem;    }    else {
2912:    }    THIS_TAG_DEBUG ("Exec[%d]: Parsing%s string %s with %O\n", i,    p_code ? " and compiling" : "", -  utils->format_short (elem), subparser); +  format_short (elem), subparser);    }    subparser->finish ([string] elem); // Might unwind.    piece = subparser->eval(); // Might unwind.
2935:    case "multiset":    if (sizeof ([multiset] elem) == 1) {    piece = ((array) elem)[0]; -  THIS_TAG_DEBUG ("Exec[%d]: Verbatim value %s\n", i, -  utils->format_short (piece)); +  THIS_TAG_DEBUG ("Exec[%d]: Verbatim value %s\n", i, format_short (piece));    }    else    _exec_array_fatal (where, i, elem,
3097:    ctx->unwind_state = (["stream_piece": res, \    "reason": "streaming"]); \    THIS_TAG_DEBUG ("Streaming %s from " #cb "\n", \ -  utils->format_short (res)); \ +  format_short (res)); \    throw (this_object()); \    } \    exec = 0; \
3169:    Parser parser = splice_arg_type->get_parser (ctx, ctx->tag_set, 0,    sub_p_code);    THIS_TAG_DEBUG ("Evaluating splice argument %s\n", -  utils->format_short (splice_arg)); +  format_short (splice_arg));   #ifdef MODULE_DEBUG    if (mixed err = catch {   #endif
3209:    Parser parser = t->get_parser (ctx, ctx_tag_set, 0, sub_p_code);    THIS_TAG_DEBUG ("Evaluating and compiling "    "argument value %s with %O\n", -  utils->format_short (raw_args[arg]), parser); +  format_short (raw_args[arg]), parser);    parser->finish (raw_args[arg]); // Should not unwind.    args[arg] = parser->eval(); // Should not unwind.    THIS_TAG_DEBUG ("Setting argument %s to %s\n", -  utils->format_short (arg), -  utils->format_short (args[arg])); +  format_short (arg), format_short (args[arg]));    fn_text_add (sprintf ("%O: %s,\n", arg,    sub_p_code->compile_text (comp)));    t->give_back (parser, ctx_tag_set);
3230:    if (t->parser_prog != PNone) {    Parser parser = t->get_parser (ctx, ctx_tag_set, 0, 0);    THIS_TAG_DEBUG ("Evaluating argument value %s with %O\n", -  utils->format_short (raw_args[arg]), parser); +  format_short (raw_args[arg]), parser);    parser->finish (raw_args[arg]); // Should not unwind.    args[arg] = parser->eval(); // Should not unwind.    THIS_TAG_DEBUG ("Setting argument %s to %s\n", -  utils->format_short (arg), -  utils->format_short (args[arg])); +  format_short (arg), format_short (args[arg]));    t->give_back (parser, ctx_tag_set);    }    else
3306:    if (content_type == t_same) {    content_type =    result_type (content_type->parser_prog, @content_type->parser_args); -  THIS_TAG_DEBUG ("Resolved t_same to content_type %O\n", content_type); +  THIS_TAG_DEBUG ("Resolved t_same to content_type %s\n", +  content_type->name);    } -  else THIS_TAG_DEBUG ("Setting content_type to %O from tag\n", content_type); +  else THIS_TAG_DEBUG ("Setting content_type to %s from tag\n", +  content_type->name);    } -  else THIS_TAG_DEBUG ("Keeping content_type %O\n", content_type); +  else THIS_TAG_DEBUG ("Keeping content_type %s\n", content_type->name);       return func;    };
3565:    ctx->make_p_code ? " and compiling" : "",    flags & FLAG_GET_EVALED_CONTENT ?    " and result compiling" : "", -  utils->format_short (in_content), subevaler); +  format_short (in_content), subevaler);    }    else {    subevaler = content_type->get_parser (
3575:    ctx->make_p_code ? " and compiling" : "",    flags & FLAG_GET_EVALED_CONTENT ?    " and result compiling" : "", -  utils->format_short (in_content), subevaler, +  format_short (in_content), subevaler,    this_object()->additional_tags ?    " from additional_tags" : "");    }
3609:    // Handle a stream piece.    THIS_TAG_DEBUG ("Iter[%d]: Got %s stream piece %s\n",    debug_iter, finished ? "ending" : "a", -  utils->format_short (piece)); +  format_short (piece));    if (!arrayp (do_process)) {    EXEC_CALLBACK (ctx, evaler, exec, do_process, id, piece);    if (exec) {
3624:    ctx->unwind_state->stream_piece = res;    ctx->unwind_state->reason = "streaming";    THIS_TAG_DEBUG ("Iter[%d]: Streaming %s from do_process\n", -  debug_iter, utils->format_short (res)); +  debug_iter, format_short (res));    throw (this_object());    }    exec = 0;
4022:    else    val = val[index-1];    else -  parse_error( "Cannot index the array in %s with %O.\n", scope_name, index ); +  parse_error( "Cannot index the array in %s with %s.\n", +  scope_name, format_short (index) );    else if (val == nil) -  parse_error ("%s produced no value to index with %O.\n", scope_name, index); +  parse_error ("%s produced no value to index with %s.\n", +  scope_name, format_short (index));    else if( objectp( val ) && val->`[] ) {   #ifdef MODULE_DEBUG    Scope scope = [object(Scope)] val;
4051:    if (!val[index]) val = nil;    }    else if (!(<1, -1>)[index]) -  parse_error ("%s is %O which cannot be indexed with %O.\n", -  scope_name, val, index); +  parse_error ("%s is %s which cannot be indexed with %s.\n", +  scope_name, format_short (val), format_short (index));       if (i == sizeof (idxpath)) break;    scope_name += "." + index;
4069: 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]) -  fatal_error ("Cyclic rxml_var_eval chain detected in %O.\n" -  "All called objects:%{ %O%}\n", val, indices (called)); +  fatal_error ("Cyclic rxml_var_eval chain detected in %s.\n" +  "All called objects:%{ %O%}\n", +  format_short (val), indices (called));    called[val] = 1;   #endif    if (zero_type (val = ([object(Value)] val)->rxml_var_eval (
4097: Inside #if defined(MODULE_DEBUG)
   do {   #ifdef MODULE_DEBUG    if (called[val]) -  fatal_error ("Cyclic rxml_var_eval chain detected in %O.\n" -  "All called objects:%{ %O%}\n", val, indices (called)); +  fatal_error ("Cyclic rxml_var_eval chain detected in %s.\n" +  "All called objects:%{ %O%}\n", +  format_short (val), indices (called));    called[val] = 1;    Value val_obj = [object(Value)] val;   #endif
4227:    //! Writes some source data to the parser. Returns nonzero if there    //! might be data available in eval().    { -  //werror ("%O write %s\n", this_object(), utils->format_short (in)); +  //werror ("%O write %s\n", this_object(), format_short (in));    int res;    ENTER_CONTEXT (context);    if (mixed err = catch {
4266:    //! Closes the source data stream, optionally with a last bit of    //! data.    { -  //werror ("%O write_end %s\n", this_object(), utils->format_short (in)); +  //werror ("%O write_end %s\n", this_object(), format_short (in));    int res;    ENTER_CONTEXT (context);    if (mixed err = catch {
4350: Inside #if defined(DEBUG)
  #ifdef DEBUG    if (TAG_DEBUG_TEST (context->frame))    TAG_DEBUG (context->frame, " Got value %s after conversion " -  "with encoding %s\n", utils->format_short (val), encoding); +  "with encoding %s\n", format_short (val), encoding);   #endif    }   #ifdef DEBUG    else    if (TAG_DEBUG_TEST (context->frame)) -  TAG_DEBUG (context->frame, " Got value %s\n", utils->format_short (val)); +  TAG_DEBUG (context->frame, " Got value %s\n", format_short (val));   #endif       }) {
5393:    }    if (stringp (val)) {    Type type = reg_types[val]; -  if (!type) parse_error ("There is no type %s.\n", utils->format_short (val)); +  if (!type) parse_error ("There is no type %s.\n", format_short (val));    return type;    }    mixed err = catch {return (object(Type)) val;};    parse_error ("Cannot convert %s to type: %s", -  utils->format_short (val), describe_error (err)); +  format_short (val), describe_error (err));    }       string _sprintf() {return "RXML.t_type" + OBJ_COUNT;}
5441:    }    if (!stringp (val) && !intp (val) && !floatp (val))    // Cannot unambigiously use a cast for this type. -  parse_error ("Cannot convert %s to scalar.\n", utils->format_short (val)); +  parse_error ("Cannot convert %s to scalar.\n", format_short (val));    return [string|int|float] val;    }   
5482:    if (sscanf (val, "%d%*c", int i) == 1) return i;    else if (sscanf (val, "%f%*c", float f) == 1) return f;    else parse_error ("%s cannot be parsed as neither integer nor float.\n", -  utils->format_short (val)); +  format_short (val));    if (!intp (val) && !floatp (val))    // Cannot unambigiously use a cast for this type. -  parse_error ("Cannot convert %s to number.\n", utils->format_short (val)); +  parse_error ("Cannot convert %s to number.\n", format_short (val));    return [int|float] val;    }   
5524:    }    if (stringp (val))    if (sscanf (val, "%d%*c", int i) == 1) return i; -  else parse_error ("%s cannot be parsed as integer.\n", utils->format_short (val)); +  else parse_error ("%s cannot be parsed as integer.\n", format_short (val));    mixed err = catch {return (int) val;};    parse_error ("Cannot convert %s to integer: %s", -  utils->format_short (val), describe_error (err)); +  format_short (val), describe_error (err));    }       string _sprintf() {return "RXML.t_int" + OBJ_COUNT;}
5565:    }    if (stringp (val))    if (sscanf (val, "%f%*c", float f) == 1) return f; -  else parse_error ("%s cannot be parsed as float.\n", utils->format_short (val)); +  else parse_error ("%s cannot be parsed as float.\n", format_short (val));    mixed err = catch {return (float) val;};    parse_error ("Cannot convert %s to float: %s", -  utils->format_short (val), describe_error (err)); +  format_short (val), describe_error (err));    }       string _sprintf() {return "RXML.t_float" + OBJ_COUNT;}
5621:    }    mixed err = catch {return (string) val;};    parse_error ("Cannot convert %s to %s: %s", -  utils->format_short (val), name, describe_error (err)); +  format_short (val), name, describe_error (err));    }       string lower_case (string val) {return predef::lower_case (val);}
5689:    }    mixed err = catch {return (string) val;};    parse_error ("Cannot convert %s to %s: %s", -  utils->format_short (val), name, describe_error (err)); +  format_short (val), name, describe_error (err));    }       string _sprintf() {return "RXML.t_text" + OBJ_COUNT;}
5724:    return _Roxen.html_encode_string( val );    } )    parse_error ("Cannot convert %s to %s: %s", -  utils->format_short (val), name, describe_error (err)); +  format_short (val), name, describe_error (err));    }       string decode (mixed val)
5911: Inside #if defined(DEBUG)
  #ifdef DEBUG    if (TAG_DEBUG_TEST (ctx->frame))    TAG_DEBUG (ctx->frame, " Got value %s after conversion " -  "with encoding %s\n", utils->format_short (val), encoding); +  "with encoding %s\n", format_short (val), encoding);   #endif    }       else   #ifdef DEBUG    if (TAG_DEBUG_TEST (ctx->frame)) -  TAG_DEBUG (ctx->frame, " Got value %s\n", utils->format_short (val)); +  TAG_DEBUG (ctx->frame, " Got value %s\n", format_short (val));   #endif       FRAME_DEPTH_MSG ("%*s%O frame_depth decrease line %d\n",
5959:    string _sprintf() {return "RXML.VarRef(" + name() + ")" + OBJ_COUNT;}   }    - class ScopeChange (static mapping(string:mixed) settings) + class VariableChange (static mapping(string:mixed) settings)   // A compiled-in change of some scope variables. Used when caching   // results.   { -  constant is_RXML_ScopeChange = 1; +  constant is_RXML_VariableChange = 1;    constant is_RXML_encodable = 1;    constant is_RXML_p_code_entry = 1;   
5971:    {    foreach (indices (settings), string encoded_var) {    array var = decode_value (encoded_var); +  if (sizeof (var) == 1) {   #ifdef DEBUG    if (TAG_DEBUG_TEST (ctx->frame)) -  +  TAG_DEBUG (ctx->frame, " Installing cached scope %s with %d variables\n", +  replace (var[0], ".", ".."), sizeof (settings[encoded_var])); + #endif +  if (SCOPE_TYPE vars = settings[encoded_var]) +  ctx->add_scope (var[0], settings[encoded_var]); +  else +  ctx->remove_scope (var[0]); +  } +  else { + #ifdef DEBUG +  if (TAG_DEBUG_TEST (ctx->frame))    TAG_DEBUG (ctx->frame, " Installing cached value for %s: %s\n",    map ((array(string)) var, replace, ".", "..") * ".", -  utils->format_short (settings[encoded_var])); +  format_short (settings[encoded_var]));   #endif -  ctx->set_var (var[1..], settings[encoded_var], var[0]); +  mixed val = settings[encoded_var]; +  if (val != nil) +  ctx->set_var (var[1..], val, var[0]); +  else +  ctx->delete_var (var[1..], var[0]);    } -  +  }    return nil;    }   
5986:    void _decode (mapping(string:mixed) saved) {settings = saved;}       MARK_OBJECT; -  string _sprintf() {return "RXML.ScopeChange" + OBJ_COUNT;} +  string _sprintf() {return "RXML.VariableChange" + OBJ_COUNT;}   }      class CompiledError
6346:    exec[length++] = evaled_value;    mapping(string:mixed) var_chg = ctx->misc->variable_changes;    if (sizeof (var_chg)) { -  exec[length++] = ScopeChange (var_chg); +  exec[length++] = VariableChange (var_chg);    ctx->misc->variable_changes = ([]);    }    }
6383:    exec[length++] = evaled_value;    mapping(string:mixed) var_chg = ctx->misc->variable_changes;    if (sizeof (var_chg)) { -  exec[length++] = ScopeChange (var_chg); +  exec[length++] = VariableChange (var_chg);    ctx->misc->variable_changes = ([]);    }    break add_frame;
6394: Inside #if defined(DEBUG)
  #ifdef DEBUG    if (!stringp (frame->args) && !functionp (frame->args) && !mappingp (frame->args))    error ("Invalid args %s in frame about to be added to p-code.\n", -  utils->format_short (frame->args)); +  format_short (frame->args));   #endif    exec[length + 1] = frame; // Cached for reuse.    array frame_state = exec[length + 2] = frame->_save();
6763:    mixed _v__ = (val); \    report_debug (" returned %s\n", \    zero_type (_v__) ? "([])[0]" : \ -  utils->format_short (_v__, 160)); \ +  format_short (_v__, 160)); \    return _v__; \   } while (0)   string _sprintf() {return "RXML.pmod";}
7104:    if (piece == nil) return value;    else if (value != nil)    parse_error ("Cannot append another value %s to non-sequential " -  "result of type %s.\n", utils->format_short (piece), type->name); +  "result of type %s.\n", format_short (piece), type->name);    else return piece;   }   
7271:    lambda (object/*(Parser.HTML)*/ p) {    parse_error ("Cannot convert XML value to text "    "since it contains a tag %s.\n", -  utils->format_short (p->current())); +  format_short (p->current()));    });    charref_decode_parser = p;   
7322:   static function(string,mixed...:void) _run_error = run_error;   static function(string,mixed...:void) _parse_error = parse_error;    + static function(mixed,void|int:string) format_short; +    // Argh!   static program PXml;   static program PEnt;
7348:    splice_arg_type = t_any_text (PEnt);    break;    case "PExpr": PExpr = [program] val; break; -  case "utils": utils = [object] val; break; +  case "utils": +  utils = [object] val; +  format_short = utils->format_short; +  break;    case "Roxen": Roxen = [object] val; init_parsers(); break;    case "empty_tag_set": empty_tag_set = [object(TagSet)] val; break;    default: error ("Herk\n");