Branch: Tag:

2003-03-24

2003-03-24 18:05:41 by Martin Stjernholm <mast@lysator.liu.se>

Added Context.add_p_code_callback to be able to execute arbitrary code
when result p-code is evaluated (necessary to fix the bug with the
<charset> tag). Also made some _sprintf's more robust.

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

2:   //   // Created 1999-07-30 by Martin Stjernholm.   // - // $Id: module.pmod,v 1.306 2003/01/20 12:37:31 mast Exp $ + // $Id: module.pmod,v 1.307 2003/03/24 18:05:41 mast Exp $      // Kludge: Must use "RXML.refs" somewhere for the whole module to be   // loaded correctly.
1985:    var_chg[encode_value_canonic (({2, index}))] = value;    }    +  static constant p_code_callback_id = encode_value_canonic (({3})); +  +  void add_p_code_callback (function|string callback, mixed... args) +  //! If result p-code is collected then a call to @[callback] with +  //! the given arguments is added to it, so that it will be called +  //! when the result p-code is reevaluated. +  //! +  //! If @[callback] is a string then it's taken to be the name of a +  //! function to call in the current @[id] object. The string can +  //! also contain "->" to build index chains. E.g. the string +  //! "misc->foo->bar" will cause a call to @[id]->misc->foo->bar() +  //! when the result p-code is evaluated. +  { +  if (mapping var_chg = misc->variable_changes) +  var_chg[p_code_callback_id] += ({callback, args}); +  } +     static int last_internal_var_id = 0;       string alloc_internal_var()
6113:    string _sprintf()    {    return "RXML.Type(" + this_object()->name + ", " + -  parser_prog->name + ")" + OBJ_COUNT;} +  (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      static class PCacheObj   {
6156:    return val;    }    -  string _sprintf() {return "RXML.t_any(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_any(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TNil t_nil = TNil();   //! A sequential type accepting only the value nil. This type is by
6192:       int subtype_of (Type other) {return 1;}    -  string _sprintf() {return "RXML.t_nil(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_nil(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TSame t_same = TSame();   //! A magic type used only in @[Tag.content_type].
6204:    constant name = "same";    Type supertype = t_any;    Type conversion_type = 0; -  string _sprintf() {return "RXML.t_same(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_same(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TType t_type = TType();   //! A type with the set of all RXML types as values.
6249:    format_short (val), describe_error (err));    }    -  string _sprintf() {return "RXML.t_type(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_type(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TParser t_parser = TParser();   //! A type with the set of all RXML parser programs as values.
6291:    format_short (val), describe_error (err));    }    -  string _sprintf() {return "RXML.t_parser(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_parser(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      // Basic types. Even though most of these have a `+ that fulfills   // requirements to make them sequential, we don't want all those to be
6335:    return [string|int|float] val;    }    -  string _sprintf() {return "RXML.t_scalar(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_scalar(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TNum t_num = TNum();   //! Type for any number, currently integer or float.
6379:    return [int|float] val;    }    -  string _sprintf() {return "RXML.t_num(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_num(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TInt t_int = TInt();   //! Type for integers.
6420:    format_short (val), describe_error (err));    }    -  string _sprintf() {return "RXML.t_int(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_int(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TFloat t_float = TFloat();   //! Type for floats.
6461:    format_short (val), describe_error (err));    }    -  string _sprintf() {return "RXML.t_float(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_float(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TString t_string = TString();   //! Type for strings. As opposed to @[RXML.t_any_text], this doesn't
6530:    string capitalize (string val) {return String.capitalize (val);}    //! Converts the first literal character in @[val] to uppercase.    -  string _sprintf() {return "RXML.t_string(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_string(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      // Text types:   
6561:    constant free_text = 1;    constant handle_literals = 0;    -  string _sprintf() {return "RXML.t_any_text(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_any_text(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TText t_text = TText();   //! The type for plain text. Note that this is not any (unspecified)
6589:    format_short (val), name, describe_error (err));    }    -  string _sprintf() {return "RXML.t_text(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_text(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      TXml t_xml = TXml();   //! The type for XML and similar markup.
6743:    return "&" + entity + ";";    }    -  string _sprintf() {return "RXML.t_xml(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_xml(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }      THtml t_html = THtml();   //! (Currently) identical to t_xml, but tags it as "text/html".
6765:       constant decode = 0; // Cover it; not needed here.    -  string _sprintf() {return "RXML.t_html(" + parser_prog->name + ")" + OBJ_COUNT;} +  string _sprintf() +  { +  return "RXML.t_html(" + (parser_prog && parser_prog->name) + ")" + OBJ_COUNT;    } -  + }         // P-code compilation and evaluation:
6942:    format_short (var), format_short (settings[encoded_var]));   #endif    ctx->set_root_id_misc (var[1], settings[encoded_var]); +  break; +  +  case 3: { +  // Generic callbacks. +  array cb_list = settings[encoded_var]; +  for (int i = 0; i < sizeof (cb_list); i += 2) { +  mixed cb = cb_list[i]; + #ifdef DEBUG +  if (TAG_DEBUG_TEST (ctx->frame)) +  TAG_DEBUG (ctx->frame, +  " Calling cached callback: %O (%s)\n", +  cb, map (cb_list[i + 1], format_short) * ", "); + #endif +  if (stringp (cb)) { +  array(string) names = cb / "->"; +  cb = ctx->id; +  foreach (names, string name) cb = cb[name];    } -  +  cb (@cb_list[i + 1]); +  } +  break; +  } +  }       continue handle_var_loop;    }
8003:    return intro + ")" + OBJ_COUNT;    }    -  constant P_CODE_VERSION = 4.0; +  constant P_CODE_VERSION = 4.1;    // Version spec encoded with the p-code, so we can detect and reject    // incompatible p-code dumps even when the encoded format hasn't    // changed in an obvious way.
8409:    // If the program also is a function the encoder won't dump    // the byte code, but instead the parent object and the    // identifier within it. -  ENCODE_MSG (" encoding reference to program %O->%O\n", -  function_object (what), what); +  ENCODE_MSG (" encoding reference to program %O in object %O\n", +  what, function_object (what));    return ([])[0];    }    }
8419:       if (object o = functionp (what) && function_object (what))    if (o->is_RXML_encodable) { -  ENCODE_MSG (" encoding reference to function %O->%O\n", o, what); +  ENCODE_MSG (" encoding reference to function %O in object %O\n", what, o);    return ([])[0];    }    }
8439:    if (object o = function_object (what)) {    s = sprintf ("%O", o);    if (s == "object") s = ""; -  else s += "->"; +  else s = " in object " + s;    } -  error ("Cannot encode function %s%O at %s.\n", s, what, Function.defined (what)); +  error ("Cannot encode function %O%s at %s.\n", what, s, Function.defined (what));    }    else    error ("Cannot encode %O.\n", what);