RAPL

Artifact [a85b1835f3]
Login

Artifact [a85b1835f3]

Artifact a85b1835f3e48ee514e1892c4cf001ada5357808:


/*====================================================
 * rapl_register_cmd.js "A Tcl like language implementation in Javascript named WebRAPL 
 * (Web Rapid Application Programming Language)"
 *
 * registration of base built in commands for RAPL
 *
 * Released under the same terms as Tcl itself.
 * (BSD license found at <http://www.tcl.tk/software/tcltk/license.html>)
 *
 * Based on Picol by Salvatore Sanfilippo (<http://antirez.com/page/picol>)
 * (c) Stéphane Arnold 2007
 * Richard Suchenwirth 2007: cleanup, additions
 * Arnulf Wiedemann    2011: a lot of additions for Tcl 8.6 commands
 */

RP.add("rapl-register-cmd", function(R, name) {

function registerCmds(interp) {

  //---------------------------------- Commands in alphabetical order
  /* ==================== command append ===================================== */
  interp.registerCommand("::append", function (interp, args) {
    args.shift();
    this.requireMinArgc(args, 1, "append", "");
    var var_name = args.shift().toString();
    var create_it = 1;
    /* FIXME !!! need handling for array names here */
    var var_obj = interp.global_ns_ptr.lookupVariableEx(interp, var_name, 0, "", 1, 1);
    if (var_obj.isUndefined()) {
      var_obj.setValue("");
    }
    var str = interp.getVarValue(var_name).toString();
    for (var i = 0; i < args.length; i++) {
      str += args[i].toString();
    }
//    interp.setVar(var_name, str);
    var_obj.setValue(str, null);
    return str;
  });

  /* ==================== command break ===================================== */
  interp.registerCommand("::break", function (interp, args) {
    interp.code = this.BREAK;
    return;
  });


  /* ==================== command catch ===================================== */
  interp.registerCommand("::catch", function (interp, args) {
    args.shift();
    this.requireMinArgc(args, 1, "catch", "");
    var body = args.shift();
    var var_obj = null;
    if (args.length > 0) {
        var result_var_name = args.shift();
        var_obj = interp.global_ns_ptr.lookupVariableEx(interp, result_var_name, 0, "", 1, 1);
    }
    try {
      var res = this.eval(body);
      if (var_obj != null) {
        var_obj.setValue(res.toString());
      }
    } catch (e) {
      if (var_obj != null) {
        var_obj.setValue(e);
      }
      return 1;
    }
    return 0;
  });

  /* ==================== command continue ===================================== */
  interp.registerCommand("::continue", function (interp, args) {
    interp.code = this.CONTINUE;
    return;
  });

  /* ==================== command clock format ===================================== */
  interp.registerSubCommand("::clock", "format", function (interp, args) {
    var now = new Date();
    now.setTime(args[1]);
    return now.toString();
  });

  /* ==================== command clock scan ===================================== */
  interp.registerSubCommand("::clock", "scan", function (interp, args) {
    return Date.parse(args[1]);
   });

  /* ==================== command clock seconds ===================================== */
  interp.registerSubCommand("::clock", "seconds", function (interp, args) {
    return (new Date()).valueOf();
  });

  /* ==================== command dom ===================================== */
  if(typeof(jQuery) != 'undefined') {
    interp.registerCommand("::dom", function (interp, args) {
      var selector = args[1].toString();
      var fn = args[2].toString();
      args = args.slice(3);
      for (var i in args) {
        args[i] = args[i].toString();
      }
      var q = $(selector);
      q[fn].apply(q,args);
      return "dom  " + selector;
    });
  }

  /* ==================== command eval ===================================== */
  interp.registerCommand("::eval",function (interp, args) {
    this.requireMinArgc(args, 2, "eval", "");
    for (var i = 1; i < args.length; i++) {
      args[i] = args[i].toString();
    }
    if (args.length == 2) {
      var code = args[1];
    } else {
      var code = args.slice(1).join(" ");
    }
    return interp.eval_statement.eval(code);
  });

  var sqrt = "";
  sqrt = Math.sqrt; // "publish" other Math.* functions as needed

  /* ==================== command expr ===================================== */
  interp.registerCommand("::expr", function (interp, args) {
    var expr_result_ptr = new Array();
    var retcode;

    if (args.length == 2) {
      retcode = interp.eval_expression.evalExpression(args[1], expr_result_ptr);
    } else {
      if (args.length > 2) {
        var obj_ptr;

        obj_ptr = interp.default_obj.concatObj(args.length - 1, args.splice(1));
        obj_ptr.incrRefCount();
        retcode = interp.eval_expression.evalExpression(obj_ptr, expr_result_ptr);
        obj_ptr.decrRefCount();
      } else {
        interp.wrongNumArgs(1, arg, "expression ?...?");
        return interp.ERROR;
      }
    }
    if (retcode != interp.OK) {
      return retcode;
    }
    expr_result_ptr = expr_result_ptr[0];
    interp.setResult(expr_result_ptr);
    expr_result_ptr.decrRefCount();
    return interp.OK;
  });

  /* ==================== command file join ===================================== */
  interp.registerSubCommand("::file", "join", function (interp, args) {
    args.shift();
    this.requireMinArgc(args, 1, "file join", "");
    var path = args.shift();
    for (var i = 0; i < args.length; i++) {
      path += "/"+args[i].toString();
    }
//print("file join!"+path+"!");
    return path;
  });

  /* ==================== command for ===================================== */
  interp.registerCommand("::for", function (interp, args) {
    this.requireExactArgc(args, 5, "for", "");
    interp.eval_statement.eval(args[1].toString());
    if(interp.code != this.OK) return;
    var cond = "::set _ "+args[2].toString();
    var step = args[3].toString();
    var body = args[4].toString();
    interp.inLoop = true;
    interp.code = this.OK;
    while (true) {
      test = interp.statement_parser.objectify(interp.eval_statement.eval(cond));
      if (!test.toBoolean()) break;
      interp.eval_statement.eval(body);
      var ic = interp.code; // tested after step command
      interp.eval_statement.eval(step);
      if(ic == this.BREAK) break;
      if(ic == this.CONTINUE) continue;
    }
    interp.inLoop = false;
    if(interp.code == this.BREAK || interp.code == this.CONTINUE)
      interp.code = this.OK;
    return "";
  });

  /* ==================== command foreach ===================================== */
  interp.registerCommand("::foreach", function (interp, args) {
    return interp.foreachMapHelper(interp, args, 0);
  });

  /* ==================== command format ===================================== */
  interp.registerCommand("::format", function (interp, args) {
    this.requireMinArgc(args, 2, "format", "");
    throw "format not yet implemented";
  });

  /* ==================== command gets ===================================== */
  interp.registerCommand("::gets", function (interp, args) {
    this.requireArgcRange(args, 2, 3, "gets", "");
    var reply = prompt(args[1],"");
    if(args[2] != null) {
      interp.setVar(args[2],interp.statement_parser.objectify(reply));
      return reply.length;
    } else return reply;
  });

  /* ==================== command if ===================================== */
  interp.registerCommand("::if", function (interp, args) {
    var idx = 1;
    var bool = new Array();
    var retcode;
    var current = 1;
    var falsebody = 0;
    var err = false;
    var argc = args.length;

    if (args.length >= 3) {
      while (1) {
        /* Far not enough arguments given! */
        if (current >= argc) {
          err = true;
          break;
        }
        if ((retval = interp.eval_expression.getBoolFromExpr(args[current++], bool)) != interp.OK) {
          return retval;
	}
	bool = bool[0];
        /* There lacks something, isn't it? */
        if (current >= argc) {
          err = true;
	  break;
        }
        if (args[current] == "then") {
          current++;
	}
        /* Tsk tsk, no then-clause? */
        if (current >= argc) {
          err = true;
	  break;
	}
        if (bool) {
          return interp.eval_statement.evalObj(args[current]);
	}
        /* Ok: no else-clause follows */
        if (++current >= argc) {
          interp.setResult(intp.string_obj_type.newEmptyStringObj());
          return interp.OK;
        }
        falsebody = current++;
        if (args[falsebody] == "else") {
          /* IIICKS - else-clause isn't last cmd? */
          if (current != argc - 1) {
            err = true;
	    break
	  }
          return interp.eval_statement.evalObj(args[current]);
        } else {
          if (args[falsebody] == "elseif") {
            /* Ok: elseif follows meaning all the stuff
             * again (how boring...) 
	     */
            continue;
	  } else {
            /* OOPS - else-clause is not last cmd? */
            if (falsebody != argc - 1) {
              err = true;
	      break;
	    }
            return interp.eval_statement.evalObj(args[falsebody]);
	  }
	}
      }
      if (!err) {
        return interp.OK;
      }
    }
    interp.wrongNumArgs(1, args, "condition ?then? trueBody ?elseif ...? ?else? falseBody");
    return interp.ERROR;
  });

  /* ==================== command incr ===================================== */
  interp.registerCommand("::incr", function (interp, args) {
    var wide_value;
    var increment = 1;
    var int_obj_ptr;

    if (args.length != 2 && args.length != 3) {
      interp.wrongNumArgs(1, args, "varName ?increment?");
      return interp.ERROR;
    }
    if (args.length == 3) {
      increment = new Array()
      if (interp.int_obj_type.getWide(args[2], increment) != interp.OK) {
        return interp.ERROR;
      }
      increment = increment[0];
    }
    int_obj_ptr = interp.variable_obj_type.getVariable(args[1], interp.FUNCTION_FLAGS_UNSHARED);
    if (!int_obj_ptr) {
      /* Set missing variable to 0 */
      wide_value = 0;
    } else {
      wide_value = new Array();
      if (interp.int_obj_type.getWide(int_obj_ptr, wide_value) != interp.OK) {
        return interp.ERROR;
      }
    }
    if (!int_obj_ptr || int_obj_ptr.isShared()) {
      int_obj_ptr = interp.int_obj_type.newIntObj(parseInt(wide_value, 10) + parseInt(increment, 10));
      if (interp.variable_obj_type.setVariable(args[1], int_obj_ptr) != interp.OK) {
        int_obj_ptr.freeNewObj();
        return interp.ERROR;
      }
    } else {
      /* Can do it the quick way */
      int_obj_ptr.invalidateStringRep();
      int_obj_ptr.wideValue(parseInt(wide_value, 10) + parseInt(increment));
      /* The following step is required in order to invalidate the
       * string repr of "FOO" if the var name is on the form of "FOO(IDX)" 
       */
      if (args[1].obj_type != interp.variable_obj_type) {
        /* Note that this can't fail since GetVariable already succeeded */
        interp.variable_obj_type.setVariable(args[1], int_obj_ptr);
      }
    }
    interp.setResult(int_obj_ptr);
    return interp.OK;
  });

  /* ==================== command interp alias ===================================== */
  interp.registerSubCommand("::interp", "alias", function (interp, args) {
    args.shift();
    this.requireMinArgc(args, 2, "interp alias", "");
    var src_path = args.shift().toString();
    var src_cmd = args.shift().toString();
    if (args.length == 0) {
      /* return the target_cmd */
      if (src_path != "") {
        throw "interp alias interp other current interp not yet implemented, src_path must be empty!";
      }
      if (src_path == "") {
        src_path = interp;
      }
      var result_str = "";
      for (var i = 0; i < interp.aliases.length; i++) {
        var my_alias = interp.aliases[i];
	if (my_alias.src_path == src_path) {
          if (my_alias.src_cmd == src_cmd) {
            result_str = my_alias.target_cmd;
	    break;
	  }
	}
      }
      return result_str;
    }
    if (args.length == 1) {
      /* seems to be the unset, so the argument has to be empty */
      var arg3 = args.shift();
      if (src_path != "") {
        throw "interp alias interp other current interp not yet implemented, src_path must be empty!";
      }
      if (src_path == "") {
        src_path = interp;
      }
      var my_aliases = new Array();;
      var found = false;
      for (var i = 0; i < interp.aliases.length; i++) {
        var my_alias = interp.aliases[i];
	if ((my_alias.src_path != src_path) || (my_alias.src_cmd != src_cmd)) {
          my_aliases.push(my_alias);
	} else {
          found = true;
	}
      }
      if (found) {
        interp.aliases = my_aliases;
      } else {
	if (src_path == interp) {
          src_path = "{}";
	} else {
          throw "multiple interps not yet implemented!"
	}
        throw "could not unset alias: \""+src_path+" "+src_cmd+"\" does not exist";
      }
      return;
    }
    if (args.length < 2) {
      throw "usage: interp alias srcPath srcCmd targetPath targetCmd ?arg ...?";
    }
    var target_path = args.shift().toString();
    var target_cmd = args.shift().toString();
    if ((src_path != "") || (target_path != "")) {
      throw "interp alias interp other current interp not yet implemented, src_path and target_path must be empty!";
    }
    if (src_path == "") {
      src_path = interp;
    }
    if (target_path == "") {
      target_path = interp;
    }
    interp.aliases.push(new R.InterpAlias(src_path, src_cmd, target_path, target_cmd, args));
  });

  /* ==================== command interp aliases ===================================== */
  interp.registerSubCommand("::interp", "aliases", function (interp, args) {
    args.shift();
    this.requireArgcRange(args, 0, 1, "interp aliases", "");
    var src_path = null;
    if (args.length > 0) {
      src_path = args.shift().toString();
      if (src_path != "") {
        throw "interp alias interp other current interp not yet implemented, src_path must be empty!";
      }
      if (src_path == "") {
        src_path = interp;
      }
    }
    var result_str = "";
    var sep = "";
    for (var i = 0; i < interp.aliases.length; i++) {
      var my_alias = interp.aliases[i];
      if ((src_path == null) || (my_alias.src_path == src_path)) {
        result_str += sep+my_alias.src_cmd;
	sep = " ";
      }
    }
    return result_str;
  });

  /* ==================== command join ===================================== */
  interp.registerCommand("::join", function (interp, args) {
    args.shift();
    this.requireArgcRange(args, 1, 2, "join", "");
    var lst = args.shift();
    var join_str = " ";
    if (args.length > 0) {
      join_str = args.shift().toString();
    }
    var result = lst.getList(lst);
    result = result.join(join_str);
    return result;
  });

  /* ==================== command jsdebug ===================================== */
  interp.registerCommand("::jsdebug", function (interp, args) {
    args.shift();
    var type = args.shift().toString();
    switch(type) {
    case "eval2_cmd_debug":
      interp.eval_statement.eval2_cmd_debug = 1;
      break;
    case "expr_debug":
      interp.eval_statement.expr_debug = 1;
      break;
    case "eval2_parser_debug":
      interp.eval_statement.eval2_parser_debug = 1;
      break;
    case "expr_parser_debug":
      interp.eval_statement.expr_parser_debug = 1;
      break;
    case "class_command_debug":
      this.class_command_debug = 1;
      break;
    default:
      throw "bad type for js_debug: \""+type+"\"";
    }
print("set: "+type+"!");
  });

  /* ==================== command jseval ===================================== */
  interp.registerCommand("::jseval", function (interp, args) {
    args.shift();
    var result = eval(args[0].toString());
    return result;
  });

  /* ==================== command puts ===================================== */
  interp.registerCommand("::puts", function (interp, args) {
    if (args.length != 2 && args.length != 3) {
       interp.wrongNumArgs(1, args, "?-nonewline? string");
        return interp.ERROR;
    }
    if (args.length == 3) {
      if (args[1] != "-nonewline") {
        interp.setResultString("The second argument must be -nonewline", -1);
        return interp.ERROR;
      } else {
        print(args[2]);
      }
    } else {
      print(args[1]);
    }
    return interp.OK;
  });

  /* ==================== command proc ===================================== */
  interp.registerCommand("::proc", function (interp, args) {
    if (args.length != 4 && args.length != 5) {
      interp.wrongNumArgs(1, args, "name arglist ?statics? body");
      return interp.ERROR;
    }
    if (args.length == 4) {
      return interp.command_obj_type.createProcedure(args[1], args[2], null, args[3]);
    } else {
      return interp.command_obj_type.createProcedure(args[1], args[2], args[3], argvs[4]);
    }
  });

  /* ==================== command regexp ===================================== */
  interp.registerCommand("::regexp", function (interp, args) {
    args.shift();
    this.requireMinArgc(args, 2, "regexp", "");
    var re = new RegExp(args.shift().toString());
    var str = args.shift().toString();
    var res = re.exec(str);
    if (res == null) {
      return false;
    }
    for (var i = 0; i < res.length; i++) {
      if (args.length > i) {
        interp.setVar(args[i].toString(), res[i].toString());
      }
    }
    return true;
  });

  /* ==================== command regsub ===================================== */
  interp.registerCommand("::regsub", function (interp, args) {
    this.requireMinArgc(args, 2, "regsub", "");
    throw "regsub not yet implemented";
  });

  /* ==================== command rename ===================================== */
  interp.registerCommand("::rename", function (interp, args) {
    this.requireExactArgc(args, 3, "rename", "");
    interp.renameCommand(args[1], args[2]);
  });

  /* ==================== command return ===================================== */
  interp.registerCommand("::return", function (interp, args) {
    var errorcode = null;
    var errorinfo = null;
    var level = 1;
    var return_code = interp.OK;
    var options = null;
    var allowed_codes = new Object();
    var allowed_options = new Object();
    var num_option_fields = new Array();
    var num_options = new Array();
    var result = new Array();

    allowed_codes["ok"] = 0;
    allowed_codes["error"] = 1;
    allowed_codes["return"] = 2;
    allowed_codes["break"] = 3;
    allowed_codes["continue"] = 4;
    allowed_codes["0"] = 0;
    allowed_codes["1"] = 1;
    allowed_codes["2"] = 2;
    allowed_codes["3"] = 3;
    allowed_codes["4"] = 4;
    allowed_options["-code"] = 1;
    allowed_options["-errorcode"] = 1;
    allowed_options["-errorinfo"] = 1;
    allowed_options["-level"] = 1;
    allowed_options["-options"] = 1;
    interp.eval_statement.code = interp.RETURN;
    var r = "";
    if (args.length == 1) {
      /* seems to be a return value only */
      r = args.shift();
    }
    var options = interp.getOptions(allowed_options, "::return", args.slice(1), num_option_fields, num_options);
    num_option_fields = num_option_fields[0];
    num_options = num_options[0];
    if (args.length - num_option_fields > 2) {
      throw "usage: return ?option value ...? ?result?"
    }
    if (typeof options["-errorcode"] != "undefined") {
      errorcode = options["-errorcode"] ;
      throw "return -errorcode not yet implemented"
    }
    if (typeof options["-code"] != "undefined") {
      code = options["-code"];
      if (interp.return_code_obj_type.getReturnCode(code, result) == interp.ERROR) {
        return interp.ERROR;
      }
      return_code = result[0];
    }
    if (typeof options["-errorinfo"] != "undefined") {
      errorinfo = options["-errorinfo"] ;
      throw "return -errorinfo not yet implemented"
    }
    if (typeof options["-level"] != "undefined") {
      level = options["-level"];
      throw "return -level not yet implemented"
    }
    if (typeof options["-options"] != "undefined") {
      options = options["-options"];
      throw "return -options not yet implemented"
    }
    if (args.length - num_option_fields > 1) {
      r = args[num_option_fields + 1];
      interp.setResult(r);
    }
    interp.return_code = return_code;
    interp.return_level = level;
    return interp.RETURN;
  });

  /* ==================== command scan ===================================== */
  interp.registerCommand("::scan", function (interp, args) {
    this.requireMinArgc(args, 2, "scan", "");
    throw "scan not yet implemented";
  });

  /* ==================== command set ===================================== */
  interp.registerCommand("::set", function (interp, args) {
//print("::set!"+args+"!");
    if ((args.length != 2) && (args.length != 3)) {
      interp.wrongNumArgs(interp, 1, args, "varName ?newValue?");
      return interp.ERROR;
    }
    if (args.length == 2) {
      var obj_ptr;

      obj_ptr = interp.variable_obj_type.getVariable(args[1], interp.FUNCTION_FLAGS_LEAVE_ERR_MSG);
      if (obj_ptr == null) {
        return interp.ERROR;
      }
      interp.setResult(obj_ptr);
      return interp.OK;
    }
    /* args.length == 3 */
    if (interp.variable_obj_type.setVariable(args[1], args[2]) != interp.OK) {
       return interp.ERROR;
    }
    interp.setResult(args[2]);
    return interp.OK;
  });

  /* ==================== command source ===================================== */
  interp.registerCommand("::source", function (interp, args) {
    args.shift();
    this.requireExactArgc(args, 1, "source", "");
    var source_file = args.shift();
    return this.Source(interp, source_file);
  });

  /* ==================== command switch ===================================== */
  interp.registerCommand("::switch", function (interp, args) {
    var usage = '?-switch ...? string {?pattern body ...? ?default body?}';
    if (args.length < 3) {
      interp.wrongNumArgs(1, args, usage);
      return interp.ERROR;
    }
    var body_start_idx = 1;
    var have_exact_opt = 0;
    var have_glob_opt = 0;
    var have_regexp_opt = 0;
    var have_command_opt = 0;
    var have_nocase_opt = 0;
    var have_matchvar_opt = 0;
    var have_indexvar_opt = 0;
    var match_var = null;
    var index_var = null;
    var switch_string;
    var body;
    var obj;
    var text;
    var parser;
    var pattern;
    var token;
    var match_body = null;
    var have_match;
    var default_body = null;
    var re = new RegExp("^[-].*");

    for (body_start_idx = 1; body_start_idx < args.length; body_start_idx++) {
      my_arg = args[body_start_idx].toString();
      if (re.test(my_arg)) {
        if (my_arg == "-exact") {
          if (have_command_opt != 0) {
            interp.setResultFormatted('bad option "-exact": -command option already found');
	    return interp.ERROR;
	  }
          if (have_exact_opt != 0) {
            interp.setResultFormatted('bad option "-exact": -exact option already found');
	    return interp.ERROR;
          }
          if (have_glob_opt != 0) {
            interp.setResultFormatted('bad option "-exact": -glob option already found');
	    return interp.ERROR;
          }
          if (have_regexp_opt != 0) {
            interp.setResultFormatted('bad option "-exact": -regexp option already found');
	    return interp.ERROR;
          }
          have_exact_opt = 1;
        }
        if (my_arg == "-glob") {
          if (have_command_opt != 0) {
            interp.setResultFormatted('bad option "-glob": -command option already found');
	    return interp.ERROR;
          }
          if (have_exact_opt != 0) {
            interp.setResultFormatted('bad option "-glob": -exact option already found');
	    return interp.ERROR;
          }
          if (have_regexp_opt != 0) {
            interp.setResultFormatted('bad option "-glob": -regexp option already found');
	    return interp.ERROR;
          }
          if (have_glob_opt != 0) {
            interp.setResultFormatted('bad option "-glob": -glob option already found');
	    return interp.ERROR;
          }
          have_glob_opt = 1;
        }
        if (my_arg == "-regexp") {
          if (have_command_opt != 0) {
            interp.setResultFormatted('bad option "-regexp": -command option already found');
	    return interp.ERROR;
          }
          if (have_regexp_opt != 0) {
            interp.setResultFormatted('bad option "-regexp": -regexp option already found');
	    return interp.ERROR;
          }
          if (have_exact_opt != 0) {
            interp.setResultFormatted('bad option "-regexp": -exact option already found');
	    return interp.ERROR;
          }
          if (have_glob_opt != 0) {
            interp.setResultFormatted('bad option "-regexp": -glob option already found');
	    return interp.ERROR;
          }
          have_regexp_opt = 1;
        }
        if (my_arg == "-command") {
          if (have_command_opt != 0) {
            interp.setResultFormatted('bad option "-command": -command option already found');
	    return interp.ERROR;
          }
          if (have_regexp_opt != 0) {
            interp.setResultFormatted('bad option "-command": -regexp option already found');
	    return interp.ERROR;
          }
          if (have_exact_opt != 0) {
            interp.setResultFormatted('bad option "-command": -exact option already found');
	    return interp.ERROR;
          }
          if (have_glob_opt != 0) {
            interp.setResultFormatted('bad option "-command": -glob option already found');
	    return interp.ERROR;
          }
          have_command_opt = 1;
        }
        if (my_arg == "-nocase") {
          if (have_nocase_opt != 0) {
            interp.setResultFormatted('bad option "-nocase": -nocase option already found');
	    return interp.ERROR;
          }
          have_nocase_opt = 1;
        }
        if (my_arg == "-matchvar") {
          if (have_matchvar_opt != 0) {
            interp.setResultFormatted('bad option "-matchvar": -matchvar option already found');
	    return interp.ERROR;
          }
          if (have_regexp_opt == 0) {
            interp.setResultFormatted('-matchvar option requires -regexp option');
	    return interp.ERROR;
          }
          have_matchvar_opt = 1;
          if (body_start_idx > args.length-1) {
            interp.wrongNumArgs(1, args, usage);
	    return interp.ERROR;
          }
          body_start_idx++;
          matchvar = args[body_start_idx].toString();
        }
        if (my_arg == "-indexvar") {
          if (have_indexvar_opt != 0) {
            interp.setResultFormatted('bad option "-indexvar": -indexvar option already found');
	    return interp.ERROR;
          }
          if (have_regexp_opt == 0) {
            interp.setResultFormatted('-indexvar option requires -regexp option');
	    return interp.ERROR;
          }
          have_indexvar_opt = 1;
          if (body_start_idx > args.length-1) {
            interp.wrongNumArgs(1, args, usage);
	    return interp.ERROR;
          }
          body_start_idx++;
          indexvar = args[body_start_idx].toString();
        }
        if (my_arg == "--") {
          body_start_idx++;
          break;
        }
      } else {
        break;
      }
    }
    if (body_start_idx == args.length - 1) {
      interp.wrongNumArgs(1, args, usage);
      return interp.ERROR;
    }
    if ((have_exact_opt == 0) && (have_glob_opt == 0) && (have_regexp_opt == 0)) {
      have_exact_opt = 1;
    }
//    switch_string = args[body_start_idx].toString();
//    body_start_idx++;
//print("swstr!"+switch_string+"!");
//    if (body_start_idx > args.length - 1) {
//print("wrong4!");
//      interp.wrongNumArgs(1, args, usage);
//      return interp.ERROR;
//    }
    /* if we have one argument left, it must be a list, otherwise we have the
     * list elements in the args array
     */
    var case_list;
    var i;
    var script = 0;
    var str_obj = args[body_start_idx++];
    var pat_count = args.length - body_start_idx;
    if (pat_count == 1) {
      var vector = new Array();

      pat_count = new Array();
      interp.list_obj_type.listGetElements(args[args.length-1], pat_count, vector);
      pat_count = pat_count[0];
      case_list = vector[0];
    } else {
      case_list = args.slice(body_start_idx);
    }
    if (pat_count == 0 || pat_count % 2 != 0) {
      interp.wrongNumArgs(1, args, usage);
      return interp.ERROR;
    }
    have_match = 0;
    for (i = 0; script == 0 && i < pat_count; i += 2) {
      var pat_obj = case_list[i];

      if (pat_obj.getString() != "default" || i < (pat_count - 2)) {
        if (have_exact_opt) {
          if (str_obj.getString() == pat_obj.getString()) {
            script = case_list[i + 1];
	  }
	}
        if (have_glob_opt) {
          if (pat_obj.stringMatchObj(str_obj, 0)) {
            script = case_list[i + 1];
	  }
	}
        if (have_regexp_opt) {
          command = interp.string_obj_type.newStringObj("regexp", -1);
          /* Fall thru intentionally */
	}
        if (have_command_opt) {
          var rc = Jim_CommandMatchObj(interp, command, pat_obj, str_obj, 0);
          /* After the execution of a command we need to
           * make sure to reconvert the object into a list
           * again. Only for the single-list style [switch]. */
          if (argc - opt == 1) { 
            var vector = new Array();
	    var count = new Array();

            interp.list_obj_type.listGetElements(args[opt], count, vector);
	    pat_count = count[0];
            case_list = vector[0];
          }
          /* command is here already decref'd */
          if (rc < 0) {
            return -rc;
          }
          if (rc) {
            script = case_list[i + 1];
	  }
        }
      } else {
        script = case_list[i + 1];
      }
    }
    for (; i < pat_count && script.getString() == "-"; i += 2) {
      script = case_list[i + 1];
    }
    if (script && script.getString() == "-") {
        interp.setResultFormatted("no body specified for pattern \"%#s\"", case_list[i - 2]);
        return interp.ERROR;
    }
    interp.setEmptyResult();
    if (script) {
      return interp.eval_statement.evalObj(script);
    }
    return interp.OK;
  });

  /* ==================== sec_msec ===================================== */
  function sec_msec () {
    var t = new Date();
    return t.getSeconds()*1000 + t.getMilliseconds();
  }

  /* ==================== command time ===================================== */
  interp.registerCommand("::time", function (interp, args) {
    if ((args.length != 2) && (args.length != 3)) {
      interp.wrongNumArgs(interp, 1, args, "command ?count?");
      return interp.ERROR;
    }
    var code = args[1];
    if (args.length > 2) {
      var n = args[2];
    } else {
      var n = 1;
    }
    var t0 = sec_msec();
//var xx = interp.string_obj_type.newStringObj("10", -1);
//var yy = interp.string_obj_type.newStringObj("a", -1);
    for(var i = 0; i < n; i++) {
      interp.eval_statement.evalObj(code);
//        interp.setVar("a", xx);
//        interp.variable_obj_type.setVariable(yy, xx);
    }
//print("TT!"+((sec_msec()-t0)*1000/n + " microseconds per iteration")+"!");
    interp.setResult(interp.string_obj_type.newStringObj((sec_msec()-t0)*1000/n + " microseconds per iteration", -1));
    return interp.OK;
  });

  /* ==================== command uplevel ===================================== */
  interp.registerCommand("::uplevel", function (interp, args) {
    args.shift();
    this.requireMinArgc(args, 1, "uplevel", "");
    var arg1 = args.shift();
    var have_level = 0;
    var have_integer_level = 0;
    if (this.isLevel.test(arg1)) {
      have_level = 1;
      if (this.isInteger.test(arg1)) {
        have_integer_level = 1;
      } else {
	arg1 = arg1.substring(1);
      }
    } else {
      have_level = 1;
      have_integer_level = 1;
      arg1 = "1";
    }
    if (interp.eval_statement.level < arg1) {
        throw "bad level \""+arg1+"\" interp level: "+interp.eval_statement.level;
    }
    for (var i = arg1; i > 0; i--) {
      interp.uplevel_dist++;
    }
    var my_obj = interp.empty_obj.newRaplStringObject("", -1);
    var my_args;
    if (args.length == 1) {
      var lst = my_obj.getList(args);
      my_args = lst.getString();
    } else {
      my_args = args.getString();
    }
//print("UPLEVEL!"+arg1+"!"+args+"!"+my_args+"!");
    var res = interp.eval_statement.eval(my_args);
    for (var i = arg1; i > 0; i--) {
      interp.uplevel_dist--;
    }
    return interp.statement_parser.objectify(res);
  });

  /* ==================== command upvar ===================================== */
  interp.registerCommand("::upvar", function (interp, args) {
//print("UPVAR!"+args+"!");
    args.shift();
    this.requireMinArgc(args, 2, "upvar", "");
    var arg1 = args[0];
    var have_level = 0;
    var have_integer_level = 0;
    var index_ptr = new Array();
    var err_msg_ptr = new Array();

    if (this.isLevel.test((arg1))) {
      have_level = 1;
      args.shift();
      if (this.isInteger.test(arg1)) {
        have_integer_level = 1;
      } else {
	arg1 = arg1.substring(1);
      }
    } else {
      have_level = 1;
      have_integer_level = 1;
      arg1 = "1";
    }
    arg1 = parseInt(arg1);
    interp.upvar_dist = parseInt(arg1);
    interp.in_upvar = 1;
    if (interp.eval_statement.level < arg1) {
        throw "bad level \""+arg1+"\" interp level: "+interp.eval_statement.level;
    }
    var my_flags = 0;
    while (args.length > 0) {
      if (args.length == 1) {
        throw "must be an even number of references"
      }
      var create = 1;
      var to_var = args.shift().toString();
      var my_var = args.shift().toString();
//print("upvar to_var!"+to_var+"!my_var!"+my_var+"!arg1!"+arg1+"!intplv!"+interp.eval_statement.level+"!");
      interp.eval_statement.level -= arg1;
      var var_to_obj = interp.global_ns_ptr.lookupVariableEx(interp, to_var, interp.FUNCTION_FLAGS_LEAVE_ERR_MSG, "access", 0, 0);
      interp.eval_statement.level += arg1;
      if (var_to_obj == null) {
        interp.code = this.ERROR;
	return "";
      }
      var my_var_obj = interp.variable_obj_type.lookupSimpleVar(interp, my_var, my_flags|this.VAR_LOOKUP_AVOID_RESOLVERS, create, err_msg_ptr, index_ptr);
      if (my_var_obj == null) {
        this.VarErrMsg(interp, my_var, null, "create", interp.current_namespace.err_msg, -1);
	this.SetErrorCode(interp, "TCL", "LOOKUP", "VARNAME", my_name);
	interp.code = this.ERROR;
	return "";
      }
      if (var_to_obj == my_var_obj) {
        this.SetResult(interp, "can't upvar from variable to itself");
	this.SetErrorCode(interp, "TCL", "UPVAR", "SELF");
	interp.code = this.ERROR;
	return "";
      }
      my_var_obj.linkVar(var_to_obj);
    }
    interp.in_upvar = 0;
    interp.code = this.OK;
    return "";
  });

  /* ==================== command unset ===================================== */
  interp.registerCommand("::unset", function (interp, args) {
    this.requireExactArgc(args, 2, "unset", "");
    interp.setVar(args[1], null);
  });

  /* ==================== command while ===================================== */
  interp.registerCommand("::while", function (interp, args) {
    args.shift();
    this.requireExactArgc(args, 2, "while", "");
    var cond = args.shift();
    var body = args.shift();
    var res  = "";
    interp.inLoop = true;
    interp.code = this.OK;
    while (true) {
      var my_cond = interp.statement_parser.parse2ExprTree(cond.toString());
      test = interp.statement_parser.objectify(interp.eval_statement.evalExprSubTree(my_cond, null, 0));
      interp.eval_statement.eval("::set _ "+test.toString());
      if (!test.toBoolean()){
        break;
      }
      res = interp.eval_statement.eval(body);
      if(interp.code == this.CONTINUE) {
        continue;
      }
      if(interp.code != this.OK) {
        break;
      }
    }
    interp.inLoop = false;
    if(interp.code == this.BREAK || interp.code == this.CONTINUE) {
      interp.code = this.OK;
    }
    return interp.statement_parser.objectify(res);
  });

  /* ==================== command variable ===================================== */
  interp.registerCommand("::variable", function (interp, args) {
print("variable!"+args+"!");
    var var_name;
    var tail;
    var i;
    var j;
    var cp;
    var var_ptr;
    var array_ptr = new Array();
    var var_value_ptr;
    var i;
    var result;
    var var_name_ptr;
    var tail_ptr;

    if (args.length < 2) {
      interp.wrongNumArgs(interp, 1, args, "variable ?value variable value ...?");
      return interp.ERROR;
    }
    for (i = 1 ; i < args.length ; i += 2) {
      /*
       * Look up each variable in the current namespace context, creating it
       * if necessary.
       */
      var_name_ptr = args[i];
print("I1!"+i+"!"+var_name_ptr+"!");
      var_name = var_name_ptr.getString();
      var_ptr = interp.variable_obj_type.objLookupVarEx(var_name_ptr, null,
        (interp.NAMESPACE_ONLY | interp.FUNCTION_FLAGS_LEAVE_ERR_MSG), "define",
        /*createPart1*/ 1, /*createPart2*/ 0, array_ptr);
      if (array_ptr[0] != null) {
        /*
         * Variable cannot be an element in an array. If arrayPtr is
         * non-NULL, it is, so throw up an error and return.
         */
        interp.objVarErrMsg(var_name_ptr, null, "define", is_array_element, -1);
        interp.setErrorCode(["TCL", "UPVAR", "LOCAL_ELEMENT"]);
        return interp.ERROR;
      }
      if (var_ptr == null) {
        return interp.ERROR;
      }
      /*
       * Mark the variable as a namespace variable and increment its
       * reference count so that it will persist until its namespace is
       * destroyed or until the variable is unset.
       */
      interp.variable_obj_type.setVarNamespaceVar(var_ptr);
      /*
       * If a value was specified, set the variable to that value.
       * Otherwise, if the variable is new, leave it undefined. (If the
       * variable already exists and no value was specified, leave its value
       * unchanged; just create the local link if we're in a Tcl procedure).
       */
print("i!"+i+"!"+args.length+"!");
      if (i + 1 < args.length) {	/* A value was specified. */
//FIXME !!!
      if (interp.variable_obj_type.setVariable(var_name_ptr, args[i + 1]) != interp.OK) {
        return interp.ERROR;
      }
//        var_value_ptr = interp.variable_obj_type.ptrSetVar(var_ptr, array_ptr, var_name_ptr,
//	      null, args[i + 1],
//	      interp.NAMESPACE_LOOKUP_NAMESPACE_ONLY | interp.FUNCTION_FLAGS_LEAVE_ERR_MSG, -1);
//        if (var_value_ptr == null) {
//          return interp.ERROR;
//        }
      }
      /*
       * If we are executing inside a Rapl procedure, create a local variable
       * linked to the new namespace variable "var_name".
       */
print("hasLocalVars!");
      if (interp.var_frame_ptr.hasLocalVars()) {
print("hasLocalVars yes!");
        /*
         * var_name might have a scope qualifier, but the name for the
         * local "link" variable must be the simple name at the tail.
         *
         * Locate tail in one pass: drop any prefix after two *or more*
         * consecutive ":" characters).
         */
        tail = var_name;
        i = 0;
        j = i;
        for (; i < var_name.length; i++) {
          if (tail.charAt(i) == ':') {
	    j = i;
            while (tail.charAt(j) == ':') {
	      j++;
            }
          }
        }
        tail = tail.substring(j);
        /*
         * Create a local link "tail" to the variable "varName" in the
         * current namespace.
         */
        if (tail == var_name) {
          tail_ptr = var_name_ptr;
        } else {
	  tail_ptr = interp.string_obj_type.newStringObj(tail, -1);
	  tail_ptr.incrRefCount();
        }
        result = interp.variable_obj_type.objMakeUpvar(null, var_name_ptr, /*other_p2*/ null,
	      /*other_flags*/ interp.NAMESPACE_LOOKUP_NAMESPACE_ONLY,
	      /*my_name*/ tail_ptr, /*my_flags*/ 0, -1);
        if (tail != var_name) {
	  tail_ptr.decrRefCount();
        }
        if (result != interp.OK) {
          return result;
        }
      }
    }
    return interp.OK;


  });

  /* ==================== command native ===================================== */
  // native cmdname {function(interp, args) {...}}
  interp.registerCommand("::native", function (interp, args) {
    this.requireExactArgc(args, 3, "native", "");
    var cmd = args[1].toList();
    var func = eval(args[2].toString());
//print("in: "+args[2].toString()+", func: "+ func);
    if (cmd.length == 1) {
      interp.registerCommand(cmd[0].toString(), func);
      return;
    }
    base = cmd[0].toString();
    cmd.shift();
    interp.registerSubCommand(base, cmd.join(" "), eval(args[2].toString()));
    return;
  });

  /* ==================== command showLevelInfo ===================================== */
  interp.registerCommand("::showLevelInfo", function (interp, args) {

    args.shift();
    this.requireMinArgc(args, 1, "showLevelInfo", "");
    var txt = "";
    if (args.length > 0) {
      txt = args.shift();
    }
    for (var i = interp.eval_statement.level-1; i >= 0; i--) {
      print("LEVEL_INFO!"+i+"!"+txt+"!"+interp.level_infos[i]+"!");
    }
  });

}

R.registerCmds = registerCmds;

}, "0.0.1", {});