/// <summary> See Tcl user documentation for details.</summary> public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv) { if ((argv.Length < 2) || (argv.Length > 3)) { throw new TclNumArgsException(interp, 1, argv, "script ?count?"); } int count; if (argv.Length == 2) { count = 1; } else { count = TclInteger.get(interp, argv[2]); } long startTime = System.DateTime.Now.Ticks; for (int i = 0; i < count; i++) { interp.eval(argv[1], 0); } long endTime = System.DateTime.Now.Ticks; long uSecs = (((endTime - startTime) / 10) / count); if (uSecs == 1) { interp.setResult(TclString.newInstance("1 microsecond per iteration")); } else { interp.setResult(TclString.newInstance(uSecs + " microseconds per iteration")); } return TCL.CompletionCode.RETURN; }
/// <summary> Evaluates a Tcl expression. See Tcl user documentation for /// details. /// </summary> /// <exception cref=""> TclException If malformed expression. /// </exception> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { if ( argv.Length < 2 ) { throw new TclNumArgsException( interp, 1, argv, "arg ?arg ...?" ); } if ( argv.Length == 2 ) { interp.setResult( interp.expr.eval( interp, argv[1].ToString() ) ); } else { StringBuilder sbuf = new StringBuilder(); sbuf.Append( argv[1].ToString() ); for ( int i = 2; i < argv.Length; i++ ) { sbuf.Append( ' ' ); sbuf.Append( argv[i].ToString() ); } interp.setResult( interp.expr.eval( interp, sbuf.ToString() ) ); } return TCL.CompletionCode.RETURN; }
/// <summary> This procedure is invoked to process the "eof" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { Channel chan; /* The channel being operated on this method */ if ( argv.Length != 2 ) { throw new TclNumArgsException( interp, 1, argv, "channelId" ); } chan = TclIO.getChannel( interp, argv[1].ToString() ); if ( chan == null ) { throw new TclException( interp, "can not find channel named \"" + argv[1].ToString() + "\"" ); } if ( chan.eof() ) { interp.setResult( TclInteger.newInstance( 1 ) ); } else { interp.setResult( TclInteger.newInstance( 0 ) ); } return TCL.CompletionCode.RETURN; }
public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv ) { TclObject varValue = null; if ( objv.Length < 2 ) { throw new TclNumArgsException( interp, 1, objv, "varName ?value value ...?" ); } else if ( objv.Length == 2 ) { interp.resetResult(); interp.setResult( interp.getVar( objv[1], 0 ) ); } else { for ( int i = 2; i < objv.Length; i++ ) { varValue = interp.setVar( objv[1], objv[i], TCL.VarFlag.APPEND_VALUE ); } if ( varValue != null ) { interp.resetResult(); interp.setResult( varValue ); } else { interp.resetResult(); } } return TCL.CompletionCode.RETURN; }
/// <summary> This procedure is invoked to process the "gets" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { bool writeToVar = false; // If true write to var passes as arg string varName = ""; // The variable to write value to Channel chan; // The channel being operated on int lineLen; TclObject line; if ( ( argv.Length < 2 ) || ( argv.Length > 3 ) ) { throw new TclNumArgsException( interp, 1, argv, "channelId ?varName?" ); } if ( argv.Length == 3 ) { writeToVar = true; varName = argv[2].ToString(); } chan = TclIO.getChannel( interp, argv[1].ToString() ); if ( chan == null ) { throw new TclException( interp, "can not find channel named \"" + argv[1].ToString() + "\"" ); } try { line = TclString.newInstance( new StringBuilder( 64 ) ); lineLen = chan.read( interp, line, TclIO.READ_LINE, 0 ); if ( lineLen < 0 ) { // FIXME: Need more specific posix error codes! if ( !chan.eof() && !chan.isBlocked( interp ) ) { throw new TclPosixException( interp, TclPosixException.EIO, true, "error reading \"" + argv[1].ToString() + "\"" ); } lineLen = -1; } if ( writeToVar ) { interp.setVar( varName, line, 0 ); interp.setResult( lineLen ); } else { interp.setResult( line ); } } catch ( IOException e ) { throw new TclRuntimeError( "GetsCmd.cmdProc() Error: IOException when getting " + chan.ChanName + ": " + e.Message ); } return TCL.CompletionCode.RETURN; }
/// <summary> Creates an exception with the appropiate Tcl error message to /// indicate an error with variable access. /// /// </summary> /// <param name="interp">currrent interpreter. /// </param> /// <param name="name1">first part of a variable name. /// </param> /// <param name="name2">second part of a variable name. May be null. /// </param> /// <param name="operation">either "read" or "set". /// </param> /// <param name="reason">a string message to explain why the operation fails.. /// </param> internal TclVarException(Interp interp, string name1, string name2, string operation, string reason):base(TCL.CompletionCode.ERROR) { if (interp != null) { interp.resetResult(); if ((System.Object) name2 == null) { interp.setResult("can't " + operation + " \"" + name1 + "\": " + reason); } else { interp.setResult("can't " + operation + " \"" + name1 + "(" + name2 + ")\": " + reason); } } }
/// <summary> Creates a TclException with the appropiate Tcl error /// message for having the wring number of arguments to a Tcl command. /// <p> /// Example: <pre> /// /// if (argv.length != 3) { /// throw new TclNumArgsException(interp, 1, argv, "option name"); /// } /// </pre> /// /// </summary> /// <param name="interp">current Interpreter. /// </param> /// <param name="argc">the number of arguments to copy from the offending /// command to put into the error message. /// </param> /// <param name="argv">the arguments of the offending command. /// </param> /// <param name="message">extra message to appear in the error message that /// explains the proper usage of the command. /// </param> /// <exception cref=""> TclException is always thrown. /// </exception> public TclNumArgsException( Interp interp, int argc, TclObject[] argv, string message ) : base(TCL.CompletionCode.ERROR) { if ( interp != null ) { StringBuilder buff = new StringBuilder( 50 ); buff.Append( "wrong # args: should be \"" ); for ( int i = 0; i < argc; i++ ) { if ( argv[i].InternalRep is TclIndex ) { buff.Append( argv[i].InternalRep.ToString() ); } else { buff.Append( argv[i].ToString() ); } if ( i < ( argc - 1 ) ) { buff.Append( " " ); } } if ( ( message != null ) ) { buff.Append( " " + message ); } buff.Append( "\"" ); interp.setResult( buff.ToString() ); } }
/// <summary> This procedure is invoked to process the "tell" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv) { Channel chan; /* The channel being operated on this method */ if (argv.Length != 2) { throw new TclNumArgsException(interp, 1, argv, "channelId"); } chan = TclIO.getChannel(interp, argv[1].ToString()); if (chan == null) { throw new TclException(interp, "can not find channel named \"" + argv[1].ToString() + "\""); } try { interp.setResult(TclInteger.newInstance((int) chan.tell())); } catch (System.IO.IOException e) { throw new TclException(interp, "Error in TellCmd"); } return TCL.CompletionCode.RETURN; }
public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv) { if (argv.Length < 2 || argv.Length > 4) { throw new TclNumArgsException(interp, 1, argv, "message ?errorInfo? ?errorCode?"); } if (argv.Length >= 3) { string errorInfo = argv[2].ToString(); if (!errorInfo.Equals("")) { interp.addErrorInfo(errorInfo); interp.errAlreadyLogged = true; } } if (argv.Length == 4) { interp.setErrorCode(argv[3]); } interp.setResult(argv[1]); throw new TclException(TCL.CompletionCode.ERROR); }
/// <summary> See Tcl user documentation for details.</summary> /// <exception cref=""> TclException If incorrect number of arguments. /// </exception> public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv) { if (argv.Length != 2) { throw new TclNumArgsException(interp, 1, argv, "list"); } interp.setResult(TclInteger.newInstance(TclList.getLength(interp, argv[1]))); return TCL.CompletionCode.RETURN; }
public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { bool debug; if ( argv.Length == 2 ) { System.Diagnostics.Debug.WriteLine( "getting value of \"" + argv[1].ToString() + "\"" ); interp.setResult( interp.getVar( argv[1], 0 ) ); } else if ( argv.Length == 3 ) { System.Diagnostics.Debug.WriteLine( "setting value of \"" + argv[1].ToString() + "\" to \"" + argv[2].ToString() + "\"" ); interp.setResult( interp.setVar( argv[1], argv[2], 0 ) ); } else { throw new TclNumArgsException( interp, 1, argv, "varName ?newValue?" ); } return TCL.CompletionCode.RETURN; }
protected internal TclException(Interp interp, string msg, TCL.CompletionCode ccode, int idx):base(msg) { if (ccode == TCL.CompletionCode.OK) { throw new TclRuntimeError("The reserved completion code TCL.CompletionCode.OK (0) cannot be used " + "in TclException"); } compCode = ccode; errIndex = idx; if (interp != null && (System.Object) msg != null) { interp.setResult(msg); } }
/// <summary> This procedure is invoked to process the "incr" Tcl command. /// See the user documentation for details on what it does. /// </summary> /// <exception cref=""> TclException if wrong # of args or increment is not an /// integer. /// </exception> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv ) { int incrAmount; TclObject newValue; if ( ( objv.Length != 2 ) && ( objv.Length != 3 ) ) { throw new TclNumArgsException( interp, 1, objv, "varName ?increment?" ); } // Calculate the amount to increment by. if ( objv.Length == 2 ) { incrAmount = 1; } else { try { incrAmount = TclInteger.get( interp, objv[2] ); } catch ( TclException e ) { interp.addErrorInfo( "\n (reading increment)" ); throw; } } // Increment the variable's value. newValue = Var.incrVar( interp, objv[1], null, incrAmount, TCL.VarFlag.LEAVE_ERR_MSG ); // FIXME: we need to look at this exception throwing problem again /* if (newValue == null) { return TCL_ERROR; } */ // Set the interpreter's object result to refer to the variable's new // value object. interp.setResult( newValue ); return TCL.CompletionCode.RETURN; }
/// <summary> See Tcl user documentation for details.</summary> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { TclObject list = TclList.newInstance(); list.preserve(); try { for ( int i = 1; i < argv.Length; i++ ) TclList.append( interp, list, argv[i] ); interp.setResult( list ); } finally { list.release(); } return TCL.CompletionCode.RETURN; }
/// <summary> See Tcl user documentation for details.</summary> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { string sep = null; if ( argv.Length == 2 ) { sep = null; } else if ( argv.Length == 3 ) { sep = argv[2].ToString(); } else { throw new TclNumArgsException( interp, 1, argv, "list ?joinString?" ); } TclObject list = argv[1]; int size = TclList.getLength( interp, list ); if ( size == 0 ) { interp.resetResult(); return TCL.CompletionCode.RETURN; } StringBuilder sbuf = new StringBuilder( TclList.index( interp, list, 0 ).ToString() ); for ( int i = 1; i < size; i++ ) { if ( (System.Object)sep == null ) { sbuf.Append( ' ' ); } else { sbuf.Append( sep ); } sbuf.Append( TclList.index( interp, list, i ).ToString() ); } interp.setResult( sbuf.ToString() ); return TCL.CompletionCode.RETURN; }
public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { if ( argv.Length < 3 ) { throw new TclNumArgsException( interp, 1, argv, "list index" ); } int size = TclList.getLength( interp, argv[1] ); int index = Util.getIntForIndex( interp, argv[2], size - 1 ); TclObject element = TclList.index( interp, argv[1], index ); if ( element != null ) { interp.setResult( element ); } else { interp.resetResult(); } return TCL.CompletionCode.RETURN; }
/// <summary> This procedure is invoked to process the "fblocked" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv) { Channel chan; // The channel being operated on this method if (argv.Length != 2) { throw new TclNumArgsException(interp, 1, argv, "channelId"); } chan = TclIO.getChannel(interp, argv[1].ToString()); if (chan == null) { throw new TclException(interp, "can not find channel named \"" + argv[1].ToString() + "\""); } interp.setResult(chan.isBlocked(interp)); return TCL.CompletionCode.RETURN; }
public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { if ( argv.Length != 1 ) { throw new TclNumArgsException( interp, 1, argv, null ); } // Get the name of the working dir. string dirName = interp.getWorkingDir().ToString(); // Java File Object methods use backslashes on Windows. // Convert them to forward slashes before returning the dirName to Tcl. if ( JACL.PLATFORM == JACL.PLATFORM_WINDOWS ) { dirName = dirName.Replace( '\\', '/' ); } interp.setResult( dirName ); return TCL.CompletionCode.RETURN; }
/// <summary> See Tcl user documentation for details.</summary> /// <exception cref=""> TclException If incorrect number of arguments. /// </exception> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { if ( argv.Length != 4 ) { throw new TclNumArgsException( interp, 1, argv, "lset list index element" ); } int size = TclList.getLength( interp, argv[1] ); int index = Util.getIntForIndex( interp, argv[2], size ); TclObject list = argv[1]; bool isDuplicate = false; // If the list object is unshared we can modify it directly. Otherwise // we create a copy to modify: this is "copy on write". if ( list.Shared ) { list = list.duplicate(); isDuplicate = true; } try { TclObject[] replace = new TclObject[1]; replace[0]=argv[3]; TclList.replace(interp,list,index,1,replace,0,0 ); interp.setResult( list ); } catch ( TclException e ) { if ( isDuplicate ) { list.release(); } throw; } return TCL.CompletionCode.RETURN; }
/// <summary> This procedure is invoked to process the "catch" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> /// <exception cref=""> TclException if wrong number of arguments. /// </exception> public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv) { if (argv.Length != 2 && argv.Length != 3) { throw new TclNumArgsException(interp, 1, argv, "command ?varName?"); } TclObject result; TCL.CompletionCode code = TCL.CompletionCode.OK; try { interp.eval(argv[1], 0); } catch (TclException e) { code = e.getCompletionCode(); } result = interp.getResult(); if ( argv.Length == 3 ) { try { interp.setVar(argv[2], result, 0); } catch (TclException e) { throw new TclException(interp, "couldn't save command result in variable"); } } interp.resetResult(); interp.setResult(TclInteger.newInstance((int)code)); return TCL.CompletionCode.RETURN; }
/// <summary> This procedure is invoked to process the "encoding" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { if ( argv.Length < 2 ) { throw new TclNumArgsException( interp, 1, argv, "option ?arg ...?" ); } int index = TclIndex.get( interp, argv[1], validCmds, "option", 0 ); switch ( index ) { case OPT_CONVERTTO: case OPT_CONVERTFROM: { string tclEncoding; Encoding javaEncoding; TclObject data; if ( argv.Length == 3 ) { tclEncoding = systemTclEncoding; data = argv[2]; } else if ( argv.Length == 4 ) { tclEncoding = argv[2].ToString(); data = argv[3]; } else { throw new TclNumArgsException( interp, 2, argv, "?encoding? data" ); } javaEncoding = getJavaName( tclEncoding ); if ( (System.Object)javaEncoding == null ) { throw new TclException( interp, "unknown encoding \"" + tclEncoding + "\"" ); } try { if ( index == OPT_CONVERTFROM ) { // Treat the string as binary data byte[] bytes = TclByteArray.getBytes( interp, data ); // ATK interp.setResult( System.Text.Encoding.UTF8.GetString( bytes, 0, bytes.Length) ); } else { // Store the result as binary data // ATK byte[] bytes = data.ToString().getBytes(javaEncoding); byte[] bytes = System.Text.Encoding.UTF8.GetBytes( data.ToString() ); interp.setResult( TclByteArray.newInstance( bytes ) ); } } catch ( IOException ex ) { throw new TclRuntimeError( "Encoding.cmdProc() error: " + "unsupported java encoding \"" + javaEncoding + "\"" ); } break; } case OPT_NAMES: { if ( argv.Length > 2 ) { throw new TclNumArgsException( interp, 2, argv, null ); } TclObject list = TclList.newInstance(); for ( int i = 0; i < tclNames.Length; i++ ) { TclList.append( interp, list, TclString.newInstance( tclNames[i] ) ); } interp.setResult( list ); break; } case OPT_SYSTEM: { if ( argv.Length > 3 ) throw new TclNumArgsException( interp, 2, argv, "?encoding?" ); if ( argv.Length == 2 ) { interp.setResult( systemTclEncoding ); } else { string tclEncoding = argv[2].ToString(); Encoding javaEncoding = getJavaName( tclEncoding ); if ( javaEncoding == null ) { throw new TclException( interp, "unknown encoding \"" + tclEncoding + "\"" ); } systemTclEncoding = tclEncoding; systemJavaEncoding = javaEncoding; } break; } default: { throw new TclRuntimeError( "Encoding.cmdProc() error: " + "incorrect index returned from TclIndex.get()" ); } } return TCL.CompletionCode.RETURN; }
/// <summary> This procedure is invoked to process the "subst" Tcl command. /// See the user documentation for details on what it does. /// /// </summary> /// <param name="interp">the current interpreter. /// </param> /// <param name="argv">command arguments. /// </param> /// <exception cref=""> TclException if wrong # of args or invalid argument(s). /// </exception> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { int currentObjIndex, len, i; int objc = argv.Length - 1; bool doBackslashes = true; bool doCmds = true; bool doVars = true; StringBuilder result = new StringBuilder(); string s; char c; for ( currentObjIndex = 1; currentObjIndex < objc; currentObjIndex++ ) { if ( !argv[currentObjIndex].ToString().StartsWith( "-" ) ) { break; } int opt = TclIndex.get( interp, argv[currentObjIndex], validCmds, "switch", 0 ); switch ( opt ) { case OPT_NOBACKSLASHES: doBackslashes = false; break; case OPT_NOCOMMANDS: doCmds = false; break; case OPT_NOVARS: doVars = false; break; default: throw new TclException( interp, "SubstCmd.cmdProc: bad option " + opt + " index to cmds" ); } } if ( currentObjIndex != objc ) { throw new TclNumArgsException( interp, currentObjIndex, argv, "?-nobackslashes? ?-nocommands? ?-novariables? string" ); } /* * Scan through the string one character at a time, performing * command, variable, and backslash substitutions. */ s = argv[currentObjIndex].ToString(); len = s.Length; i = 0; while ( i < len ) { c = s[i]; if ( ( c == '[' ) && doCmds ) { ParseResult res; try { interp.evalFlags = Parser.TCL_BRACKET_TERM; interp.eval( s.Substring( i + 1, ( len ) - ( i + 1 ) ) ); TclObject interp_result = interp.getResult(); interp_result.preserve(); res = new ParseResult( interp_result, i + interp.termOffset ); } catch ( TclException e ) { i = e.errIndex + 1; throw; } i = res.nextIndex + 2; result.Append( res.value.ToString() ); res.release(); } else if ( c == '\r' ) { /* * (ToDo) may not be portable on Mac */ i++; } else if ( ( c == '$' ) && doVars ) { ParseResult vres = Parser.parseVar( interp, s.Substring( i, ( len ) - ( i ) ) ); i += vres.nextIndex; result.Append( vres.value.ToString() ); vres.release(); } else if ( ( c == '\\' ) && doBackslashes ) { BackSlashResult bs = tcl.lang.Interp.backslash( s, i, len ); i = bs.nextIndex; if ( bs.isWordSep ) { break; } else { result.Append( bs.c ); } } else { result.Append( c ); i++; } } interp.setResult( result.ToString() ); return TCL.CompletionCode.RETURN; }
/// <summary> See Tcl user documentation for details.</summary> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { interp.setResult( Util.concat( 1, argv.Length, argv ) ); return TCL.CompletionCode.RETURN; }
public static void evalObjv( Interp interp, TclObject[] objv, int length, int flags ) { Command cmd; WrappedCommand wCmd = null; TclObject[] newObjv; int i; CallFrame savedVarFrame; //Saves old copy of interp.varFrame // in case TCL.EVAL_GLOBAL was set. interp.resetResult(); if ( objv.Length == 0 ) { return; } // If the interpreter was deleted, return an error. if ( interp.deleted ) { interp.setResult( "attempt to call eval in deleted interpreter" ); interp.setErrorCode( TclString.newInstance( "CORE IDELETE {attempt to call eval in deleted interpreter}" ) ); throw new TclException( TCL.CompletionCode.ERROR ); } // Check depth of nested calls to eval: if this gets too large, // it's probably because of an infinite loop somewhere. if ( interp.nestLevel >= interp.maxNestingDepth ) { throw new TclException( interp, "too many nested calls to eval (infinite loop?)" ); } interp.nestLevel++; try { // Find the procedure to execute this command. If there isn't one, // then see if there is a command "unknown". If so, create a new // word array with "unknown" as the first word and the original // command words as arguments. Then call ourselves recursively // to execute it. cmd = interp.getCommand( objv[0].ToString() ); if ( cmd == null ) wCmd = interp.getObjCommand( objv[0].ToString() ); // See if we are running as a slave interpretor, and this is a windows command if ( cmd == null && wCmd == null && interp.slave != null ) { wCmd = interp.slave.masterInterp.getObjCommand( objv[0].ToString() ); } if ( cmd == null && wCmd == null ) { newObjv = new TclObject[objv.Length + 1]; for ( i = ( objv.Length - 1 ); i >= 0; i-- ) { newObjv[i + 1] = objv[i]; } newObjv[0] = TclString.newInstance( "unknown" ); newObjv[0].preserve(); cmd = interp.getCommand( "unknown" ); if ( cmd == null ) { Debug.Assert( false, "invalid command name \"" + objv[0].ToString() + "\"" ); throw new TclException( interp, "invalid command name \"" + objv[0].ToString() + "\"" ); } else { evalObjv( interp, newObjv, length, 0 ); } newObjv[0].release(); return; } // Finally, invoke the Command's cmdProc. interp.cmdCount++; savedVarFrame = interp.varFrame; if ( ( flags & TCL.EVAL_GLOBAL ) != 0 ) { interp.varFrame = null; } int rc = 0; if ( cmd != null ) { if ( cmd.cmdProc( interp, objv ) == TCL.CompletionCode.EXIT ) throw new TclException( TCL.CompletionCode.EXIT ); } else { rc = wCmd.objProc( wCmd.objClientData, interp, objv.Length, objv ); if ( rc != 0 ) { if ( rc == TCL.TCL_RETURN ) throw new TclException( TCL.CompletionCode.RETURN ); throw new TclException( TCL.CompletionCode.ERROR ); } } interp.varFrame = savedVarFrame; } finally { interp.nestLevel--; } }
public static TclParse parseVarName( Interp interp, char[] script_array, int script_index, int numBytes, TclParse parse, bool append ) // Non-zero means append tokens to existing // information in parse; zero means ignore // existing tokens in parse and reinitialize // it. { char cur; TclToken token, startToken; int endIndex, varIndex; #if DEBUG System.Diagnostics.Debug.WriteLine(); System.Diagnostics.Debug.WriteLine("Entered parseVarName()"); System.Diagnostics.Debug.Write("now to parse var off the string \""); for (int k = script_index; k < script_array.Length; k++) { System.Diagnostics.Debug.Write(script_array[k]); } System.Diagnostics.Debug.WriteLine("\""); #endif if ( numBytes >= 0 ) { endIndex = script_index + numBytes; } else { endIndex = script_array.Length - 1; } if ( !append ) { parse = new TclParse( interp, script_array, endIndex, null, -1 ); } // Generate one token for the variable, an additional token for the // name, plus any number of additional tokens for the index, if // there is one. token = parse.getToken( parse.numTokens ); token.type = TCL_TOKEN_VARIABLE; token.script_array = script_array; token.script_index = script_index; varIndex = parse.numTokens; parse.numTokens++; script_index++; if ( script_index >= endIndex ) { // The dollar sign isn't followed by a variable name. // replace the TCL_TOKEN_VARIABLE token with a // TCL_TOKEN_TEXT token for the dollar sign. token.type = TCL_TOKEN_TEXT; token.size = 1; token.numComponents = 0; parse.result = TCL.CompletionCode.OK; return parse; } startToken = token; token = parse.getToken( parse.numTokens ); // The name of the variable can have three forms: // 1. The $ sign is followed by an open curly brace. Then // the variable name is everything up to the next close // curly brace, and the variable is a scalar variable. // 2. The $ sign is not followed by an open curly brace. Then // the variable name is everything up to the next // character that isn't a letter, digit, or underscore. // :: sequences are also considered part of the variable // name, in order to support namespaces. If the following // character is an open parenthesis, then the information // between parentheses is the array element name. // 3. The $ sign is followed by something that isn't a letter, // digit, or underscore: in this case, there is no variable // name and the token is just "$". if ( script_array[script_index] == '{' ) { System.Diagnostics.Debug.WriteLine( "parsing curley var name" ); script_index++; token.type = TCL_TOKEN_TEXT; token.script_array = script_array; token.script_index = script_index; token.numComponents = 0; while ( true ) { if ( script_index == endIndex ) { if ( interp != null ) { interp.setResult( "missing close-brace for variable name" ); } parse.termIndex = token.script_index - 1; parse.incomplete = true; parse.result = TCL.CompletionCode.ERROR; return parse; } if ( script_array[script_index] == '}' ) { break; } script_index++; } token.size = script_index - token.script_index; startToken.size = script_index - startToken.script_index; parse.numTokens++; script_index++; } else { System.Diagnostics.Debug.WriteLine( "parsing non curley var name" ); token.type = TCL_TOKEN_TEXT; token.script_array = script_array; token.script_index = script_index; token.numComponents = 0; while ( script_index != endIndex ) { cur = script_array[script_index]; if ( ( System.Char.IsLetterOrDigit( cur ) ) || ( cur == '_' ) ) { script_index++; continue; } if ( ( cur == ':' ) && ( ( ( script_index + 1 ) != endIndex ) && ( script_array[script_index + 1] == ':' ) ) ) { script_index += 2; while ( ( script_index != endIndex ) && ( script_array[script_index] == ':' ) ) { script_index++; } continue; } break; } token.size = script_index - token.script_index; if ( token.size == 0 ) { // The dollar sign isn't followed by a variable name. // replace the TCL_TOKEN_VARIABLE token with a // TCL_TOKEN_TEXT token for the dollar sign. System.Diagnostics.Debug.WriteLine( "single $ with no var name found" ); startToken.type = TCL_TOKEN_TEXT; startToken.size = 1; startToken.numComponents = 0; parse.result = TCL.CompletionCode.OK; return parse; } parse.numTokens++; if ( ( script_index != endIndex ) && ( script_array[script_index] == '(' ) ) { // This is a reference to an array element. Call // parseTokens recursively to parse the element name, // since it could contain any number of substitutions. System.Diagnostics.Debug.WriteLine( "parsing array element" ); script_index++; parse = parseTokens( script_array, script_index, TYPE_CLOSE_PAREN, parse ); if ( parse.result != TCL.CompletionCode.OK ) { return parse; } if ( ( parse.termIndex == endIndex ) || ( parse.inString[parse.termIndex] != ')' ) ) { if ( interp != null ) { interp.setResult( "missing )" ); } parse.termIndex = script_index - 1; parse.incomplete = true; parse.result = TCL.CompletionCode.ERROR; return parse; } script_index = parse.termIndex + 1; } } #if DEBUG System.Diagnostics.Debug.WriteLine("default end parse case"); System.Diagnostics.Debug.Write("var token is \""); for (int k = startToken.script_index; k < script_index; k++) { System.Diagnostics.Debug.Write(script_array[k]); } System.Diagnostics.Debug.WriteLine("\""); #endif startToken.size = script_index - startToken.script_index; startToken.numComponents = parse.numTokens - ( varIndex + 1 ); parse.result = TCL.CompletionCode.OK; return parse; }
public static void eval2( Interp interp, char[] script_array, int script_index, int numBytes, int flags ) { int i; int objUsed = 0; int nextIndex, tokenIndex; int commandLength, bytesLeft; bool nested; TclObject[] objv; TclObject obj; TclParse parse = null; TclToken token; // Saves old copy of interp.varFrame in case TCL.EVAL_GLOBAL was set CallFrame savedVarFrame; // Take into account the trailing '\0' int script_length = script_array.Length - 1; // These are modified instead of script_array and script_index char[] src_array = script_array; int src_index = script_index; #if DEBUG System.Diagnostics.Debug.WriteLine(); System.Diagnostics.Debug.WriteLine("Entered eval2()"); System.Diagnostics.Debug.Write("now to eval2 the string \""); for (int k = script_index; k < script_array.Length; k++) { System.Diagnostics.Debug.Write(script_array[k]); } System.Diagnostics.Debug.WriteLine("\""); #endif if ( numBytes < 0 ) { numBytes = script_length - script_index; } interp.resetResult(); savedVarFrame = interp.varFrame; if ( ( flags & TCL.EVAL_GLOBAL ) != 0 ) { interp.varFrame = null; } // Each iteration through the following loop parses the next // command from the script and then executes it. bytesLeft = numBytes; // Init objv with the most commonly used array size objv = grabObjv( interp, 3 ); if ( ( interp.evalFlags & TCL_BRACKET_TERM ) != 0 ) { nested = true; } else { nested = false; } interp.evalFlags &= ~TCL_BRACKET_TERM; try { do { parse = parseCommand( interp, src_array, src_index, bytesLeft, null, 0, nested ); if ( parse.result != TCL.CompletionCode.OK ) { throw new TclException( parse.result ); } // The test on noEval is temporary. As soon as the new expr // parser is implemented it should be removed. if ( parse.numWords > 0 && interp.noEval == 0 ) { // Generate an array of objects for the words of the command. try { tokenIndex = 0; token = parse.getToken( tokenIndex ); // Test to see if new space needs to be allocated. If objv // is the EXACT size of parse.numWords, then no allocation // needs to be performed. if ( objv.Length != parse.numWords ) { //System.out.println("need new size " + objv.length); releaseObjv( interp, objv ); //let go of resource objv = grabObjv( interp, parse.numWords ); //get new resource } else { //System.out.println("reusing size " + objv.length); } for ( objUsed = 0; objUsed < parse.numWords; objUsed++ ) { obj = evalTokens( interp, parse.tokenList, tokenIndex + 1, token.numComponents ); if ( obj == null ) { throw new TclException( TCL.CompletionCode.ERROR ); } else { objv[objUsed] = obj; if ( token.type == TCL_TOKEN_EXPAND_WORD ) { int numElements; int code; TclList.setListFromAny( null, objv[objUsed] ); TclObject[] elements = TclList.getElements( null, objv[objUsed] ); if ( elements.Length == 0 ) { elements = new TclObject[1]; elements[0] = TclString.newInstance("{}") ; TclList.setListFromAny( null, elements[0] ); } numElements = elements.Length; /* * Some word expansion was requested. Check for objv resize. */ int objIdx = objUsed + numElements - 1; Array.Resize( ref objv, objIdx+1 ); while ( numElements-- != 0 ) { objv[objIdx] = elements[numElements]; objv[objIdx].preserve(); objIdx--; } objUsed = objv.Length-1; } } tokenIndex += ( token.numComponents + 1 ); token = parse.getToken( tokenIndex ); } // Execute the command and free the objects for its words. try { evalObjv( interp, objv, bytesLeft, 0 ); } catch ( System.StackOverflowException e ) { interp.setResult( "too many nested calls" + " to eval (infinite loop?)" ); throw new TclException( TCL.CompletionCode.ERROR ); } } catch ( TclException e ) { // Generate various pieces of error information, such // as the line number where the error occurred and // information to add to the errorInfo variable. Then // free resources that had been allocated // to the command. if ( e.getCompletionCode() == TCL.CompletionCode.ERROR && !( interp.errAlreadyLogged ) ) { commandLength = parse.commandSize; char term = script_array[parse.commandStart + commandLength - 1]; int type = charType( term ); int terminators; if ( nested ) { terminators = TYPE_COMMAND_END | TYPE_CLOSE_BRACK; } else { terminators = TYPE_COMMAND_END; } if ( ( type & terminators ) != 0 ) { // The command where the error occurred didn't end // at the end of the script (i.e. it ended at a // terminator character such as ";". Reduce the // length by one so that the error message // doesn't include the terminator character. commandLength -= 1; } interp.varFrame = savedVarFrame; logCommandInfo( interp, script_array, script_index, parse.commandStart, commandLength, e ); throw e; } else throw; } finally { for ( i = 0; i < objUsed; i++ ) { objv[i].release(); } objUsed = 0; parse.release(); // Cleanup parser resources } } // Advance to the next command in the script. nextIndex = parse.commandStart + parse.commandSize; bytesLeft -= ( nextIndex - src_index ); src_index = nextIndex; if ( nested && ( src_index > 1 ) && ( src_array[src_index - 1] == ']' ) ) { // We get here in the special case where the TCL_BRACKET_TERM // flag was set in the interpreter and we reached a close // bracket in the script. Return immediately. interp.termOffset = ( src_index - 1 ) - script_index; interp.varFrame = savedVarFrame; return; } } while ( bytesLeft > 0 ); } finally { if ( parse != null ) { parse.release(); // Let go of parser resources } releaseObjv( interp, objv ); // Let go of objv buffer } interp.termOffset = src_index - script_index; interp.varFrame = savedVarFrame; return; }
internal static void list( Interp interp, Interp slaveInterp ) { TclObject result = TclList.newInstance(); interp.setResult( result ); IEnumerator aliases = slaveInterp.aliasTable.Values.GetEnumerator(); while ( aliases.MoveNext() ) { InterpAliasCmd alias = (InterpAliasCmd)aliases.Current; TclList.append( interp, result, alias.name ); } }
internal static void describe( Interp interp, Interp slaveInterp, TclObject name ) { // If the alias has been renamed in the slave, the master can still use // the original name (with which it was created) to find the alias to // describe it. string inString = name.ToString(); if ( slaveInterp.aliasTable.ContainsKey( inString ) ) { InterpAliasCmd alias = (InterpAliasCmd)slaveInterp.aliasTable[inString]; interp.setResult( alias.prefix ); } }
private const int GENERIC = 4; // Floating or exponential, // depending on exponent. %g /// <summary> This procedure is invoked to process the "format" Tcl command. /// See the user documentation for details on what it does. /// /// The first argument to the cmdProc is the formatString. The cmdProc /// simply copies all the chars into the sbuf until a '%' is found. At /// this point the cmdProc parces the formatString and determines the /// format parameters. The parcing of the formatString can be broken into /// six possible phases: /// /// Phase 0 - Simply Print: If the next char is % /// Phase 1 - XPG3 Position Specifier: If the format [1-n]$ is used /// Phase 2 - A Set of Flags: One or more of the following + - /// [space] 0 # /// Phase 3 - A Minimun Field Width Either [integer] or * /// Phase 4 - A Precision If the format .[integer] or .* /// Phase 5 - A Length Modifier If h is present /// Phase 6 - A Conversion Character If one of the following is used /// d u i o x X c s f E g G /// /// Any phase can skip ahead one or more phases, but are not allowed /// to move back to previous phases. Once the parameters are determined /// the cmdProc calls one of three private methods that returns a fully /// formatted string. This loop occurs for ever '%' in the formatString. /// </summary> public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { StringBuilder sbuf; // Stores the return value of the parsed // format string StrtoulResult stoul; // A return object to the strtoul call char[] format; // The format argument is converted to a char // array and manipulated as such int phase; // Stores the current phase of the parsing int width; // Minimum field width int precision; // Field precision from field specifier int fmtFlags; // Used to store the format flags ( #,+,etc) int argIndex; // Index of argument to substitute next. int fmtIndex; // Used to locate end of the format fields. int endIndex; // Used to locate end of numerical fields. int intValue; // Generic storage variable long lngValue; // Store the TclInteger.get() result double dblValue; // Store the TclDouble.get() result bool noPercent; // Special case for speed: indicates there's // no field specifier, just a string to copy. bool xpgSet; // Indicates that xpg has been used for the // particular format of the main while loop bool gotXpg; // True means that an XPG3 %n$-style // specifier has been seen. bool gotSequential; // True means that a regular sequential // (non-XPG3) conversion specifier has // been seen. bool useShort; // Value to be printed is short // (half word). bool precisionSet; // Used for f, e, and E conversions bool cont; // Used for phase 3 if ( argv.Length < 2 ) { throw new TclNumArgsException( interp, 1, argv, "formatString ?arg arg ...?" ); } argIndex = 2; fmtIndex = 0; gotXpg = gotSequential = false; format = argv[1].ToString().ToCharArray(); sbuf = new StringBuilder(); // So, what happens here is to scan the format string one % group // at a time, making many individual appends to the StringBuffer. while ( fmtIndex < format.Length ) { fmtFlags = phase = width = 0; noPercent = true; xpgSet = precisionSet = useShort = false; precision = -1; // Append all characters to sbuf that are not used for the // format specifier. if ( format[fmtIndex] != '%' ) { int i; for ( i = fmtIndex; ( i < format.Length ); i++ ) { if ( format[i] == '%' ) { noPercent = false; break; } } sbuf.Append( new string( format, fmtIndex, i - fmtIndex ) ); fmtIndex = i; if ( noPercent ) { break; } } // If true, then a % has been indicated but we are at the end // of the format string. Call function to throw exception. if ( fmtIndex + 1 >= format.Length ) { errorEndMiddle( interp ); } // Phase 0: // Check for %%. If true then simply write a single '%' // to the list. checkOverFlow( interp, format, fmtIndex + 1 ); if ( format[fmtIndex + 1] == '%' ) { sbuf.Append( "%" ); fmtIndex += 2; // Re-enter the loop continue; } fmtIndex++; checkOverFlow( interp, format, fmtIndex ); if ( System.Char.IsDigit( format[fmtIndex] ) ) { // Parce the format array looking for the end of // the number. stoul = strtoul( format, fmtIndex ); intValue = (int)stoul.value; endIndex = stoul.index; if ( format[endIndex] == '$' ) { if ( intValue == 0 ) { errorBadIndex( interp, true ); } // Phase 1: // Check for an XPG3-style %n$ specification. // Note: there must not be a mixture of XPG3 // specs and non-XPG3 specs in the same format string. if ( gotSequential ) { errorMixedXPG( interp ); } gotXpg = true; xpgSet = true; phase = 2; fmtIndex = endIndex + 1; argIndex = intValue + 1; if ( ( argIndex < 2 ) || ( argIndex >= argv.Length ) ) { errorBadIndex( interp, gotXpg ); } } else { // Phase 3: // Format jumped straight to phase 3; Setting // width field. Again, verify that all format // specifiers are sequential. if ( gotXpg ) { errorMixedXPG( interp ); } gotSequential = true; if ( format[fmtIndex] != '0' ) { fmtIndex = endIndex; width = intValue; phase = 4; } } } else { if ( gotXpg ) { errorMixedXPG( interp ); } gotSequential = true; } // Phase 2: // Setting the Format Flags. At this point the phase value // can be either zero or three. Anything greater is an // incorrect format. if ( phase < 3 ) { checkOverFlow( interp, format, fmtIndex ); char ch = format[fmtIndex]; cont = true; while ( cont ) { switch ( ch ) { case '-': { fmtFlags |= LEFT_JUSTIFY; break; } case '#': { fmtFlags |= ALT_OUTPUT; break; } case '0': { fmtFlags |= PAD_W_ZERO; break; } case ' ': { fmtFlags |= SPACE_OR_SIGN; break; } case '+': { fmtFlags |= SHOW_SIGN; break; } default: { cont = false; } break; } if ( cont ) { fmtIndex++; checkOverFlow( interp, format, fmtIndex ); ch = format[fmtIndex]; } } phase = 3; } // Phase 3: // Setting width field. Partially redundant code from the // Phase 1 if/else statement, but this is made to run fast. checkOverFlow( interp, format, fmtIndex ); if ( System.Char.IsDigit( format[fmtIndex] ) ) { stoul = strtoul( format, fmtIndex ); width = (int)stoul.value; fmtIndex = stoul.index; } else if ( format[fmtIndex] == '*' ) { if ( argv.Length > argIndex ) { width = TclInteger.get( interp, argv[argIndex] ); if ( width < 0 ) { width = -width; fmtFlags |= LEFT_JUSTIFY; } argIndex++; fmtIndex++; } } // Phase 4: // Setting the precision field. checkOverFlow( interp, format, fmtIndex ); if ( format[fmtIndex] == '.' ) { fmtIndex++; checkOverFlow( interp, format, fmtIndex ); if ( System.Char.IsDigit( format[fmtIndex] ) ) { precisionSet = true; stoul = strtoul( format, fmtIndex ); precision = (int)stoul.value; fmtIndex = stoul.index; } else if ( format[fmtIndex] == '*' ) { if ( argv.Length > argIndex ) { precisionSet = true; precision = TclInteger.get( interp, argv[argIndex] ); argIndex++; fmtIndex++; checkOverFlow( interp, format, fmtIndex ); } } else { // Format field had a '.' without an integer or '*' // preceeding it (eg %2.d or %2.-5d) errorBadField( interp, format[fmtIndex] ); } } // Phase 5: // Setting the length modifier. if ( format[fmtIndex] == 'h' ) { fmtIndex++; checkOverFlow( interp, format, fmtIndex ); useShort = true; } else if ( format[fmtIndex] == 'l' ) { fmtIndex++; checkOverFlow( interp, format, fmtIndex ); // 'l' is ignored, but should still be processed. } if ( ( argIndex < 2 ) || ( argIndex >= argv.Length ) ) { errorBadIndex( interp, gotXpg ); } // Phase 6: // Setting conversion field. // At this point, variables are initialized as follows: // // width The specified field width. This is always // non-negative. Zero is the default. // precision The specified precision. The default // is -1. // argIndex The argument index from the argv array // for the appropriate arg. // fmtFlags The format flags are set via bitwise // operations. Below are the bits // and their meanings. // ALT_OUTPUT set if a '#' is present. // SHOW_SIGN set if a '+' is present. // SPACE_OR_SIGN set if a ' ' is present. // LEFT_JUSTIFY set if a '-' is present or if the // field width was negative. // PAD_W_ZERO set if a '0' is present string strValue = ""; char index = format[fmtIndex]; switch ( index ) { case 'u': case 'd': case 'o': case 'x': case 'X': case 'i': { if ( index == 'u' ) { // Since Java does not provide unsigned ints we need to // make our own. If the value is negative we need to // clear out all of the leading bits from the 33rd bit // and on. The result is a long value equal to that // of an unsigned int. lngValue = (long)TclInteger.get( interp, argv[argIndex] ); if ( lngValue < 0 ) { lngValue = ( lngValue << 32 ); lngValue = ( SupportClass.URShift( lngValue, 32 ) ); } } else { fmtFlags |= SIGNED_VALUE; lngValue = (long)TclInteger.get( interp, argv[argIndex] ); } // If the useShort option has been selected, we need // to clear all but the first 16 bits. if ( useShort ) { lngValue = ( lngValue << 48 ); lngValue = ( lngValue >> 48 ); } if ( index == 'o' ) { sbuf.Append( cvtLngToStr( lngValue, width, precision, fmtFlags, 8, "01234567".ToCharArray(), "0" ) ); } else if ( index == 'x' ) { sbuf.Append( cvtLngToStr( lngValue, width, precision, fmtFlags, 16, "0123456789abcdef".ToCharArray(), "0x" ) ); } else if ( index == 'X' ) { sbuf.Append( cvtLngToStr( lngValue, width, precision, fmtFlags, 16, "0123456789ABCDEF".ToCharArray(), "0X" ) ); } else { sbuf.Append( cvtLngToStr( lngValue, width, precision, fmtFlags, 10, "0123456789".ToCharArray(), "" ) ); } break; } case 'c': { intValue = 0; char[] arr = new char[] { (char)TclInteger.get( interp, argv[argIndex] ) }; strValue = new string( arr ); sbuf.Append( cvtStrToStr( strValue, width, precision, fmtFlags ) ); break; } case 's': { strValue = argv[argIndex].ToString(); sbuf.Append( cvtStrToStr( strValue, width, precision, fmtFlags ) ); break; } case 'f': { dblValue = TclDouble.get( interp, argv[argIndex] ); sbuf.Append( cvtDblToStr( dblValue, width, precision, fmtFlags, 10, "0123456789".ToCharArray(), "", FLOAT ) ); break; } case 'e': { dblValue = TclDouble.get( interp, argv[argIndex] ); sbuf.Append( cvtDblToStr( dblValue, width, precision, fmtFlags, 10, "e".ToCharArray(), "", EXP ) ); break; } case 'E': { dblValue = TclDouble.get( interp, argv[argIndex] ); sbuf.Append( cvtDblToStr( dblValue, width, precision, fmtFlags, 10, "E".ToCharArray(), "", EXP ) ); break; } case 'g': { dblValue = TclDouble.get( interp, argv[argIndex] ); sbuf.Append( cvtDblToStr( dblValue, width, precision, fmtFlags, 10, "e".ToCharArray(), "", GENERIC ) ); break; } case 'G': { dblValue = TclDouble.get( interp, argv[argIndex] ); sbuf.Append( cvtDblToStr( dblValue, width, precision, fmtFlags, 10, "E".ToCharArray(), "", GENERIC ) ); break; } default: { errorBadField( interp, format[fmtIndex] ); } break; } fmtIndex++; argIndex++; } interp.setResult( sbuf.ToString() ); return TCL.CompletionCode.RETURN; }
internal static void create( Interp interp, Interp slaveInterp, Interp masterInterp, TclObject name, TclObject targetName, int objIx, TclObject[] objv ) { string inString = name.ToString(); InterpAliasCmd alias = new InterpAliasCmd(); alias.name = name; name.preserve(); alias.slaveInterp = slaveInterp; alias.targetInterp = masterInterp; alias.prefix = TclList.newInstance(); alias.prefix.preserve(); TclList.append( interp, alias.prefix, targetName ); TclList.insert( interp, alias.prefix, 1, objv, objIx, objv.Length - 1 ); slaveInterp.createCommand( inString, alias ); alias.slaveCmd = NamespaceCmd.findCommand( slaveInterp, inString, null, 0 ); try { interp.preventAliasLoop( slaveInterp, alias.slaveCmd ); } catch ( TclException e ) { // Found an alias loop! The last call to Tcl_CreateObjCommand made // the alias point to itself. Delete the command and its alias // record. Be careful to wipe out its client data first, so the // command doesn't try to delete itself. slaveInterp.deleteCommandFromToken( alias.slaveCmd ); throw; } // Make an entry in the alias table. If it already exists delete // the alias command. Then retry. if ( slaveInterp.aliasTable.ContainsKey( inString ) ) { InterpAliasCmd oldAlias = (InterpAliasCmd)slaveInterp.aliasTable[inString]; slaveInterp.deleteCommandFromToken( oldAlias.slaveCmd ); } alias.aliasEntry = inString; SupportClass.PutElement( slaveInterp.aliasTable, inString, alias ); // Create the new command. We must do it after deleting any old command, // because the alias may be pointing at a renamed alias, as in: // // interp alias {} foo {} bar # Create an alias "foo" // rename foo zop # Now rename the alias // interp alias {} foo {} zop # Now recreate "foo"... SupportClass.PutElement( masterInterp.targetTable, alias.slaveCmd, slaveInterp ); interp.setResult( name ); }