Esempio n. 1
0
    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;
    }
Esempio n. 2
0
		public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv)
		{
			if (argv.Length != 2)
			{
				throw new TclNumArgsException(interp, 1, argv, "name");
			}
			
			VwaitTrace trace = new VwaitTrace();
			Var.traceVar(interp, argv[1], TCL.VarFlag.GLOBAL_ONLY | TCL.VarFlag.TRACE_WRITES | TCL.VarFlag.TRACE_UNSETS, trace);
			
			int foundEvent = 1;
			while (!trace.done && (foundEvent != 0))
			{
				foundEvent = interp.getNotifier().doOneEvent(TCL.ALL_EVENTS);
			}
			
			Var.untraceVar(interp, argv[1], TCL.VarFlag.GLOBAL_ONLY | TCL.VarFlag.TRACE_WRITES | TCL.VarFlag.TRACE_UNSETS, trace);
			
			// Clear out the interpreter's result, since it may have been set
			// by event handlers.
			
			interp.resetResult();
			
			if (foundEvent == 0)
			{
				
				throw new TclException(interp, "can't wait for variable \"" + argv[1] + "\":  would wait forever");
			}
      return TCL.CompletionCode.RETURN;
    }
Esempio n. 3
0
    /// <summary> Tcl_UpvarObjCmd -> UpvarCmd.cmdProc
    /// 
    /// This procedure is invoked to process the "upvar" Tcl command.
    /// See the user documentation for details on what it does.
    /// </summary>

    public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv )
    {
      CallFrame frame;
      string frameSpec, otherVarName, myVarName;
      int p;
      int objc = objv.Length, objv_index;
      int result;

      if ( objv.Length < 3 )
      {
        throw new TclNumArgsException( interp, 1, objv, "?level? otherVar localVar ?otherVar localVar ...?" );
      }

      // Find the call frame containing each of the "other variables" to be
      // linked to. 


      frameSpec = objv[1].ToString();
      // Java does not support passing a reference by refernece so use an array
      CallFrame[] frameArr = new CallFrame[1];
      result = CallFrame.getFrame( interp, frameSpec, frameArr );
      frame = frameArr[0];
      objc -= ( result + 1 );
      if ( ( objc & 1 ) != 0 )
      {
        throw new TclNumArgsException( interp, 1, objv, "?level? otherVar localVar ?otherVar localVar ...?" );
      }
      objv_index = result + 1;


      // Iterate over each (other variable, local variable) pair.
      // Divide the other variable name into two parts, then call
      // MakeUpvar to do all the work of linking it to the local variable.

      for ( ; objc > 0; objc -= 2, objv_index += 2 )
      {

        myVarName = objv[objv_index + 1].ToString();

        otherVarName = objv[objv_index].ToString();

        int otherLength = otherVarName.Length;
        p = otherVarName.IndexOf( (System.Char)'(' );
        if ( ( p != -1 ) && ( otherVarName[otherLength - 1] == ')' ) )
        {
          // This is an array variable name
          Var.makeUpvar( interp, frame, otherVarName.Substring( 0, ( p ) - ( 0 ) ), otherVarName.Substring( p + 1, ( otherLength - 1 ) - ( p + 1 ) ), 0, myVarName, 0 );
        }
        else
        {
          // This is a scalar variable name
          Var.makeUpvar( interp, frame, otherVarName, null, 0, myVarName, 0 );
        }
      }
      interp.resetResult();
      return TCL.CompletionCode.RETURN;
    }
Esempio n. 4
0
    /// <summary> This procedure is invoked to process the "while" 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 script causes error.
    /// </exception>

    public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv )
    {
      if ( argv.Length != 3 )
      {
        throw new TclNumArgsException( interp, 1, argv, "test command" );
      }

      string test = argv[1].ToString();
      TclObject command = argv[2];

      {
        while ( interp.expr.evalBoolean( interp, test ) )
        {
          try
          {
            interp.eval( command, 0 );
          }
          catch ( TclException e )
          {
            switch ( e.getCompletionCode() )
            {

              case TCL.CompletionCode.BREAK:
                goto loop_brk;


              case TCL.CompletionCode.CONTINUE:
                continue;


              case TCL.CompletionCode.ERROR:
                interp.addErrorInfo( "\n    (\"while\" body line " + interp.errorLine + ")" );
                throw;


              default:
                throw;

            }
          }
        }
      }

loop_brk:
      ;


      interp.resetResult();
      return TCL.CompletionCode.RETURN;
    }
Esempio n. 5
0
		/// <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);
				}
			}
		}
Esempio n. 6
0
    /// <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;
    }
Esempio n. 7
0
        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;
        }
Esempio n. 8
0
    public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv )
    {
      int flags;

      if ( argv.Length == 1 )
      {
        flags = TCL.ALL_EVENTS | TCL.DONT_WAIT;
      }
      else if ( argv.Length == 2 )
      {
        TclIndex.get( interp, argv[1], validOpts, "option", 0 );

        /*
        * Since we just have one valid option, if the above call returns
        * without an exception, we've got "idletasks" (or abreviations).
        */

        flags = TCL.IDLE_EVENTS | TCL.DONT_WAIT;
      }
      else
      {
        throw new TclNumArgsException( interp, 1, argv, "?idletasks?" );
      }

      while ( interp.getNotifier().doOneEvent( flags ) != 0 )
      {
        /* Empty loop body */
      }

      /*
      * Must clear the interpreter's result because event handlers could
      * have executed commands.
      */

      interp.resetResult();
      return TCL.CompletionCode.RETURN;
    }
Esempio n. 9
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;
    }
    /// <summary>----------------------------------------------------------------------
    /// 
    /// Tcl_StringObjCmd -> StringCmd.cmdProc
    /// 
    /// This procedure is invoked to process the "string" Tcl command.
    /// See the user documentation for details on what it does.
    /// 
    /// Results:
    /// None.
    /// 
    /// Side effects:
    /// See the user documentation.
    /// 
    /// ----------------------------------------------------------------------
    /// </summary>

    public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv )
    {
      if ( objv.Length < 2 )
      {
        throw new TclNumArgsException( interp, 1, objv, "option arg ?arg ...?" );
      }
      int index = TclIndex.get( interp, objv[1], options, "option", 0 );

      switch ( index )
      {

        case STR_EQUAL:
        case STR_COMPARE:
          {

            if ( objv.Length < 4 || objv.Length > 7 )
            {
              throw new TclNumArgsException( interp, 2, objv, "?-nocase? ?-length int? string1 string2" );
            }

            bool nocase = false;
            int reqlength = -1;
            for ( int i = 2; i < objv.Length - 2; i++ )
            {

              string string2 = objv[i].ToString();
              int length2 = string2.Length;
              if ( ( length2 > 1 ) && "-nocase".StartsWith( string2 ) )
              {
                nocase = true;
              }
              else if ( ( length2 > 1 ) && "-length".StartsWith( string2 ) )
              {
                if ( i + 1 >= objv.Length - 2 )
                {
                  throw new TclNumArgsException( interp, 2, objv, "?-nocase? ?-length int? string1 string2" );
                }
                reqlength = TclInteger.get( interp, objv[++i] );
              }
              else
              {
                throw new TclException( interp, "bad option \"" + string2 + "\": must be -nocase or -length" );
              }
            }


            string string1 = objv[objv.Length - 2].ToString();

            string string3 = objv[objv.Length - 1].ToString();
            int length1 = string1.Length;
            int length3 = string3.Length;

            // This is the min length IN BYTES of the two strings

            int length = ( length1 < length3 ) ? length1 : length3;

            int match;

            if ( reqlength == 0 )
            {
              // Anything matches at 0 chars, right?

              match = 0;
            }
            else if ( nocase || ( ( reqlength > 0 ) && ( reqlength <= length ) ) )
            {
              // In Java, strings are always encoded in unicode, so we do
              // not need to worry about individual char lengths

              // Do the reqlength check again, against 0 as well for
              // the benfit of nocase

              if ( ( reqlength > 0 ) && ( reqlength < length ) )
              {
                length = reqlength;
              }
              else if ( reqlength < 0 )
              {
                // The requested length is negative, so we ignore it by
                // setting it to the longer of the two lengths.

                reqlength = ( length1 > length3 ) ? length1 : length3;
              }
              if ( nocase )
              {
                string1 = string1.ToLower();
                string3 = string3.ToLower();
              }
              match = System.Globalization.CultureInfo.InvariantCulture.CompareInfo.Compare( string1, 0, length, string3, 0, length, System.Globalization.CompareOptions.Ordinal );
              // match = string1.Substring(0, (length) - (0)).CompareTo(string3.Substring(0, (length) - (0)));

              if ( ( match == 0 ) && ( reqlength > length ) )
              {
                match = length1 - length3;
              }
            }
            else
            {
              match = System.Globalization.CultureInfo.InvariantCulture.CompareInfo.Compare( string1, 0, length, string3, 0, length, System.Globalization.CompareOptions.Ordinal );
              // ATK match = string1.Substring(0, (length) - (0)).CompareTo(string3.Substring(0, (length) - (0)));
              if ( match == 0 )
              {
                match = length1 - length3;
              }
            }

            if ( index == STR_EQUAL )
            {
              interp.setResult( ( match != 0 ) ? false : true );
            }
            else
            {
              interp.setResult( ( ( match > 0 ) ? 1 : ( match < 0 ) ? -1 : 0 ) );
            }
            break;
          }


        case STR_FIRST:
          {
            if ( objv.Length < 4 || objv.Length > 5 )
            {
              throw new TclNumArgsException( interp, 2, objv, "subString string ?startIndex?" );
            }

            string string1 = objv[2].ToString();

            string string2 = objv[3].ToString();
            int length2 = string2.Length;

            int start = 0;

            if ( objv.Length == 5 )
            {
              // If a startIndex is specified, we will need to fast
              // forward to that point in the string before we think
              // about a match.

              start = Util.getIntForIndex( interp, objv[4], length2 - 1 );
              if ( start >= length2 )
              {
                interp.setResult( -1 );
                return TCL.CompletionCode.RETURN;
              }
            }

            if ( string1.Length == 0 )
            {
              interp.setResult( -1 );
            }
            else
            {

              interp.setResult( string2.IndexOf( string1, start ) );
            }
            break;
          }


        case STR_INDEX:
          {
            if ( objv.Length != 4 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string charIndex" );
            }


            string string1 = objv[2].ToString();
            int length1 = string1.Length;

            int i = Util.getIntForIndex( interp, objv[3], length1 - 1 );

            if ( ( i >= 0 ) && ( i < length1 ) )
            {
              interp.setResult( string1.Substring( i, ( i + 1 ) - ( i ) ) );
            }
            break;
          }


        case STR_IS:
          {
            if ( objv.Length < 4 || objv.Length > 7 )
            {
              throw new TclNumArgsException( interp, 2, objv, "class ?-strict? ?-failindex var? str" );
            }
            index = TclIndex.get( interp, objv[2], isOptions, "class", 0 );

            bool strict = false;
            TclObject failVarObj = null;

            if ( objv.Length != 4 )
            {
              for ( int i = 3; i < objv.Length - 1; i++ )
              {

                string string2 = objv[i].ToString();
                int length2 = string2.Length;
                if ( ( length2 > 1 ) && "-strict".StartsWith( string2 ) )
                {
                  strict = true;
                }
                else if ( ( length2 > 1 ) && "-failindex".StartsWith( string2 ) )
                {
                  if ( i + 1 >= objv.Length - 1 )
                  {
                    throw new TclNumArgsException( interp, 3, objv, "?-strict? ?-failindex var? str" );
                  }
                  failVarObj = objv[++i];
                }
                else
                {
                  throw new TclException( interp, "bad option \"" + string2 + "\": must be -strict or -failindex" );
                }
              }
            }

            bool result = true;
            int failat = 0;

            // We get the objPtr so that we can short-cut for some classes
            // by checking the object type (int and double), but we need
            // the string otherwise, because we don't want any conversion
            // of type occuring (as, for example, Tcl_Get*FromObj would do

            TclObject obj = objv[objv.Length - 1];

            string string1 = obj.ToString();
            int length1 = string1.Length;
            if ( length1 == 0 )
            {
              if ( strict )
              {
                result = false;
              }
            }

            switch ( index )
            {

              case STR_IS_BOOL:
              case STR_IS_TRUE:
              case STR_IS_FALSE:
                {
                  if ( obj.InternalRep is TclBoolean )
                  {
                    if ( ( ( index == STR_IS_TRUE ) && !TclBoolean.get( interp, obj ) ) || ( ( index == STR_IS_FALSE ) && TclBoolean.get( interp, obj ) ) )
                    {
                      result = false;
                    }
                  }
                  else
                  {
                    try
                    {
                      bool i = TclBoolean.get( null, obj );
                      if ( ( ( index == STR_IS_TRUE ) && !i ) || ( ( index == STR_IS_FALSE ) && i ) )
                      {
                        result = false;
                      }
                    }
                    catch ( TclException e )
                    {
                      result = false;
                    }
                  }
                  break;
                }

              case STR_IS_DOUBLE:
                {
                  if ( ( obj.InternalRep is TclDouble ) || ( obj.InternalRep is TclInteger ) )
                  {
                    break;
                  }

                  // This is adapted from Tcl_GetDouble
                  //
                  // The danger in this function is that
                  // "12345678901234567890" is an acceptable 'double',
                  // but will later be interp'd as an int by something
                  // like [expr].  Therefore, we check to see if it looks
                  // like an int, and if so we do a range check on it.
                  // If strtoul gets to the end, we know we either
                  // received an acceptable int, or over/underflow

                  if ( Expression.looksLikeInt( string1, length1, 0 ) )
                  {
                    char c = string1[0];
                    int signIx = ( c == '-' || c == '+' ) ? 1 : 0;
                    StrtoulResult res = Util.strtoul( string1, signIx, 0 );
                    if ( res.index == length1 )
                    {
                      if ( res.errno == TCL.INTEGER_RANGE )
                      {
                        result = false;
                        failat = -1;
                      }
                      break;
                    }
                  }

                  char c2 = string1[0];
                  int signIx2 = ( c2 == '-' || c2 == '+' ) ? 1 : 0;
                  StrtodResult res2 = Util.strtod( string1, signIx2 );
                  if ( res2.errno == TCL.DOUBLE_RANGE )
                  {
                    // if (errno == ERANGE), then it was an over/underflow
                    // problem, but in this method, we only want to know
                    // yes or no, so bad flow returns 0 (false) and sets
                    // the failVarObj to the string length.

                    result = false;
                    failat = -1;
                  }
                  else if ( res2.index == 0 )
                  {
                    // In this case, nothing like a number was found

                    result = false;
                    failat = 0;
                  }
                  else
                  {
                    // Go onto SPACE, since we are
                    // allowed trailing whitespace

                    failat = res2.index;
                    for ( int i = res2.index; i < length1; i++ )
                    {
                      if ( !System.Char.IsWhiteSpace( string1[i] ) )
                      {
                        result = false;
                        break;
                      }
                    }
                  }
                  break;
                }

              case STR_IS_INT:
                {
                  if ( obj.InternalRep is TclInteger )
                  {
                    break;
                  }
                  bool isInteger = true;
                  try
                  {
                    TclInteger.get( null, obj );
                  }
                  catch ( TclException e )
                  {
                    isInteger = false;
                  }
                  if ( isInteger )
                  {
                    break;
                  }

                  char c = string1[0];
                  int signIx = ( c == '-' || c == '+' ) ? 1 : 0;
                  StrtoulResult res = Util.strtoul( string1, signIx, 0 );
                  if ( res.errno == TCL.INTEGER_RANGE )
                  {
                    // if (errno == ERANGE), then it was an over/underflow
                    // problem, but in this method, we only want to know
                    // yes or no, so bad flow returns false and sets
                    // the failVarObj to the string length.

                    result = false;
                    failat = -1;
                  }
                  else if ( res.index == 0 )
                  {
                    // In this case, nothing like a number was found

                    result = false;
                    failat = 0;
                  }
                  else
                  {
                    // Go onto SPACE, since we are
                    // allowed trailing whitespace

                    failat = res.index;
                    for ( int i = res.index; i < length1; i++ )
                    {
                      if ( !System.Char.IsWhiteSpace( string1[i] ) )
                      {
                        result = false;
                        break;
                      }
                    }
                  }
                  break;
                }

              case STR_IS_WIDE:
                {
                  if ( obj.InternalRep is TclLong )
                  {
                    break;
                  }
                  bool isInteger = true;
                  try
                  {
                    TclLong.get( null, obj );
                  }
                  catch ( TclException e )
                  {
                    isInteger = false;
                  }
                  if ( isInteger )
                  {
                    break;
                  }

                  char c = string1[0];
                  int signIx = ( c == '-' || c == '+' ) ? 1 : 0;
                  StrtoulResult res = Util.strtoul( string1, signIx, 0 );
                  if ( res.errno == TCL.INTEGER_RANGE )
                  {
                    // if (errno == ERANGE), then it was an over/underflow
                    // problem, but in this method, we only want to know
                    // yes or no, so bad flow returns false and sets
                    // the failVarObj to the string length.

                    result = false;
                    failat = -1;
                  }
                  else if ( res.index == 0 )
                  {
                    // In this case, nothing like a number was found

                    result = false;
                    failat = 0;
                  }
                  else
                  {
                    // Go onto SPACE, since we are
                    // allowed trailing whitespace

                    failat = res.index;
                    for ( int i = res.index; i < length1; i++ )
                    {
                      if ( !System.Char.IsWhiteSpace( string1[i] ) )
                      {
                        result = false;
                        break;
                      }
                    }
                  }
                  break;
                }

              default:
                {
                  for ( failat = 0; failat < length1; failat++ )
                  {
                    char c = string1[failat];
                    switch ( index )
                    {

                      case STR_IS_ASCII:

                        result = c < 0x80;
                        break;

                      case STR_IS_ALNUM:
                        result = System.Char.IsLetterOrDigit( c );
                        break;

                      case STR_IS_ALPHA:
                        result = System.Char.IsLetter( c );
                        break;

                      case STR_IS_DIGIT:
                        result = System.Char.IsDigit( c );
                        break;

                      case STR_IS_GRAPH:
                        result = ( ( 1 << (int)System.Char.GetUnicodeCategory( c ) ) & PRINT_BITS ) != 0 && c != ' ';
                        break;

                      case STR_IS_PRINT:
                        result = ( ( 1 << (int)System.Char.GetUnicodeCategory( c ) ) & PRINT_BITS ) != 0;
                        break;

                      case STR_IS_PUNCT:
                        result = ( ( 1 << (int)System.Char.GetUnicodeCategory( c ) ) & PUNCT_BITS ) != 0;
                        break;

                      case STR_IS_UPPER:
                        result = System.Char.IsUpper( c );
                        break;

                      case STR_IS_SPACE:
                        result = System.Char.IsWhiteSpace( c );
                        break;

                      case STR_IS_CONTROL:
                        result = ( System.Char.GetUnicodeCategory( c ) == System.Globalization.UnicodeCategory.Control );
                        break;

                      case STR_IS_LOWER:
                        result = System.Char.IsLower( c );
                        break;

                      case STR_IS_WORD:
                        result = ( ( 1 << (int)System.Char.GetUnicodeCategory( c ) ) & WORD_BITS ) != 0;
                        break;

                      case STR_IS_XDIGIT:
                        result = "0123456789ABCDEFabcdef".IndexOf( c ) >= 0;
                        break;

                      default:
                        throw new TclRuntimeError( "unimplemented" );

                    }
                    if ( !result )
                    {
                      break;
                    }
                  }
                }
                break;

            }

            // Only set the failVarObj when we will return 0
            // and we have indicated a valid fail index (>= 0)

            if ( ( !result ) && ( failVarObj != null ) )
            {
              interp.setVar( failVarObj, TclInteger.newInstance( failat ), 0 );
            }
            interp.setResult( result );
            break;
          }


        case STR_LAST:
          {
            if ( objv.Length < 4 || objv.Length > 5 )
            {
              throw new TclNumArgsException( interp, 2, objv, "subString string ?startIndex?" );
            }

            string string1 = objv[2].ToString();

            string string2 = objv[3].ToString();
            int length2 = string2.Length;

            int start = 0;
            if ( objv.Length == 5 )
            {
              // If a startIndex is specified, we will need to fast
              // forward to that point in the string before we think
              // about a match.

              start = Util.getIntForIndex( interp, objv[4], length2 - 1 );
              if ( start < 0 )
              {
                interp.setResult( -1 );
                break;
              }
              else if ( start < length2 )
              {
                string2 = string2.Substring( 0, ( start + 1 ) - ( 0 ) );
              }
            }

            if ( string1.Length == 0 )
            {
              interp.setResult( -1 );
            }
            else
            {
              interp.setResult( string2.LastIndexOf( string1 ) );
            }
            break;
          }


        case STR_BYTELENGTH:
          if ( objv.Length != 3 )
          {
            throw new TclNumArgsException( interp, 2, objv, "string" );
          }

          interp.setResult( Utf8Count( objv[2].ToString() ) );
          break;


        case STR_LENGTH:
          {
            if ( objv.Length != 3 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string" );
            }

            interp.setResult( objv[2].ToString().Length );
            break;
          }


        case STR_MAP:
          {
            if ( objv.Length < 4 || objv.Length > 5 )
            {
              throw new TclNumArgsException( interp, 2, objv, "?-nocase? charMap string" );
            }

            bool nocase = false;
            if ( objv.Length == 5 )
            {

              string string2 = objv[2].ToString();
              int length2 = string2.Length;
              if ( ( length2 > 1 ) && "-nocase".StartsWith( string2 ) )
              {
                nocase = true;
              }
              else
              {
                throw new TclException( interp, "bad option \"" + string2 + "\": must be -nocase" );
              }
            }

            TclObject[] mapElemv = TclList.getElements( interp, objv[objv.Length - 2] );
            if ( mapElemv.Length == 0 )
            {
              // empty charMap, just return whatever string was given

              interp.setResult( objv[objv.Length - 1] );
            }
            else if ( ( mapElemv.Length % 2 ) != 0 )
            {
              // The charMap must be an even number of key/value items

              throw new TclException( interp, "char map list unbalanced" );
            }

            string string1 = objv[objv.Length - 1].ToString();
            string cmpString1;
            if ( nocase )
            {
              cmpString1 = string1.ToLower();
            }
            else
            {
              cmpString1 = string1;
            }
            int length1 = string1.Length;
            if ( length1 == 0 )
            {
              // Empty input string, just stop now

              break;
            }

            // Precompute pointers to the unicode string and length.
            // This saves us repeated function calls later,
            // significantly speeding up the algorithm.

            string[] mapStrings = new string[mapElemv.Length];
            int[] mapLens = new int[mapElemv.Length];
            for ( int ix = 0; ix < mapElemv.Length; ix++ )
            {

              mapStrings[ix] = mapElemv[ix].ToString();
              mapLens[ix] = mapStrings[ix].Length;
            }
            string[] cmpStrings;
            if ( nocase )
            {
              cmpStrings = new string[mapStrings.Length];
              for ( int ix = 0; ix < mapStrings.Length; ix++ )
              {
                cmpStrings[ix] = mapStrings[ix].ToLower();
              }
            }
            else
            {
              cmpStrings = mapStrings;
            }

            TclObject result = TclString.newInstance( "" );
            int p, str1;
            for ( p = 0, str1 = 0; str1 < length1; str1++ )
            {
              for ( index = 0; index < mapStrings.Length; index += 2 )
              {
                // Get the key string to match on

                string string2 = mapStrings[index];
                int length2 = mapLens[index];
                if ( ( length2 > 0 ) && ( cmpString1.Substring( str1 ).StartsWith( cmpStrings[index] ) ) )
                {
                  if ( p != str1 )
                  {
                    // Put the skipped chars onto the result first

                    TclString.append( result, string1.Substring( p, ( str1 ) - ( p ) ) );
                    p = str1 + length2;
                  }
                  else
                  {
                    p += length2;
                  }

                  // Adjust len to be full length of matched string

                  str1 = p - 1;

                  // Append the map value to the unicode string

                  TclString.append( result, mapStrings[index + 1] );
                  break;
                }
              }
            }

            if ( p != str1 )
            {
              // Put the rest of the unmapped chars onto result

              TclString.append( result, string1.Substring( p, ( str1 ) - ( p ) ) );
            }
            interp.setResult( result );
            break;
          }


        case STR_MATCH:
          {
            if ( objv.Length < 4 || objv.Length > 5 )
            {
              throw new TclNumArgsException( interp, 2, objv, "?-nocase? pattern string" );
            }

            string string1, string2;
            if ( objv.Length == 5 )
            {

              string inString = objv[2].ToString();
              if ( !( ( inString.Length > 1 ) && "-nocase".StartsWith( inString ) ) )
              {
                throw new TclException( interp, "bad option \"" + inString + "\": must be -nocase" );
              }

              string1 = objv[4].ToString().ToLower();

              string2 = objv[3].ToString().ToLower();
            }
            else
            {

              string1 = objv[3].ToString();

              string2 = objv[2].ToString();
            }

            interp.setResult( Util.stringMatch( string1, string2 ) );
            break;
          }


        case STR_RANGE:
          {
            if ( objv.Length != 5 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string first last" );
            }


            string string1 = objv[2].ToString();
            int length1 = string1.Length;

            int first = Util.getIntForIndex( interp, objv[3], length1 - 1 );
            if ( first < 0 )
            {
              first = 0;
            }
            int last = Util.getIntForIndex( interp, objv[4], length1 - 1 );
            if ( last >= length1 )
            {
              last = length1 - 1;
            }

            if ( first > last )
            {
              interp.resetResult();
            }
            else
            {
              interp.setResult( string1.Substring( first, ( last + 1 ) - ( first ) ) );
            }
            break;
          }


        case STR_REPEAT:
          {
            if ( objv.Length != 4 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string count" );
            }

            int count = TclInteger.get( interp, objv[3] );


            string string1 = objv[2].ToString();
            if ( string1.Length > 0 )
            {
              TclObject tstr = TclString.newInstance( "" );
              for ( index = 0; index < count; index++ )
              {
                TclString.append( tstr, string1 );
              }
              interp.setResult( tstr );
            }
            break;
          }


        case STR_REPLACE:
          {
            if ( objv.Length < 5 || objv.Length > 6 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string first last ?string?" );
            }


            string string1 = objv[2].ToString();
            int length1 = string1.Length - 1;

            int first = Util.getIntForIndex( interp, objv[3], length1 );
            int last = Util.getIntForIndex( interp, objv[4], length1 );

            if ( ( last < first ) || ( first > length1 ) || ( last < 0 ) )
            {
              interp.setResult( objv[2] );
            }
            else
            {
              if ( first < 0 )
              {
                first = 0;
              }
              string start = string1.Substring( first );
              int ind = ( ( last > length1 ) ? length1 : last ) - first + 1;
              string end;
              if ( ind <= 0 )
              {
                end = start;
              }
              else if ( ind >= start.Length )
              {
                end = "";
              }
              else
              {
                end = start.Substring( ind );
              }

              TclObject tstr = TclString.newInstance( string1.Substring( 0, ( first ) - ( 0 ) ) );

              if ( objv.Length == 6 )
              {
                TclString.append( tstr, objv[5] );
              }
              if ( last < length1 )
              {
                TclString.append( tstr, end );
              }

              interp.setResult( tstr );
            }
            break;
          }


        case STR_TOLOWER:
        case STR_TOUPPER:
        case STR_TOTITLE:
          {
            if ( objv.Length < 3 || objv.Length > 5 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string ?first? ?last?" );
            }

            string string1 = objv[2].ToString();

            if ( objv.Length == 3 )
            {
              if ( index == STR_TOLOWER )
              {
                interp.setResult( string1.ToLower() );
              }
              else if ( index == STR_TOUPPER )
              {
                interp.setResult( string1.ToUpper() );
              }
              else
              {
                interp.setResult( Util.toTitle( string1 ) );
              }
            }
            else
            {
              int length1 = string1.Length - 1;
              int first = Util.getIntForIndex( interp, objv[3], length1 );
              if ( first < 0 )
              {
                first = 0;
              }
              int last = first;
              if ( objv.Length == 5 )
              {
                last = Util.getIntForIndex( interp, objv[4], length1 );
              }
              if ( last >= length1 )
              {
                last = length1;
              }
              if ( last < first )
              {
                interp.setResult( objv[2] );
                break;
              }

              string string2;
              StringBuilder buf = new StringBuilder();
              buf.Append( string1.Substring( 0, ( first ) - ( 0 ) ) );
              if ( last + 1 > length1 )
              {
                string2 = string1.Substring( first );
              }
              else
              {
                string2 = string1.Substring( first, ( last + 1 ) - ( first ) );
              }
              if ( index == STR_TOLOWER )
              {
                buf.Append( string2.ToLower() );
              }
              else if ( index == STR_TOUPPER )
              {
                buf.Append( string2.ToUpper() );
              }
              else
              {
                buf.Append( Util.toTitle( string2 ) );
              }
              if ( last + 1 <= length1 )
              {
                buf.Append( string1.Substring( last + 1 ) );
              }

              interp.setResult( buf.ToString() );
            }
            break;
          }


        case STR_TRIM:
          {
            if ( objv.Length == 3 )
            {
              // Case 1: "string trim str" --
              // Remove leading and trailing white space


              interp.setResult( objv[2].ToString().Trim() );
            }
            else if ( objv.Length == 4 )
            {

              // Case 2: "string trim str chars" --
              // Remove leading and trailing chars in the chars set


              string tmp = Util.TrimLeft( objv[2].ToString(), objv[3].ToString() );

              interp.setResult( Util.TrimRight( tmp, objv[3].ToString() ) );
            }
            else
            {
              // Case 3: Wrong # of args

              throw new TclNumArgsException( interp, 2, objv, "string ?chars?" );
            }
            break;
          }


        case STR_TRIMLEFT:
          {
            if ( objv.Length == 3 )
            {
              // Case 1: "string trimleft str" --
              // Remove leading and trailing white space


              interp.setResult( Util.TrimLeft( objv[2].ToString() ) );
            }
            else if ( objv.Length == 4 )
            {
              // Case 2: "string trimleft str chars" --
              // Remove leading and trailing chars in the chars set


              interp.setResult( Util.TrimLeft( objv[2].ToString(), objv[3].ToString() ) );
            }
            else
            {
              // Case 3: Wrong # of args

              throw new TclNumArgsException( interp, 2, objv, "string ?chars?" );
            }
            break;
          }


        case STR_TRIMRIGHT:
          {
            if ( objv.Length == 3 )
            {
              // Case 1: "string trimright str" --
              // Remove leading and trailing white space


              interp.setResult( Util.TrimRight( objv[2].ToString() ) );
            }
            else if ( objv.Length == 4 )
            {
              // Case 2: "string trimright str chars" --
              // Remove leading and trailing chars in the chars set


              interp.setResult( Util.TrimRight( objv[2].ToString(), objv[3].ToString() ) );
            }
            else
            {
              // Case 3: Wrong # of args

              throw new TclNumArgsException( interp, 2, objv, "string ?chars?" );
            }
            break;
          }


        case STR_WORDEND:
          {
            if ( objv.Length != 4 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string index" );
            }


            string string1 = objv[2].ToString();
            char[] strArray = string1.ToCharArray();
            int cur;
            int length1 = string1.Length;
            index = Util.getIntForIndex( interp, objv[3], length1 - 1 );

            if ( index < 0 )
            {
              index = 0;
            }
            if ( index >= length1 )
            {
              interp.setResult( length1 );
              return TCL.CompletionCode.RETURN;
            }
            for ( cur = index; cur < length1; cur++ )
            {
              char c = strArray[cur];
              if ( ( ( 1 << (int)System.Char.GetUnicodeCategory( c ) ) & WORD_BITS ) == 0 )
              {
                break;
              }
            }
            if ( cur == index )
            {
              cur = index + 1;
            }
            interp.setResult( cur );
            break;
          }


        case STR_WORDSTART:
          {
            if ( objv.Length != 4 )
            {
              throw new TclNumArgsException( interp, 2, objv, "string index" );
            }


            string string1 = objv[2].ToString();
            char[] strArray = string1.ToCharArray();
            int cur;
            int length1 = string1.Length;
            index = Util.getIntForIndex( interp, objv[3], length1 - 1 );

            if ( index > length1 )
            {
              index = length1 - 1;
            }
            if ( index < 0 )
            {
              interp.setResult( 0 );
              return TCL.CompletionCode.RETURN;
            }
            for ( cur = index; cur >= 0; cur-- )
            {
              char c = strArray[cur];
              if ( ( ( 1 << (int)System.Char.GetUnicodeCategory( c ) ) & WORD_BITS ) == 0 )
              {
                break;
              }
            }
            if ( cur != index )
            {
              cur += 1;
            }
            interp.setResult( cur );
            break;
          }
      }
      return TCL.CompletionCode.RETURN;
    }
    /// <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();
      }
    }
Esempio n. 12
0
    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;
    }
Esempio n. 13
0
    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--;
      }
    }
Esempio n. 14
0
    /// <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, "list first last" );
      }

      int size = TclList.getLength( interp, argv[1] );
      int first;
      int last;

      first = Util.getIntForIndex( interp, argv[2], size - 1 );
      last = Util.getIntForIndex( interp, argv[3], size - 1 );

      if ( last < 0 )
      {
        interp.resetResult();
        return TCL.CompletionCode.RETURN;
      }
      if ( first >= size )
      {
        interp.resetResult();
        return TCL.CompletionCode.RETURN;
      }
      if ( first <= 0 && last >= size )
      {
        interp.setResult( argv[1] );
        return TCL.CompletionCode.RETURN;
      }

      if ( first < 0 )
      {
        first = 0;
      }
      if ( first >= size )
      {
        first = size - 1;
      }
      if ( last < 0 )
      {
        last = 0;
      }
      if ( last >= size )
      {
        last = size - 1;
      }
      if ( first > last )
      {
        interp.resetResult();
        return TCL.CompletionCode.RETURN;
      }

      TclObject list = TclList.newInstance();

      list.preserve();
      try
      {
        for ( int i = first; i <= last; i++ )
        {
          TclList.append( interp, list, TclList.index( interp, argv[1], i ) );
        }
        interp.setResult( list );
      }
      finally
      {
        list.release();
      }
      return TCL.CompletionCode.RETURN;
    }
Esempio n. 15
0
		/*
		*----------------------------------------------------------------------
		*
		* Tcl_Import -> importList
		*
		*	Imports all of the commands matching a pattern into the namespace
		*	specified by namespace (or the current namespace if namespace
		*	is null). This is done by creating a new command (the "imported
		*	command") that points to the real command in its original namespace.
		*
		*      If matching commands are on the autoload path but haven't been
		*	loaded yet, this command forces them to be loaded, then creates
		*	the links to them.
		*
		* Results:
		*  Returns if successful, raises TclException if something goes wrong.
		*
		* Side effects:
		*	Creates new commands in the importing namespace. These indirect
		*	calls back to the real command and are deleted if the real commands
		*	are deleted.
		*
		*----------------------------------------------------------------------
		*/
		
		internal static void  importList(Interp interp, Namespace namespace_Renamed, string pattern, bool allowOverwrite)
		{
			Namespace ns, importNs;
			Namespace currNs = getCurrentNamespace(interp);
			string simplePattern, cmdName;
			IEnumerator search;
			WrappedCommand cmd, realCmd;
			ImportRef ref_Renamed;
			WrappedCommand autoCmd, importedCmd;
			ImportedCmdData data;
			bool wasExported;
			int i, result;
			
			// If the specified namespace is null, use the current namespace.
			
			if (namespace_Renamed == null)
			{
				ns = currNs;
			}
			else
			{
				ns = namespace_Renamed;
			}
			
			// First, invoke the "auto_import" command with the pattern
			// being imported.  This command is part of the Tcl library.
			// It looks for imported commands in autoloaded libraries and
			// loads them in.  That way, they will be found when we try
			// to create links below.
			
			autoCmd = findCommand(interp, "auto_import", null, TCL.VarFlag.GLOBAL_ONLY);
			
			if (autoCmd != null)
			{
				TclObject[] objv = new TclObject[2];
				
				objv[0] = TclString.newInstance("auto_import");
				objv[0].preserve();
				objv[1] = TclString.newInstance(pattern);
				objv[1].preserve();
				
				cmd = autoCmd;
				try
				{
					// Invoke the command with the arguments
					cmd.cmd.cmdProc(interp, objv);
				}
				finally
				{
					objv[0].release();
					objv[1].release();
				}
				
				interp.resetResult();
			}
			
			// From the pattern, find the namespace from which we are importing
			// and get the simple pattern (no namespace qualifiers or ::'s) at
			// the end.
			
			if (pattern.Length == 0)
			{
				throw new TclException(interp, "empty import pattern");
			}
			
			// Java does not support passing an address so we pass
			// an array of size 1 and then assign arr[0] to the value
			Namespace[] importNsArr = new Namespace[1];
			Namespace[] dummyArr = new Namespace[1];
			string[] simplePatternArr = new string[1];
			
			getNamespaceForQualName(interp, pattern, ns, TCL.VarFlag.LEAVE_ERR_MSG, importNsArr, dummyArr, dummyArr, simplePatternArr);
			
			importNs = importNsArr[0];
			simplePattern = simplePatternArr[0];
			
			if (importNs == null)
			{
				throw new TclException(interp, "unknown namespace in import pattern \"" + pattern + "\"");
			}
			if (importNs == ns)
			{
				if ((System.Object) pattern == (System.Object) simplePattern)
				{
					throw new TclException(interp, "no namespace specified in import pattern \"" + pattern + "\"");
				}
				else
				{
					throw new TclException(interp, "import pattern \"" + pattern + "\" tries to import from namespace \"" + importNs.name + "\" into itself");
				}
			}
			
			// Scan through the command table in the source namespace and look for
			// exported commands that match the string pattern. Create an "imported
			// command" in the current namespace for each imported command; these
			// commands redirect their invocations to the "real" command.
			
			
			for (search = importNs.cmdTable.Keys.GetEnumerator(); search.MoveNext(); )
			{
				
				cmdName = ((string) search.Current);
				if (Util.stringMatch(cmdName, simplePattern))
				{
					// The command cmdName in the source namespace matches the
					// pattern. Check whether it was exported. If it wasn't,
					// we ignore it.
					
					wasExported = false;
					for (i = 0; i < importNs.numExportPatterns; i++)
					{
						if (Util.stringMatch(cmdName, importNs.exportArray[i]))
						{
							wasExported = true;
							break;
						}
					}
					if (!wasExported)
					{
						continue;
					}
					
					// Unless there is a name clash, create an imported command
					// in the current namespace that refers to cmdPtr.
					
					if ((ns.cmdTable[cmdName] == null) || allowOverwrite)
					{
						// Create the imported command and its client data.
						// To create the new command in the current namespace, 
						// generate a fully qualified name for it.
						
						System.Text.StringBuilder ds;
						
						ds = new System.Text.StringBuilder();
						ds.Append(ns.fullName);
						if (ns != interp.globalNs)
						{
							ds.Append("::");
						}
						ds.Append(cmdName);
						
						// Check whether creating the new imported command in the
						// current namespace would create a cycle of imported->real
						// command references that also would destroy an existing
						// "real" command already in the current namespace.
						
						cmd = (WrappedCommand) importNs.cmdTable[cmdName];
						
						if (cmd.cmd is ImportedCmdData)
						{
							// This is actually an imported command, find
							// the real command it references
							realCmd = getOriginalCommand(cmd);
							if ((realCmd != null) && (realCmd.ns == currNs) && (currNs.cmdTable[cmdName] != null))
							{
								throw new TclException(interp, "import pattern \"" + pattern + "\" would create a loop containing command \"" + ds.ToString() + "\"");
							}
						}
						
						data = new ImportedCmdData();
						
						// Create the imported command inside the interp
						interp.createCommand(ds.ToString(), data);
						
						// Lookup in the namespace for the new WrappedCommand
						importedCmd = findCommand(interp, ds.ToString(), ns, (TCL.VarFlag.NAMESPACE_ONLY | TCL.VarFlag.LEAVE_ERR_MSG));
						
						data.realCmd = cmd;
						data.self = importedCmd;
						
						// Create an ImportRef structure describing this new import
						// command and add it to the import ref list in the "real"
						// command.
						
						ref_Renamed = new ImportRef();
						ref_Renamed.importedCmd = importedCmd;
						ref_Renamed.next = cmd.importRef;
						cmd.importRef = ref_Renamed;
					}
					else
					{
						throw new TclException(interp, "can't import command \"" + cmdName + "\": already exists");
					}
				}
			}
			return ;
		}
Esempio n. 16
0
		/// <summary> Tcl_ForeachObjCmd -> ForeachCmd.cmdProc
		/// 
		/// This procedure is invoked to process the "foreach" Tcl command.
		/// See the user documentation for details on what it does.
		/// 
		/// </summary>
		/// <param name="interp">the current interpreter.
		/// </param>
		/// <param name="objv">command arguments.
		/// </param>
		/// <exception cref=""> TclException if script causes error.
		/// </exception>
		
		public TCL.CompletionCode cmdProc(Interp interp, TclObject[] objv)
		{
			if (objv.Length < 4 || (objv.Length % 2) != 0)
			{
				throw new TclNumArgsException(interp, 1, objv, "varList list ?varList list ...? command");
			}
			
			// foreach {n1 n2} {1 2 3 4} {n3} {1 2} {puts $n1-$n2-$n3}
			//	name[0] = {n1 n2}	value[0] = {1 2 3 4}
			//	name[1] = {n3}		value[0] = {1 2}
			
			TclObject[] name = new TclObject[(objv.Length - 2) / 2];
			TclObject[] value = new TclObject[(objv.Length - 2) / 2];
			
			int c, i, j, base_;
			int maxIter = 0;
			TclObject command = objv[objv.Length - 1];
			bool done = false;
			
			for (i = 0; i < objv.Length - 2; i += 2)
			{
				int x = i / 2;
				name[x] = objv[i + 1];
				value[x] = objv[i + 2];
				
				int nSize = TclList.getLength(interp, name[x]);
				int vSize = TclList.getLength(interp, value[x]);
				
				if (nSize == 0)
				{
					throw new TclException(interp, "foreach varlist is empty");
				}
				
				int iter = (vSize + nSize - 1) / nSize;
				if (maxIter < iter)
				{
					maxIter = iter;
				}
			}
			
			for (c = 0; !done && c < maxIter; c++)
			{
				// Set up the variables
				
				for (i = 0; i < objv.Length - 2; i += 2)
				{
					int x = i / 2;
					int nSize = TclList.getLength(interp, name[x]);
					base_ = nSize * c;
					for (j = 0; j < nSize; j++)
					{
						// Test and see if the name variable is an array.
						
						
						Var[] result = Var.lookupVar(interp, name[x].ToString(), null, 0, null, false, false);
						Var var = null;
						
						if (result != null)
						{
							if (result[1] != null)
							{
								var = result[1];
							}
							else
							{
								var = result[0];
							}
						}
						
						try
						{
							if (base_ + j >= TclList.getLength(interp, value[x]))
							{
								interp.setVar(TclList.index(interp, name[x], j), TclString.newInstance(""), 0);
							}
							else
							{
								interp.setVar(TclList.index(interp, name[x], j), TclList.index(interp, value[x], base_ + j), 0);
							}
						}
						catch (TclException e)
						{
							
							throw new TclException(interp, "couldn't set loop variable: \"" + TclList.index(interp, name[x], j) + "\"");
						}
					}
				}
				
				// Execute the script
				
				try
				{
					interp.eval(command, 0);
				}
				catch (TclException e)
				{
					switch (e.getCompletionCode())
					{
						
						case TCL.CompletionCode.BREAK: 
							done = true;
							break;
						
						
						case TCL.CompletionCode.CONTINUE: 
							continue;
						
						
						case TCL.CompletionCode.ERROR: 
							interp.addErrorInfo("\n    (\"foreach\" body line " + interp.errorLine + ")");
							throw ;
						
						
						default: 
							throw ;
						
					}
				}
			}
			
			interp.resetResult();
      return TCL.CompletionCode.RETURN;
    }
Esempio n. 17
0
        public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv )
        {
            int i;
              Notifier notifier = (Notifier)interp.getNotifier();
              Object info;

              if ( assocData == null )
              {
            /*
            * Create the "after" information associated for this
            * interpreter, if it doesn't already exist.
            */

            assocData = (AfterAssocData)interp.getAssocData( "tclAfter" );
            if ( assocData == null )
            {
              assocData = new AfterAssocData( this );
              interp.setAssocData( "tclAfter", assocData );
            }
              }

              if ( argv.Length < 2 )
              {
            throw new TclNumArgsException( interp, 1, argv, "option ?arg arg ...?" );
              }

              /*
              * First lets see if the command was passed a number as the first argument.
              */

              bool isNumber = false;
              int ms = 0;

              if ( argv[1].InternalRep is TclInteger )
              {
            ms = TclInteger.get( interp, argv[1] );
            isNumber = true;
              }
              else
              {
            string s = argv[1].ToString();
            if ( ( s.Length > 0 ) && ( System.Char.IsDigit( s[0] ) ) )
            {
              ms = TclInteger.get( interp, argv[1] );
              isNumber = true;
            }
              }

              if ( isNumber )
              {
            if ( ms < 0 )
            {
              ms = 0;
            }
            if ( argv.Length == 2 )
            {
              /*
              * Sleep for at least the given milliseconds and return.
              */

              long endTime = System.DateTime.Now.Ticks / 10000 + ms;
              while ( true )
              {
            try
            {
              System.Threading.Thread.Sleep( ms );
              return TCL.CompletionCode.RETURN;
            }
            catch ( System.Threading.ThreadInterruptedException e )
            {
              /*
              * We got interrupted. Sleep again if we havn't slept
              * long enough yet.
              */

              long sysTime = System.DateTime.Now.Ticks / 10000;
              if ( sysTime >= endTime )
              {
                return TCL.CompletionCode.RETURN;
              }
              ms = (int)( endTime - sysTime );
              continue;
            }
              }
            }

            TclObject cmd = getCmdObject( argv );
            cmd.preserve();

            assocData.lastAfterId++;
            TimerInfo timerInfo = new TimerInfo( this, notifier, ms );
            timerInfo.interp = interp;
            timerInfo.command = cmd;
            timerInfo.id = assocData.lastAfterId;

            assocData.handlers.Add( timerInfo );

            interp.setResult( "after#" + timerInfo.id );

            return TCL.CompletionCode.RETURN;
              }

              /*
              * If it's not a number it must be a subcommand.
              */

              int index;

              try
              {
            index = TclIndex.get( interp, argv[1], validOpts, "option", 0 );
              }
              catch ( TclException e )
              {
            throw new TclException( interp, "bad argument \"" + argv[1] + "\": must be cancel, idle, info, or a number" );
              }

              switch ( index )
              {

            case OPT_CANCEL:
              if ( argv.Length < 3 )
              {
            throw new TclNumArgsException( interp, 2, argv, "id|command" );
              }

              TclObject arg = getCmdObject( argv );
              arg.preserve();

              /*
              * Search the timer/idle handler by id or by command.
              */

              info = null;
              for ( i = 0; i < assocData.handlers.Count; i++ )
              {
            Object obj = assocData.handlers[i];
            if ( obj is TimerInfo )
            {
              TclObject cmd = ( (TimerInfo)obj ).command;

              if ( ( cmd == arg ) || cmd.ToString().Equals( arg.ToString() ) )
              {
                info = obj;
                break;
              }
            }
            else
            {
              TclObject cmd = ( (IdleInfo)obj ).command;

              if ( ( cmd == arg ) || cmd.ToString().Equals( arg.ToString() ) )
              {
                info = obj;
                break;
              }
            }
              }
              if ( info == null )
              {

            info = getAfterEvent( arg.ToString() );
              }
              arg.release();

              /*
              * Cancel the handler.
              */

              if ( info != null )
              {
            if ( info is TimerInfo )
            {
              ( (TimerInfo)info ).cancel();
              ( (TimerInfo)info ).command.release();
            }
            else
            {
              ( (IdleInfo)info ).cancel();
              ( (IdleInfo)info ).command.release();
            }

            SupportClass.VectorRemoveElement( assocData.handlers, info );
              }
              break;

            case OPT_IDLE:
              if ( argv.Length < 3 )
              {
            throw new TclNumArgsException( interp, 2, argv, "script script ..." );
              }

              TclObject cmd2 = getCmdObject( argv );
              cmd2.preserve();
              assocData.lastAfterId++;

              IdleInfo idleInfo = new IdleInfo( this, notifier );
              idleInfo.interp = interp;
              idleInfo.command = cmd2;
              idleInfo.id = assocData.lastAfterId;

              assocData.handlers.Add( idleInfo );

              interp.setResult( "after#" + idleInfo.id );
              break;

            case OPT_INFO:
              if ( argv.Length == 2 )
              {
            /*
            * No id is given. Return a list of current after id's.
            */

            TclObject list = TclList.newInstance();
            for ( i = 0; i < assocData.handlers.Count; i++ )
            {
              int id;
              Object obj = assocData.handlers[i];
              if ( obj is TimerInfo )
              {
                id = ( (TimerInfo)obj ).id;
              }
              else
              {
                id = ( (IdleInfo)obj ).id;
              }
              TclList.append( interp, list, TclString.newInstance( "after#" + id ) );
            }
            interp.resetResult();
            interp.setResult( list );
            return TCL.CompletionCode.RETURN;
              }
              if ( argv.Length != 3 )
              {
            throw new TclNumArgsException( interp, 2, argv, "?id?" );
              }

              /*
              * Return command and type of the given after id.
              */

              info = getAfterEvent( argv[2].ToString() );
              if ( info == null )
              {

            throw new TclException( interp, "event \"" + argv[2] + "\" doesn't exist" );
              }
              TclObject list2 = TclList.newInstance();
              TclList.append( interp, list2, ( ( info is TimerInfo ) ? ( (TimerInfo)info ).command : ( (IdleInfo)info ).command ) );
              TclList.append( interp, list2, TclString.newInstance( ( info is TimerInfo ) ? "timer" : "idle" ) );

              interp.resetResult();
              interp.setResult( list2 );
              break;
              }
              return TCL.CompletionCode.RETURN;
        }
    /*
    * This procedure is invoked to process the "for" Tcl command.
    * See the user documentation for details on what it does.
    *
    * @param interp the current interpreter.
    * @param argv command arguments.
    * @exception TclException if script causes error.
    */

    public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv )
    {
      if ( argv.Length != 5 )
      {
        throw new TclNumArgsException( interp, 1, argv, "start test next command" );
      }

      TclObject start = argv[1];

      string test = argv[2].ToString();
      TclObject next = argv[3];
      TclObject command = argv[4];

      bool done = false;
      try
      {
        interp.eval( start, 0 );
      }
      catch ( TclException e )
      {
        interp.addErrorInfo( "\n    (\"for\" initial command)" );
        throw;
      }

      while ( !done )
      {
        if ( !interp.expr.evalBoolean( interp, test ) )
        {
          break;
        }

        try
        {
          interp.eval( command, 0 );
        }
        catch ( TclException e )
        {
          switch ( e.getCompletionCode() )
          {

            case TCL.CompletionCode.BREAK:
              done = true;
              break;


            case TCL.CompletionCode.CONTINUE:
              break;


            case TCL.CompletionCode.ERROR:
              interp.addErrorInfo( "\n    (\"for\" body line " + interp.errorLine + ")" );
              throw;


            default:
              throw;

          }
        }

        if ( !done )
        {
          try
          {
            interp.eval( next, 0 );
          }
          catch ( TclException e )
          {
            switch ( e.getCompletionCode() )
            {

              case TCL.CompletionCode.BREAK:
                done = true;
                break;


              case TCL.CompletionCode.CONTINUE:
                break;


              default:
                interp.addErrorInfo( "\n    (\"for\" loop-end command)" );
                throw;

            }
          }
        }
      }

      interp.resetResult();
      return TCL.CompletionCode.RETURN;
    }
Esempio n. 19
0
    internal static string pkgRequire( Interp interp, string pkgName, string version, bool exact )
    {
      VersionSatisfiesResult vsres;
      Package pkg;
      PkgAvail avail, best;
      string script;
      StringBuilder sbuf;
      int pass, result;

      // Do extra check to make sure that version is not
      // null when the exact flag is set to true.

      if ( (System.Object)version == null && exact )
      {
        throw new TclException( interp, "conflicting arguments : version == null and exact == true" );
      }

      // Before we can compare versions the version string
      // must be verified but if it is null we are just looking
      // for the latest version so skip the check in this case.

      if ( (System.Object)version != null )
      {
        checkVersion( interp, version );
      }

      // It can take up to three passes to find the package:  one pass to
      // run the "package unknown" script, one to run the "package ifneeded"
      // script for a specific version, and a final pass to lookup the
      // package loaded by the "package ifneeded" script.

      vsres = new VersionSatisfiesResult();
      for ( pass = 1; ; pass++ )
      {
        pkg = findPackage( interp, pkgName );
        if ( (System.Object)pkg.version != null )
        {
          break;
        }

        // The package isn't yet present.  Search the list of available
        // versions and invoke the script for the best available version.

        best = null;
        for ( avail = pkg.avail; avail != null; avail = avail.next )
        {
          if ( ( best != null ) && ( compareVersions( avail.version, best.version, null ) <= 0 ) )
          {
            continue;
          }
          if ( (System.Object)version != null )
          {
            result = compareVersions( avail.version, version, vsres );
            if ( ( result != 0 ) && exact )
            {
              continue;
            }
            if ( !vsres.satisfies )
            {
              continue;
            }
          }
          best = avail;
        }
        if ( best != null )
        {
          // We found an ifneeded script for the package.  Be careful while
          // executing it:  this could cause reentrancy, so (a) protect the
          // script itself from deletion and (b) don't assume that best
          // will still exist when the script completes.

          script = best.script;
          try
          {
            interp.eval( script, TCL.EVAL_GLOBAL );
          }
          catch ( TclException e )
          {
            interp.addErrorInfo( "\n    (\"package ifneeded\" script)" );

            // Throw the error with new info added to errorInfo.

            throw;
          }
          interp.resetResult();
          pkg = findPackage( interp, pkgName );
          break;
        }

        // Package not in the database.  If there is a "package unknown"
        // command, invoke it (but only on the first pass;  after that,
        // we should not get here in the first place).

        if ( pass > 1 )
        {
          break;
        }
        script = interp.packageUnknown;
        if ( (System.Object)script != null )
        {
          sbuf = new StringBuilder();
          try
          {
            Util.appendElement( interp, sbuf, script );
            Util.appendElement( interp, sbuf, pkgName );
            if ( (System.Object)version == null )
            {
              Util.appendElement( interp, sbuf, "" );
            }
            else
            {
              Util.appendElement( interp, sbuf, version );
            }
            if ( exact )
            {
              Util.appendElement( interp, sbuf, "-exact" );
            }
          }
          catch ( TclException e )
          {
            throw new TclRuntimeError( "unexpected TclException: " + e.Message );
          }
          try
          {
            interp.eval( sbuf.ToString(), TCL.EVAL_GLOBAL );
          }
          catch ( TclException e )
          {
            interp.addErrorInfo( "\n    (\"package unknown\" script)" );

            // Throw the first exception.

            throw;
          }
          interp.resetResult();
        }
      }
      if ( (System.Object)pkg.version == null )
      {
        sbuf = new StringBuilder();
        sbuf.Append( "can't find package " + pkgName );
        if ( (System.Object)version != null )
        {
          sbuf.Append( " " + version );
        }
        throw new TclException( interp, sbuf.ToString() );
      }

      // At this point we know that the package is present.  Make sure that the
      // provided version meets the current requirement.

      if ( (System.Object)version == null )
      {
        return pkg.version;
      }

      result = compareVersions( pkg.version, version, vsres );
      if ( ( vsres.satisfies && !exact ) || ( result == 0 ) )
      {
        return pkg.version;
      }

      // If we have a version conflict we throw a TclException.

      throw new TclException( interp, "version conflict for package \"" + pkgName + "\": have " + pkg.version + ", need " + version );
    }
Esempio n. 20
0
		/// <summary> 
		/// Tcl_LappendObjCmd -> LappendCmd.cmdProc
		/// 
		/// This procedure is invoked to process the "lappend" Tcl command.
		/// See the user documentation for details on what it does.
		/// </summary>
		
		public TCL.CompletionCode cmdProc(Interp interp, TclObject[] objv)
		{
			TclObject varValue, newValue = null;
      int i;//int numElems, i, j;
			bool createdNewObj, createVar;
			
			if (objv.Length < 2)
			{
				throw new TclNumArgsException(interp, 1, objv, "varName ?value value ...?");
			}
			if (objv.Length == 2)
			{
				try
				{
					newValue = interp.getVar(objv[1], 0);
				}
				catch (TclException e)
				{
					// The variable doesn't exist yet. Just create it with an empty
					// initial value.
					varValue = TclList.newInstance();
					
					try
					{
						newValue = interp.setVar(objv[1], varValue, 0);
					}
					finally
					{
						if (newValue == null)
							varValue.release(); // free unneeded object
					}
					
					interp.resetResult();
          return TCL.CompletionCode.RETURN;
				}
			}
			else
			{
				// We have arguments to append. We used to call Tcl_SetVar2 to
				// append each argument one at a time to ensure that traces were run
				// for each append step. We now append the arguments all at once
				// because it's faster. Note that a read trace and a write trace for
				// the variable will now each only be called once. Also, if the
				// variable's old value is unshared we modify it directly, otherwise
				// we create a new copy to modify: this is "copy on write".
				
				createdNewObj = false;
				createVar = true;
				
				try
				{
					varValue = interp.getVar(objv[1], 0);
				}
				catch (TclException e)
				{
					// We couldn't read the old value: either the var doesn't yet
					// exist or it's an array element. If it's new, we will try to
					// create it with Tcl_ObjSetVar2 below.
					
					// FIXME : not sure we even need this parse for anything!
					// If we do not need to parse could we at least speed it up a bit
					
					string varName;
					int nameBytes;
					
					
					varName = objv[1].ToString();
					nameBytes = varName.Length; // Number of Unicode chars in string
					
					for (i = 0; i < nameBytes; i++)
					{
						if (varName[i] == '(')
						{
							i = nameBytes - 1;
							if (varName[i] == ')')
							{
								// last char is ')' => array ref
								createVar = false;
							}
							break;
						}
					}
					varValue = TclList.newInstance();
					createdNewObj = true;
				}
				
				// We only take this branch when the catch branch was not run
				if (createdNewObj == false && varValue.Shared)
				{
					varValue = varValue.duplicate();
					createdNewObj = true;
				}
				
				// Insert the new elements at the end of the list.
				
				for (i = 2; i < objv.Length; i++)
				{
					TclList.append(interp, varValue, objv[i]);
				}
				
				// No need to call varValue.invalidateStringRep() since it
				// is called during the TclList.append operation.
				
				// Now store the list object back into the variable. If there is an
				// error setting the new value, decrement its ref count if it
				// was new and we didn't create the variable.
				
				try
				{
					
					newValue = interp.setVar(objv[1].ToString(), varValue, 0);
				}
				catch (TclException e)
				{
					if (createdNewObj && !createVar)
					{
						varValue.release(); // free unneeded obj
					}
					throw ;
				}
			}
			
			// Set the interpreter's object result to refer to the variable's value
			// object.
			
			interp.setResult(newValue);
      return TCL.CompletionCode.RETURN;
		}
    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. 22
0
		/// <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)
		{
			int i;
			bool value;
			
			i = 1;
			while (true)
			{
				/*
				* At this point in the loop, argv and argc refer to an
				* expression to test, either for the main expression or
				* an expression following an "elseif".  The arguments
				* after the expression must be "then" (optional) and a
				* script to execute if the expression is true.
				*/
				
				if (i >= argv.Length)
				{
					
					throw new TclException(interp, "wrong # args: no expression after \"" + argv[i - 1] + "\" argument");
				}
				try
				{
					
					value = interp.expr.evalBoolean(interp, argv[i].ToString());
				}
				catch (TclException e)
				{
					switch (e.getCompletionCode())
					{
						
						case TCL.CompletionCode.ERROR: 
							interp.addErrorInfo("\n    (\"if\" test expression)");
							break;
						}
					throw ;
				}
				
				i++;
				
				if ((i < argv.Length) && (argv[i].ToString().Equals("then")))
				{
					i++;
				}
				if (i >= argv.Length)
				{
					
					throw new TclException(interp, "wrong # args: no script following \"" + argv[i - 1] + "\" argument");
				}
				if (value)
				{
					try
					{
						interp.eval(argv[i], 0);
					}
					catch (TclException e)
					{
						switch (e.getCompletionCode())
						{
							
							case TCL.CompletionCode.ERROR: 
								interp.addErrorInfo("\n    (\"if\" then script line " + interp.errorLine + ")");
								break;
							}
						throw ;
					}
          return TCL.CompletionCode.RETURN;
				}
				
				/*
				* The expression evaluated to false.  Skip the command, then
				* see if there is an "else" or "elseif" clause.
				*/
				
				i++;
				if (i >= argv.Length)
				{
					interp.resetResult();
          return TCL.CompletionCode.RETURN;
				}
				
				if (argv[i].ToString().Equals("elseif"))
				{
					i++;
					continue;
				}
				break;
			}
			
			/*
			* Couldn't find a "then" or "elseif" clause to execute.
			* Check now for an "else" clause.  We know that there's at
			* least one more argument when we get here.
			*/
			
			
			if (argv[i].ToString().Equals("else"))
			{
				i++;
				if (i >= argv.Length)
				{
					throw new TclException(interp, "wrong # args: no script following \"else\" argument");
				}
				else if (i != (argv.Length - 1))
				{
					throw new TclException(interp, "wrong # args: extra words after \"else\" clause in " + "\"if\" command");
				}
			}
			try
			{
				interp.eval(argv[i], 0);
			}
			catch (TclException e)
			{
				switch (e.getCompletionCode())
				{
					
					case TCL.CompletionCode.ERROR: 
						interp.addErrorInfo("\n    (\"if\" else script line " + interp.errorLine + ")");
						break;
					}
				throw ;
			}
      return TCL.CompletionCode.RETURN;
    }