Branch: Tag:

2001-06-18

2001-06-18 15:48:16 by Martin Stjernholm <mast@lysator.liu.se>

Made defines work with p-code. Better parsing of <attrib> tags inside
<define>. Fixed a couple of cases of inappropriate use of variables in
Frame objects (they can only be used between the do_* callbacks in a
single evaluation). Fixed the types in several tags so that they're
useable in any context.

Use RXML_CONTEXT instead of RXML.get_context(). Use RXML_CONTEXT->misc
instead of id->misc->defines.

Rev: server/modules/tags/rxmltags.pike:1.241

1: - // This is a roxen module. Copyright © 1996 - 2000, Roxen IS. + // This is a roxen module. Copyright © 1996 - 2001, Roxen IS.   //    - #define _stat id->misc->defines[" _stat"] - #define _error id->misc->defines[" _error"] - #define _extra_heads id->misc->defines[" _extra_heads"] - #define _rettext id->misc->defines[" _rettext"] - #define _ok id->misc->defines[" _ok"] + #define _stat RXML_CONTEXT->misc[" _stat"] + #define _error RXML_CONTEXT->misc[" _error"] + #define _extra_heads RXML_CONTEXT->misc[" _extra_heads"] + #define _rettext RXML_CONTEXT->misc[" _rettext"] + #define _ok RXML_CONTEXT->misc[" _ok"]    - constant cvs_version = "$Id: rxmltags.pike,v 1.240 2001/06/15 11:48:06 jonasw Exp $"; + constant cvs_version = "$Id: rxmltags.pike,v 1.241 2001/06/18 15:48:16 mast Exp $";   constant thread_safe = 1;   constant language = roxen->language;   
438:    if(!args->variable && !args->scope)    parse_error("Variable nor scope not specified.\n");    if(!args->variable && args->scope!="roxen") { -  RXML.get_context()->add_scope(args->scope, ([]) ); +  RXML_CONTEXT->add_scope(args->scope, ([]) );    return 0;    } -  RXML.get_context()->user_delete_var(args->variable, args->scope); +  RXML_CONTEXT->user_delete_var(args->variable, args->scope);    return 0;    }    }
510:    inherit RXML.Frame;       array do_enter(RequestID id) { -  RXML.Context ctx = RXML.get_context(); +  RXML.Context ctx = RXML_CONTEXT;    foreach(ctx->list_var(args->from), string var)    ctx->set_var(var, ctx->get_var(var, args->from), args->to);    }
557:      static void inc(mapping m, int val, RequestID id)   { -  RXML.Context context=RXML.get_context(); +  RXML.Context context=RXML_CONTEXT;    array entity=context->parse_user_var(m->variable, m->scope);    if(!context->exist_scope(entity[0])) RXML.parse_error("Scope "+entity[0]+" does not exist.\n");    context->user_set_var(m->variable, (int)context->user_get_var(m->variable, m->scope)+val, m->scope);
871:    constant plugin_name = "variables";       string get_data(string var, mapping args) { -  RXML.Context context=RXML.get_context(); +  RXML.Context context=RXML_CONTEXT;    if(var=="full")    return map(sort(context->list_var(args->scope)),    lambda(string s) {
887:    constant plugin_name = "scopes";       string get_data(string var, mapping args) { -  RXML.Context context=RXML.get_context(); +  RXML.Context context=RXML_CONTEXT;    if(var=="full") {    string result = "";    foreach(sort(context->list_scopes()), string scope) {
1173:   // if(scope_name=="form") oldvar=id->variables;   // #endif    if(args->extend) -  // This is not really good, since we are peeking on the -  // RXML parser internals without any abstraction... -  vars=copy_value(RXML.get_context()->scopes[scope_name]); +  vars=copy_value(RXML_CONTEXT->get_scope (scope_name));    else    vars=([]);   // #if ROXEN_COMPAT <= 1.3
1784:    inherit RXML.Frame;    string link, alink, vlink;    - #define LOCAL_PUSH(X) if(args->X) { X=id->misc->defines->X; id->misc->defines->X=args->X; } + #define LOCAL_PUSH(X) if(args->X) { X=RXML_CONTEXT->misc->X; RXML_CONTEXT->misc->X=args->X; }    array do_enter(RequestID id) {    Roxen.push_color("colorscope",args,id);    LOCAL_PUSH(link);
1793:    return 0;    }    - #define LOCAL_POP(X) if(X) id->misc->defines->X=X + #define LOCAL_POP(X) if(X) RXML_CONTEXT->misc->X=X    array do_return(RequestID id) {    Roxen.pop_color("colorscope",id);    LOCAL_POP(link);
1818:    inherit RXML.Frame;       array do_return(RequestID id) { -  array tags=map(indices(RXML.get_context()->tag_set->get_tag_names()), +  array tags=map(indices(RXML_CONTEXT->tag_set->get_tag_names()),    lambda(string tag) {    if(tag[..3]=="!--#" || !has_value(tag, "#"))    return tag;    return "";    } ) - ({ "" }); -  tags += map(indices(RXML.get_context()->tag_set->get_proc_instr_names()), +  tags += map(indices(RXML_CONTEXT->tag_set->get_proc_instr_names()),    lambda(string tag) { return "&lt;?"+tag+"?&gt;"; } );    tags = Array.sort_array(tags,    lambda(string a, string b) {
1870:    /*    ret+="<p><b>This is a list of all currently defined RXML scopes and their entities</b></p>";    -  RXML.Context context=RXML.get_context(); +  RXML.Context context=RXML_CONTEXT;    foreach(sort(context->list_scopes()), string scope) {    ret+=sprintf("<h3><a href=\"%s?_r_t_h=%s\">%s</a></h3>\n",    id->not_query, Roxen.http_encode_url("&"+scope+";"), scope);
1897:    if(args->type=="roman") return ({ Roxen.int2roman((int)args->num) });    if(args->type=="memory") return ({ Roxen.sizetostring((int)args->num) });    result=roxen.language(args->lang||args->language|| -  id->misc->defines->theme_language, +  RXML_CONTEXT->misc->theme_language,    args->type||"number",id)( (int)args->num );    }    }
1936:    sscanf(data, "%*shelp=%d", help);    res = "<dt><b>"+f+"</b></dt><dd>"+(doc?doc+"<br />":"")+"</dd>";    -  array pack = parse_use_package(data, RXML.get_context()); -  cache_set("macrofiles", "|"+f, pack, 300); +  array defs = parse_use_package(data, RXML_CONTEXT); +  cache_set("macrofiles", "|"+f, defs, 300);    -  constant types = ({ "if plugin", "tag", "variable" }); +  array(string) ifs = ({}), tags = ({});    -  pack = pack + ({}); -  pack[0] = indices(pack[0]); -  pack[1] = pack[1]->name; -  pack[2] = indices(pack[2])+indices(pack[3]); +  foreach (indices (defs[0]), string defname) +  if (has_prefix (defname, "if\0")) +  ifs += ({defname[sizeof ("if\0")..]}); +  else if (has_prefix (defname, "tag\0")) +  tags += ({defname[sizeof ("tag\0")..]});    -  +  constant types = ({ "if plugin", "tag", "form variable", "\"var\" scope variable" }); +  +  array pack = ({ifs, tags, indices(defs[1]), indices(defs[2])}); +     for(int i; i<3; i++)    if(sizeof(pack[i])) {    res += "Defines the following " + types[i] + (sizeof(pack[i])!=1?"s":"") +
1957:    }       private array parse_use_package(string data, RXML.Context ctx) { -  array res = allocate(4); -  multiset before=ctx->get_runtime_tags(); -  if(!ctx->id->misc->_ifs) ctx->id->misc->_ifs = ([]); -  mapping before_ifs = mkmapping(indices(ctx->id->misc->_ifs), -  indices(ctx->id->misc->_ifs)); -  mapping scope_form = mkmapping(ctx->list_var("form"), -  map(ctx->list_var("form"), -  lambda(string v) { return ctx->get_var(v, "form"); } )); -  mapping scope_var = mkmapping(ctx->list_var("var"), -  map(ctx->list_var("var"), -  lambda(string v) { return ctx->get_var(v, "var"); } )); +  RequestID id = ctx->id;    -  Roxen.parse_rxml( data, ctx->id ); +  RXML.Parser parser = Roxen.get_rxml_parser (ctx->id); +  parser->write_end (data); +  parser->eval();    -  foreach( ctx->list_var("form"), string var ) { -  mixed val = ctx->get_var(var, "form"); -  if(scope_form[var]==val) -  m_delete(scope_form, var); -  else -  scope_form[var]=val; +  return ({ +  parser->context->misc, +  parser->context->get_scope ("form"), +  parser->context->get_scope ("var") +  });    }    -  foreach( ctx->list_var("var"), string var ) { -  mixed val = ctx->get_var(var, "var"); -  if(scope_var[var]==val) -  m_delete(scope_var, var); -  else -  scope_var[var]=val; -  } -  -  res[0] = ctx->id->misc->_ifs - before_ifs; -  res[1] = indices(RXML.get_context()->get_runtime_tags()-before); -  res[2] = scope_form; -  res[3] = scope_var; -  return res; -  } -  +     class Frame {    inherit RXML.Frame;   
2018:    }    else    name = "|" + args->package; -  RXML.Context ctx = RXML.get_context(); +  RXML.Context ctx = RXML_CONTEXT;       if(args->info || id->pragma["no-cache"] ||    !(res=cache_lookup("macrofiles",name)) ) {
2039:    cache_set("macrofiles", name, res);    }    -  id->misc->_ifs += res[0]; -  foreach(res[1], RXML.Tag tag) -  ctx->add_runtime_tag(tag); -  foreach(indices(res[2]), string var) -  ctx->set_var(var, res[2][var], "form"); -  foreach(indices(res[3]), string var) -  ctx->set_var(var, res[3][var], "var"); +  [mapping(string:mixed) newdefs, +  mapping(string:mixed)|RXML.Scope formvars, +  mapping(string:mixed)|RXML.Scope varvars] = res; +  foreach (indices (newdefs), string defname) { +  mixed def = ctx->misc[defname] = newdefs[defname]; +  if (has_prefix (defname, "tag\0")) ctx->add_runtime_tag (def[3]); +  } +  foreach(indices(formvars), string var) +  ctx->set_var(var, formvars[var], "form"); +  foreach(indices(varvars), string var) +  ctx->set_var(var, varvars[var], "var");       return 0;    }
2084:      class UserTag {    inherit RXML.Tag; -  string name; +  string name, lookup_name;    int flags = 0;    RXML.Type content_type = RXML.t_xml;    array(RXML.Type) result_types = ({ RXML.t_any(RXML.PXml) });    -  string c; -  mapping defaults; -  string scope; +  // Note: We can't store the actual user tag definition directly in +  // this object; it won't work correctly in p-code since we don't +  // reparse the source and thus don't create a frame with the current +  // runtime tag definition. By looking up the definition in +  // RXML.Context.misc we can get the current definition even if it +  // changes in loops etc.    -  void create(string _name, string _c, mapping _defaults, -  int tag, void|string scope_name) { +  void create(string _name, int tag) {    name=_name; -  c=_c; -  defaults=_defaults; +  lookup_name = "tag\0" + name;    if(tag) flags=RXML.FLAG_EMPTY_ELEMENT; -  scope=scope_name; +     }       class Frame {    inherit RXML.Frame;    RXML.TagSet additional_tags = user_tag_contents_tag_set;    mapping vars; -  string scope_name; +  string content; +  string def; +  mapping defaults; +  string def_scope_name, scope_name;    constant is_user_tag = 1;    string user_tag_contents;    -  +  array do_enter (RequestID id) +  { +  if (array tagdef = RXML_CONTEXT->misc[lookup_name]) +  [def, defaults, def_scope_name, UserTag ignored] = tagdef; +  else +  def = 0; +  return 0; +  } +     array do_return(RequestID id) { -  +  if (!def) return ({propagate_tag()}); +     mapping nargs = defaults+args;    id->misc->last_tag_args = nargs; -  scope_name = scope||name; +  scope_name = def_scope_name || name;    vars = nargs;       if(content && args->trimwhites)
2131: Inside #if ROXEN_COMPAT <= 1.3
   replace_to = values(nargs)+({ Roxen.make_tag_attributes(nargs)[1..], content });    }    string c2; -  c2 = replace(c, replace_from, replace_to); -  if(c2!=c) { +  c2 = replace(def, replace_from, replace_to); +  if(c2!=def) {    vars=([]);    return ({c2});    }
2142:    vars->args = Roxen.make_tag_attributes(nargs)[1..];    vars["rest-args"] = Roxen.make_tag_attributes(args - defaults)[1..];    user_tag_contents = vars->contents = content; -  return ({ c }); +  return ({ def });    }    }   }
2167:       array do_return(RequestID id) {    string n; +  RXML.Context ctx = RXML_CONTEXT;       if(n=args->variable) {    if(args->trimwhites) content=String.trim_all_whites((string)content);
2198:    }   #endif    -  +     if(!content) content = "";       string add_default(Parser.HTML p, mapping m, string c) {
2207:    };       if( compat_level > "2.1" ) { -  string want, rest, attrib=""; -  while( sscanf(content, "%*[ \t\n\r]<attrib%s</attrib%*[ \t\n\r]>%s", -  want, rest)==4 ) { -  attrib += "<attrib" + want + "</attrib>"; -  content = rest; +  Parser.HTML p = Roxen.get_xml_parser(); +  p->add_container ("attrib", add_default); +  array no_more_attrib (Parser.HTML p, void|string ignored) +  { +  p->add_container ("attrib", 0); +  p->_set_tag_callback (0); +  p->_set_data_callback (0); +  p->add_quote_tag ("?", 0, "?"); +  p->add_quote_tag ("![CDATA[", 0, "]]"); +  return 0; +  }; +  // Stop parsing for attrib tags when we reach something else +  // than whitespace and comments. +  p->_set_tag_callback (no_more_attrib); +  p->_set_data_callback (lambda (Parser.HTML p, string d) { +  sscanf (d, "%[ \t\n\r]", string ws); +  if (d != ws) no_more_attrib (p); +  return 0; +  }); +  p->add_quote_tag ("?", no_more_attrib, "?"); +  p->add_quote_tag ("![CDATA[", no_more_attrib, "]]"); +  content = p->finish (content)->read();    } -  Parser.HTML()->add_container("attrib", add_default)->finish(attrib); -  } +     else    content = Parser.HTML()->add_container("attrib", add_default)->    finish(content)->read();
2228:    if(id->conf->old_rxml_compat) content = replace( content, indices(args), values(args) );   #endif    -  RXML.get_context()->add_runtime_tag(UserTag(n, content, defaults, -  tag, args->scope)); +  UserTag user_tag = UserTag (n, tag); +  ctx->misc["tag\0" + n] = ({content, defaults, args->scope, user_tag}); +  ctx->add_runtime_tag(user_tag);    return 0;    }       if (n=args->if) { -  if(!id->misc->_ifs) id->misc->_ifs=([]); -  id->misc->_ifs[args->if]=UserIf(args->if, content); +  ctx->misc["if\0" + n] = UserIf (n, content);    return 0;    }       if (n=args->name) { -  id->misc->defines[n]=content; +  ctx->misc[n]=content;    old_rxml_warning(id, "attempt to define name ","variable");    return 0;    }
2260:    string n;       if(n=args->variable) { -  RXML.get_context()->user_delete_var(n, args->scope); +  RXML_CONTEXT->user_delete_var(n, args->scope);    return 0;    }       if (n=args->tag||args->container) { -  RXML.get_context()->remove_runtime_tag(n); +  m_delete (RXML_CONTEXT->misc, "tag\0" + n); +  RXML_CONTEXT->remove_runtime_tag(n);    return 0;    }       if (n=args->if) { -  m_delete(id->misc->_ifs, n); +  m_delete(RXML_CONTEXT->misc, "if\0" + n);    return 0;    }       if (n=args->name) { -  m_delete(id->misc->defines, args->name); +  m_delete(RXML_CONTEXT->misc, args->name);    return 0;    }   
2492:   class TagCase {    inherit RXML.Tag;    constant name = "case"; +  // FIXME: 2.1 compat: Not mandatory. +  mapping(string:RXML.Type) req_arg_types = (["case": RXML.t_xml (RXML.PEnt)]);       class Frame {    inherit RXML.Frame; -  int cap=0; +  int cap; +  array do_enter() {cap = 0; return 0;}    array do_process(RequestID id) {    if(args->case) {    string op;
2564:    if(args->or) { and = 0; m_delete( args, "or" ); }    if(args->and) { and = 1; m_delete( args, "and" ); }    mapping plugins=get_plugins(); -  if(id->misc->_ifs) plugins+=id->misc->_ifs; -  array possible = indices(args) & indices(plugins); +  mapping(string:mixed) defs = RXML_CONTEXT->misc;       int ifval=0; -  foreach(possible, string s) { -  ifval = plugins[ s ]->eval( args[s], id, args, and, s ); +  foreach(indices (args), string s) +  if (RXML.Tag plugin = plugins[s] || defs["if\0" + s]) { +  ifval = plugin->eval( args[s], id, args, and, s );    if(ifval) {    if(!and) {    do_iterate = 1;
2580:    if(and)    return 0;    } + // else if (compat_level > "2.1") + // parse_error ("Unknown if test %O.\n", s);    if(ifval) {    do_iterate = 1;    return 0;
2602:    inherit RXML.Tag;    constant name = "if";    constant flags = RXML.FLAG_SOCKET_TAG; +  array(RXML.Type) result_types = ({RXML.t_any});    program Frame = FrameIf;   }   
2609:    inherit RXML.Tag;    constant name = "else";    constant flags = 0; +  array(RXML.Type) result_types = ({RXML.t_any});    class Frame {    inherit RXML.Frame; -  int do_iterate=1; +  int do_iterate;    array do_enter(RequestID id) { -  if(_ok) do_iterate=-1; +  do_iterate= _ok ? -1 : 1;    return 0;    }    }
2623:    inherit RXML.Tag;    constant name = "then";    constant flags = 0; +  array(RXML.Type) result_types = ({RXML.t_any});    class Frame {    inherit RXML.Frame; -  int do_iterate=1; +  int do_iterate;    array do_enter(RequestID id) { -  if(!_ok) do_iterate=-1; +  do_iterate= _ok ? 1 : -1;    return 0;    }    }
2636:   class TagElseif {    inherit RXML.Tag;    constant name = "elseif"; +  array(RXML.Type) result_types = ({RXML.t_any});       class Frame {    inherit FrameIf;
2652:    }       mapping(string:RXML.Tag) get_plugins() { -  return RXML.get_context()->tag_set->get_plugins ("if"); +  return RXML_CONTEXT->tag_set->get_plugins ("if");    }    }   }
2661:    inherit RXML.Tag;    constant name = "true";    constant flags = RXML.FLAG_EMPTY_ELEMENT; +  array(RXML.Type) result_types = ({RXML.t_nil}); // No result.       class Frame {    inherit RXML.Frame;
2674:    inherit RXML.Tag;    constant name = "false";    constant flags = RXML.FLAG_EMPTY_ELEMENT; +  array(RXML.Type) result_types = ({RXML.t_nil}); // No result.    class Frame {    inherit RXML.Frame;    array do_enter(RequestID id) {
2717:       // Must override this since it's used by FrameIf.    mapping(string:RXML.Tag) get_plugins() -  {return RXML.get_context()->tag_set->get_plugins ("if");} +  {return RXML_CONTEXT->tag_set->get_plugins ("if");}    }    }   
2786:    ]);    array(string) emit_args = indices( req_arg_types+opt_arg_types );    RXML.Type def_arg_type = RXML.t_text(RXML.PNone); +  array(RXML.Type) result_types = ({RXML.t_any});       int(0..1) should_filter(mapping vs, mapping filter) { -  RXML.Context ctx = RXML.get_context(); +  RXML.Context ctx = RXML_CONTEXT;    foreach(indices(filter), string v) {    string|object val = vs[v];    if(objectp(val))
2849:    RXML.Context ctx;       if(objectp(a0) && a0->rxml_var_eval) { -  if(!ctx) ctx = RXML.get_context(); +  if(!ctx) ctx = RXML_CONTEXT;    a0 = a0->rxml_const_eval ? a0->rxml_const_eval(ctx, v, "", RXML.t_text) :    a0->rxml_var_eval(ctx, v, "", RXML.t_text);    }
2857:    a0 = (string)a0;       if(objectp(b0) && b0->rxml_var_eval) { -  if(!ctx) ctx = RXML.get_context(); +  if(!ctx) ctx = RXML_CONTEXT;    b0 = b0->rxml_const_eval ? b0->rxml_const_eval(ctx, v, "", RXML.t_text) :    b0->rxml_var_eval(ctx, v, "", RXML.t_text);    }
3185:    inherit RXML.Tag;    constant name = "comment";    constant flags = RXML.FLAG_DONT_REPORT_ERRORS; +  RXML.Type content_type = RXML.t_any (RXML.PXml); +  array(RXML.Type) result_types = ({RXML.t_nil}); // No result.    class Frame {    inherit RXML.Frame; -  int do_iterate=-1; +  int do_iterate;    array do_enter() { -  if(args && args->preparse) -  do_iterate=1; +  do_iterate = args && args->preparse ? 1 : -1;    return 0;    }    array do_return = ({});
3200:   class TagPIComment {    inherit TagComment;    constant flags = RXML.FLAG_PROC_INSTR; +  RXML.Type content_type = RXML.t_any (RXML.PXml); +  array(RXML.Type) result_types = ({RXML.t_nil}); // No result.   }      
3210:    inherit RXML.Tag;    constant name = "if";    string plugin_name; -  string rxml_code; +  string|RXML.PCode rxml_code;       void create(string pname, string code) {    plugin_name = pname;
3224:    TRACE_ENTER("user defined if argument "+plugin_name, UserIf);    otruth = _ok;    _ok = -2; -  tmp = Roxen.parse_rxml(rxml_code, id); +  if (stringp (rxml_code)) +  [tmp, rxml_code] = +  RXML_CONTEXT->eval_and_compile (RXML.t_html (RXML.PXml), rxml_code); +  else +  tmp = rxml_code->eval (RXML_CONTEXT);    res = _ok;    _ok = otruth;   
3583:    constant plugin_name = "defined";    string|int|float source(RequestID id, string s) {    mixed val; -  if(!id->misc->defines || !(val=id->misc->defines[s])) return 0; +  if(!(val=RXML_CONTEXT->misc[s])) return 0;    if(stringp(val) || intp(val) || floatp(val)) return val;    return 1;    }
3727:    constant plugin_name="sources";       array(mapping(string:string)) get_dataset(mapping m, RequestID id) { -  return Array.map( indices(RXML.get_context()->tag_set->get_plugins("emit")), +  return Array.map( indices(RXML_CONTEXT->tag_set->get_plugins("emit")),    lambda(string source) { return (["source":source]); } );    }   }
3775:    array(mapping(string:string)) get_dataset(mapping m, RequestID id) {    if(m["from-scope"]) {    m->values=([]); -  RXML.Context context=RXML.get_context(); +  RXML.Context context=RXML_CONTEXT;    map(context->list_var(m["from-scope"]),    lambda(string var){ m->values[var]=context->get_var(var, m["from-scope"]);    return ""; });    }       if( m->variable ) -  m->values = RXML.get_context()->user_get_var( m->variable ); +  m->values = RXML_CONTEXT->user_get_var( m->variable );       if(!m->values)    return ({});