public static String putVal(String name, String val, Document doc, Map<String, Object> locals) {
    String ns = null;
    int inx = name.indexOf('.');
    if (inx != -1) {
      ns = name.substring(0, inx);
      name = name.substring(inx + 1);
    }

    if (val == null || val.length() == 0) {
      // removeAttr
      if ("pref".equals(ns)) Multivalent.getInstance().removePreference(name);
      else if ("doc".equals(ns)) doc.removeAttr(name);
      else locals.remove(name);
    } else {
      val = getVal(val, doc, locals);
      if ("pref".equals(ns)) Multivalent.getInstance().putPreference(name, val);
      else if ("doc".equals(ns)) doc.putAttr(name, val);
      else locals.put(name, val);
    }

    return val;
  }
  public static String getVar(String name, Document doc, Map<String, Object> locals) {
    String ns = null;
    String val;
    int inx = name.indexOf('.');
    if (inx != -1) {
      ns = name.substring(0, inx);
      name = name.substring(inx + 1);
    }
    if ("pref".equals(ns)) val = Multivalent.getInstance().getPreference(name, null);
    else if ("doc".equals(ns)) val = doc.getAttr(name);
    else val = (String) locals.get(name);

    return val != null ? val : "";
  }
  /** Evaluate an expression, returning result in a String. */
  public static String eval(Object expr, Document doc, Map<String, Object> locals, Node node) {
    if (expr == null) return null;
    String retval = null;

    if (expr instanceof AWTEvent) {
      doc.getRoot().getBrowser().eventq((AWTEvent) expr);
      return null;
    }

    String[] args = new String[10];
    int argcnt = 0;
    StringTokenizer cmds = new StringTokenizer((String) expr, ";\n"); // handle null expr?
    while (cmds.hasMoreTokens()) {
      StringTokenizer tokens = new StringTokenizer(cmds.nextToken(), " \t");
      String cmd = tokens.nextToken().toLowerCase().intern();
      for (argcnt = 0; tokens.hasMoreTokens(); argcnt++)
        args[argcnt] = getVal(tokens.nextToken(), doc, locals);

      // System.out.print("script cmd="+cmd); for (int i=0; i<argcnt; i++) System.out.print("
      // arg="+args[i]); System.out.println();
      if ("get" == cmd || ("set" == cmd && argcnt == 1)) {
        // assert(argcnt==1)
        retval = getVar(args[0], doc, locals);
      } else if ("set" == cmd) {
        // assert(argcnt==2)
        retval = putVal(args[0], args[1], doc, locals);
      } else if ("event" == cmd) {
        // assert(argcnt==1 || argcnt==2)
        Object cd = (argcnt == 1 ? null : args[1]);
        if ("<node>".equals(cd)) cd = node;
        if (DEBUG) System.out.println("VScript eval:  semanticevent " + args[0] + " " + cd);
        doc.getRoot().getBrowser().eventq(args[0], cd);
        retval = null;
      } // else "unrecognized command"
    }
    return retval;
  }