Esempio n. 1
0
    internal static ParseResult parseNestedCmd( Interp interp, string inString, int index, int length )
    {
      CharPointer script;
      TclObject obj;

      // Check for the easy case where the last character in the string is '['.
      if ( index == length )
      {
        throw new TclException( interp, "missing close-bracket" );
      }

      script = new CharPointer( inString );
      script.index = index;

      interp.evalFlags |= Parser.TCL_BRACKET_TERM;
      Parser.eval2( interp, script.array, script.index, length - index, 0 );
      obj = interp.getResult();
      obj.preserve();
      return ( new ParseResult( obj, index + interp.termOffset + 1 ) );
    }
Esempio n. 2
0
		/// <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;
    }
Esempio n. 3
0
    /// <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;
    }
Esempio n. 4
0
    public static ParseResult parseVar( Interp interp, string inString )
    {
      TclParse parse;
      TclObject obj;

      System.Diagnostics.Debug.WriteLine( "Entered parseVar()" );
      System.Diagnostics.Debug.Write( "now to parse var off the string \"" + inString + "\"" );


      CharPointer src = new CharPointer( inString );
      parse = parseVarName( interp, src.array, src.index, -1, null, false );
      if ( parse.result != TCL.CompletionCode.OK )
      {

        throw new TclException( interp, interp.getResult().ToString() );
      }

      try
      {
        System.Diagnostics.Debug.Write( "parsed " + parse.numTokens + " tokens" );

        if ( parse.numTokens == 1 )
        {
          // There isn't a variable name after all: the $ is just a $.
          return new ParseResult( "$", 1 );
        }

        obj = evalTokens( interp, parse.tokenList, 0, parse.numTokens );
        if ( !obj.Shared )
        {
          throw new TclRuntimeError( "parseVar got temporary object from evalTokens" );
        }
        return new ParseResult( obj, parse.tokenList[0].size );
      }
      finally
      {
        parse.release(); // Release parser resources
      }
    }
Esempio n. 5
0
    internal static TclObject evalTokens( Interp interp, TclToken[] tokenList, int tIndex, int count )
    {
      TclObject result, index, value;
      TclToken token;
      string p = null;
      string varName;
      BackSlashResult bs;

      // The only tricky thing about this procedure is that it attempts to
      // avoid object creation and string copying whenever possible.  For
      // example, if the value is just a nested command, then use the
      // command's result object directly.

      result = null;
      for ( ; count > 0; count-- )
      {
        token = tokenList[tIndex];

        // The switch statement below computes the next value to be
        // concat to the result, as either a range of text or an
        // object.

        value = null;
        switch ( token.type )
        {

          case TCL_TOKEN_TEXT:
            p = token.TokenString;
            break;


          case TCL_TOKEN_BS:
            bs = backslash( token.script_array, token.script_index );
            if ( bs.isWordSep )
            {
              p = "\\" + bs.c;
            }
            else
            {
              System.Char ch = bs.c;
              p = ch.ToString();
            }
            break;


          case TCL_TOKEN_COMMAND:
            interp.evalFlags |= Parser.TCL_BRACKET_TERM;
            token.script_index++;

            //should the nest level be changed???
            //interp.nestLevel++;

            eval2( interp, token.script_array, token.script_index, token.size - 2, 0 );

            token.script_index--;
            //interp.nestLevel--;
            value = interp.getResult();
            break;


          case TCL_TOKEN_VARIABLE:
            if ( token.numComponents == 1 )
            {
              index = null;
            }
            else
            {
              index = evalTokens( interp, tokenList, tIndex + 2, token.numComponents - 1 );
              if ( index == null )
              {
                return null;
              }
            }
            varName = tokenList[tIndex + 1].TokenString;

            // In order to get the existing expr parser to work with the
            // new Parser, we test the interp.noEval flag which is set
            // by the expr parser.  If it is != 0, then we do not evaluate 
            // the variable.  This should be removed when the new expr
            // parser is implemented.

            if ( interp.noEval == 0 )
            {
              if ( index != null )
              {
                try
                {

                  value = interp.getVar( varName, index.ToString(), 0 );
                }
                finally
                {
                  index.release();
                }
              }
              else
              {
                value = interp.getVar( varName, null, 0 );
              }
            }
            else
            {
              value = TclString.newInstance( "" );
              value.preserve();
            }
            count -= token.numComponents;
            tIndex += token.numComponents;
            break;


          default:
            throw new TclRuntimeError( "unexpected token type in evalTokens" );

        }

        // If value isn't null, the next piece of text comes from that
        // object; otherwise, take value of p.

        if ( result == null )
        {
          if ( value != null )
          {
            result = value;
          }
          else
          {
            result = TclString.newInstance( p );
          }
          result.preserve();
        }
        else
        {
          if ( result.Shared )
          {
            result.release();
            result = result.duplicate();
            result.preserve();
          }
          if ( value != null )
          {

            p = value.ToString();
          }
          TclString.append( result, p );
        }
        tIndex++;
      }
      return result;
    }
    /// <summary> CallTraces -> callTraces
    /// 
    /// This procedure is invoked to find and invoke relevant
    /// trace procedures associated with a particular operation on
    /// a variable.  This procedure invokes traces both on the
    /// variable and on its containing array (where relevant).
    /// 
    /// </summary>
    /// <param name="interp">Interpreter containing variable.
    /// </param>
    /// <param name="array">array variable that contains the variable, or null
    /// if the variable isn't an element of an array.
    /// </param>
    /// <param name="var">Variable whose traces are to be invoked.
    /// </param>
    /// <param name="part1">the first part of a variable name.
    /// </param>
    /// <param name="part2">the second part of a variable name.
    /// </param>
    /// <param name="flags">Flags to pass to trace procedures: indicates
    /// what's happening to variable, plus other stuff like
    /// TCL.VarFlag.GLOBAL_ONLY, TCL.VarFlag.NAMESPACE_ONLY, and TCL.VarFlag.INTERP_DESTROYED.
    /// </param>
    /// <returns> null if no trace procedures were invoked, or
    /// if all the invoked trace procedures returned successfully.
    /// The return value is non-null if a trace procedure returned an
    /// error (in this case no more trace procedures were invoked
    /// after the error was returned). In this case the return value
    /// is a pointer to a string describing the error.
    /// </returns>

    static protected internal string callTraces( Interp interp, Var array, Var var, string part1, string part2, TCL.VarFlag flags )
    {
      TclObject oldResult;
      int i;

      // If there are already similar trace procedures active for the
      // variable, don't call them again.

      if ( ( var.flags & VarFlags.TRACE_ACTIVE ) != 0 )
      {
        return null;
      }
      var.flags |= VarFlags.TRACE_ACTIVE;
      var.refCount++;

      // If the variable name hasn't been parsed into array name and
      // element, do it here.  If there really is an array element,
      // make a copy of the original name so that nulls can be
      // inserted into it to separate the names (can't modify the name
      // string in place, because the string might get used by the
      // callbacks we invoke).

      // FIXME : come up with parsing code to use for all situations!
      if ( (System.Object)part2 == null )
      {
        int len = part1.Length;

        if ( len > 0 )
        {
          if ( part1[len - 1] == ')' )
          {
            for ( i = 0; i < len - 1; i++ )
            {
              if ( part1[i] == '(' )
              {
                break;
              }
            }
            if ( i < len - 1 )
            {
              if ( i < len - 2 )
              {
                part2 = part1.Substring( i + 1, ( len - 1 ) - ( i + 1 ) );
                part1 = part1.Substring( 0, ( i ) - ( 0 ) );
              }
            }
          }
        }
      }

      oldResult = interp.getResult();
      oldResult.preserve();
      interp.resetResult();

      try
      {
        // Invoke traces on the array containing the variable, if relevant.

        if ( array != null )
        {
          array.refCount++;
        }
        if ( ( array != null ) && ( array.traces != null ) )
        {
          for ( i = 0; ( array.traces != null ) && ( i < array.traces.Count ); i++ )
          {
            TraceRecord rec = (TraceRecord)array.traces[i];
            if ( ( rec.flags & flags ) != 0 )
            {
              try
              {
                rec.trace.traceProc( interp, part1, part2, flags );
              }
              catch ( TclException e )
              {
                if ( ( flags & TCL.VarFlag.TRACE_UNSETS ) == 0 )
                {

                  return interp.getResult().ToString();
                }
              }
            }
          }
        }

        // Invoke traces on the variable itself.

        if ( ( flags & TCL.VarFlag.TRACE_UNSETS ) != 0 )
        {
          flags |= TCL.VarFlag.TRACE_DESTROYED;
        }

        for ( i = 0; ( var.traces != null ) && ( i < var.traces.Count ); i++ )
        {
          TraceRecord rec = (TraceRecord)var.traces[i];
          if ( ( rec.flags & flags ) != 0 )
          {
            try
            {
              rec.trace.traceProc( interp, part1, part2, flags );
            }
            catch ( TclException e )
            {
              if ( ( flags & TCL.VarFlag.TRACE_UNSETS ) == 0 )
              {

                return interp.getResult().ToString();
              }
            }
          }
        }

        return null;
      }
      finally
      {
        if ( array != null )
        {
          array.refCount--;
        }
        var.flags &= ~VarFlags.TRACE_ACTIVE;
        var.refCount--;

        interp.setResult( oldResult );
        oldResult.release();
      }
    }
    internal void transferResult( Interp sourceInterp, TCL.CompletionCode result )
    {
      if ( sourceInterp == this )
      {
        return;
      }

      if ( result == TCL.CompletionCode.ERROR )
      {
        TclObject obj;

        // An error occurred, so transfer error information from the source
        // interpreter to the target interpreter.  Setting the flags tells
        // the target interp that it has inherited a partial traceback
        // chain, not just a simple error message.

        if ( !sourceInterp.errAlreadyLogged )
        {
          sourceInterp.addErrorInfo( "" );
        }
        sourceInterp.errAlreadyLogged = true;

        resetResult();

        obj = sourceInterp.getVar( "errorInfo", TCL.VarFlag.GLOBAL_ONLY );
        setVar( "errorInfo", obj, TCL.VarFlag.GLOBAL_ONLY );

        obj = sourceInterp.getVar( "errorCode", TCL.VarFlag.GLOBAL_ONLY );
        setVar( "errorCode", obj, TCL.VarFlag.GLOBAL_ONLY );

        errInProgress = true;
        errCodeSet = true;
      }

      returnCode = result;
      setResult( sourceInterp.getResult() );
      sourceInterp.resetResult();

      if ( result != TCL.CompletionCode.OK )
      {

        throw new TclException( this, getResult().ToString(), result );
      }
    }
Esempio n. 8
0
		/*
		*----------------------------------------------------------------------
		*
		* NamespaceEvalCmd -> evalCmd
		*
		*	Invoked to implement the "namespace eval" command. Executes
		*	commands in a namespace. If the namespace does not already exist,
		*	it is created. Handles the following syntax:
		*
		*	    namespace eval name arg ?arg...?
		*
		*	If more than one arg argument is specified, the command that is
		*	executed is the result of concatenating the arguments together with
		*	a space between each argument.
		*
		* Results:
		*  Returns if successful, raises TclException if something goes wrong.
		*
		* Side effects:
		*	Returns the result of the command in the interpreter's result
		*	object. If anything goes wrong, this procedure returns an error
		*	message as the result.
		*
		*----------------------------------------------------------------------
		*/
		
		private static void  evalCmd(Interp interp, TclObject[] objv)
		{
			Namespace namespace_Renamed;
			CallFrame frame;
			string cmd;
			string name;
			int length;
			
			if (objv.Length < 4)
			{
				throw new TclNumArgsException(interp, 2, objv, "name arg ?arg...?");
			}
			
			// Try to resolve the namespace reference, caching the result in the
			// namespace object along the way.
			
			namespace_Renamed = getNamespaceFromObj(interp, objv[2]);
			
			// If the namespace wasn't found, try to create it.
			
			if (namespace_Renamed == null)
			{
				
				name = objv[2].ToString();
				namespace_Renamed = createNamespace(interp, name, null);
				if (namespace_Renamed == null)
				{
					// FIXME : result hack, we get the interp result and throw it!
					
					throw new TclException(interp, interp.getResult().ToString());
				}
			}
			
			// Make the specified namespace the current namespace and evaluate
			// the command(s).
			
			frame = interp.newCallFrame();
			pushCallFrame(interp, frame, namespace_Renamed, false);
			
			try
			{
				if (objv.Length == 4)
				{
					interp.eval(objv[3], 0);
				}
				else
				{
					cmd = Util.concat(3, objv.Length, objv);
					
					// eval() will delete the object when it decrements its
					// refcount after eval'ing it.
					
					interp.eval(cmd); // do not pass TCL_EVAL_DIRECT, for compiler only
				}
			}
			catch (TclException ex)
			{
				if (ex.getCompletionCode() == TCL.CompletionCode.ERROR)
				{
					interp.addErrorInfo("\n    (in namespace eval \"" + namespace_Renamed.fullName + "\" script line " + interp.errorLine + ")");
				}
				throw ex;
			}
			finally
			{
				popCallFrame(interp);
			}
			
			return ;
		}
Esempio n. 9
0
  /*
  ** 2009 July 17
  **
  ** The author disclaims copyright to this source code.  In place of
  ** a legal notice, here is a blessing:
  **
  **    May you do good and not evil.
  **    May you find forgiveness for yourself and forgive others.
  **    May you share freely, never taking more than you give.
  **
  *************************************************************************
  ** This file contains code to implement the "sqlite" test harness
  ** which runs TCL commands for testing the C#-SQLite port.
  **
  ** $Header$
  */
  public static void Main(string[] args)
  {
    // Array of command-line argument strings.
    {
      string fileName = null;

      // Create the interpreter. This will also create the built-in
      // Tcl commands.

      Interp interp = new Interp();

      // Make command-line arguments available in the Tcl variables "argc"
      // and "argv".  If the first argument doesn't start with a "-" then
      // strip it off and use it as the name of a script file to process.
      // We also set the argv0 and TCL.Tcl_interactive vars here.

      if ((args.Length > 0) && !(args[0].StartsWith("-")))
      {
        fileName = args[0];
      }

      TclObject argv = TclList.newInstance();
      argv.preserve();
      try
      {
        int i = 0;
        int argc = args.Length;
        if ((System.Object)fileName == null)
        {
          interp.setVar("argv0", "tcl.lang.Shell", TCL.VarFlag.GLOBAL_ONLY);
          interp.setVar("tcl_interactive", "1", TCL.VarFlag.GLOBAL_ONLY);
        }
        else
        {
          interp.setVar("argv0", fileName, TCL.VarFlag.GLOBAL_ONLY);
          interp.setVar("tcl_interactive", "0", TCL.VarFlag.GLOBAL_ONLY);
          i++;
          argc--;
        }
        for (; i < args.Length; i++)
        {
          TclList.append(interp, argv, TclString.newInstance(args[i]));
        }
        interp.setVar("argv", argv, TCL.VarFlag.GLOBAL_ONLY);
        interp.setVar("argc", System.Convert.ToString(argc), TCL.VarFlag.GLOBAL_ONLY);
      }
      catch (TclException e)
      {
        throw new TclRuntimeError("unexpected TclException: " + e.Message);
      }
      finally
      {
        argv.release();
      }

      // Normally we would do application specific initialization here.
      // However, that feature is not currently supported.
      // If a script file was specified then just source that file
      // and quit.

      Console.WriteLine("C#-TCL version " + Assembly.GetExecutingAssembly().GetName().Version.ToString());
      Console.WriteLine("==============================================================");
      Console.WriteLine("");

      if ((System.Object)fileName != null)
      {
        try
        {
          interp.evalFile(fileName);
        }
        catch (TclException e)
        {
          TCL.CompletionCode code = e.getCompletionCode();
          if (code == TCL.CompletionCode.RETURN)
          {
            code = interp.updateReturnInfo();
            if (code != TCL.CompletionCode.OK)
            {
              System.Console.Error.WriteLine("command returned bad code: " + code);
              if (tcl.lang.ConsoleThread.debug) System.Diagnostics.Debug.WriteLine("command returned bad code: " + code);
            }
          }
          else if (code == TCL.CompletionCode.ERROR)
          {
            System.Console.Error.WriteLine(interp.getResult().ToString());
            if (tcl.lang.ConsoleThread.debug) System.Diagnostics.Debug.WriteLine(interp.getResult().ToString());
            System.Diagnostics.Debug.Assert(false, interp.getResult().ToString());
          }
          else
          {
            System.Console.Error.WriteLine("command returned bad code: " + code);
            if (tcl.lang.ConsoleThread.debug) System.Diagnostics.Debug.WriteLine("command returned bad code: " + code);
          }
        }

        // Note that if the above interp.evalFile() returns the main
        // thread will exit.  This may bring down the VM and stop
        // the execution of Tcl.
        //
        // If the script needs to handle events, it must call
        // vwait or do something similar.
        //
        // Note that the script can create AWT widgets. This will
        // start an AWT event handling thread and keep the VM up. However,
        // the interpreter thread (the same as the main thread) would
        // have exited and no Tcl scripts can be executed.

        interp.dispose();

        System.Environment.Exit(0);
      }

      if ((System.Object)fileName == null)
      {
        // We are running in interactive mode. Start the ConsoleThread
        // that loops, grabbing stdin and passing it to the interp.

        ConsoleThread consoleThread = new ConsoleThread(interp);
        consoleThread.IsBackground = true;
        consoleThread.Start();

        // Loop forever to handle user input events in the command line.

        Notifier notifier = interp.getNotifier();
        while (true)
        {
          // process events until "exit" is called.

          notifier.doOneEvent(TCL.ALL_EVENTS);
        }
      }
    }
  }