Exemple #1
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 index element ?element ...?");
            }

            int       size        = TclList.getLength(interp, argv[1]);
            int       index       = Util.getIntForIndex(interp, argv[2], size);
            TclObject list        = argv[1];
            bool      isDuplicate = false;

            // If the list object is unshared we can modify it directly. Otherwise
            // we create a copy to modify: this is "copy on write".

            if (list.Shared)
            {
                list        = list.duplicate();
                isDuplicate = true;
            }

            try
            {
                TclList.insert(interp, list, index, argv, 3, argv.Length - 1);
                interp.setResult(list);
            }
            catch (TclException e)
            {
                if (isDuplicate)
                {
                    list.release();
                }
                throw;
            }
            return(TCL.CompletionCode.RETURN);
        }
Exemple #2
0
        /*
         *----------------------------------------------------------------------
         *
         * cmdProc --
         *
         *	This procedure is invoked as part of the Command interface to
         *	process the "lsort" Tcl command.  See the user documentation for
         *	details on what it does.
         *
         * Results:
         *	A standard Tcl result.
         *
         * Side effects:
         *	See the user documentation.
         *
         *----------------------------------------------------------------------
         */

        public TCL.CompletionCode cmdProc(Interp interp, TclObject[] argv)
        {
            if (argv.Length < 2)
            {
                throw new TclNumArgsException(interp, 1, argv, "?options? list");
            }

            string command        = null;
            int    sortMode       = QSort.ASCII;
            int    sortIndex      = -1;
            bool   sortIncreasing = true;
            bool   unique         = false;

            for (int i = 1; i < argv.Length - 1; i++)
            {
                int index = TclIndex.get(interp, argv[i], validOpts, "option", 0);

                switch (index)
                {
                case 0:
                    sortMode = QSort.ASCII;
                    break;


                case 1:
                    if (i == argv.Length - 2)
                    {
                        throw new TclException(interp, "\"-command\" option must be" + " followed by comparison command");
                    }
                    sortMode = QSort.COMMAND;

                    command = argv[i + 1].ToString();
                    i++;
                    break;


                case 2:
                    sortIncreasing = false;
                    break;


                case 3:
                    sortMode = QSort.DICTIONARY;
                    break;


                case 4:
                    sortIncreasing = true;
                    break;


                case 5:
                    if (i == argv.Length - 2)
                    {
                        throw new TclException(interp, "\"-index\" option must be followed by list index");
                    }
                    sortIndex = Util.getIntForIndex(interp, argv[i + 1], -2);

                    command = argv[i + 1].ToString();
                    i++;
                    break;


                case 6:
                    sortMode = QSort.INTEGER;
                    break;


                case 7:
                    sortMode = QSort.REAL;
                    break;

                case 8:         /* -unique */
                    unique = true;
                    break;
                }
            }

            TclObject list        = argv[argv.Length - 1];
            bool      isDuplicate = false;

            // If the list object is unshared we can modify it directly. Otherwise
            // we create a copy to modify: this is "copy on write".

            if (list.Shared)
            {
                list        = list.duplicate();
                isDuplicate = true;
            }

            try
            {
                TclList.sort(interp, list, sortMode, sortIndex, sortIncreasing, command, unique);
                interp.setResult(list);
            }
            catch (TclException e)
            {
                if (isDuplicate)
                {
                    list.release();
                }
                throw;
            }
            return(TCL.CompletionCode.RETURN);
        }
 public static TclObject Tcl_DuplicateObj(TclObject to)
 {
     return(to.duplicate());
 }
    /// <summary> TCL.Tcl_SetVar2Ex -> setVar
    /// 
    /// Given a two-part variable name, which may refer either to a scalar
    /// variable or an element of an array, change the value of the variable
    /// to a new Tcl object value. If the named scalar or array or element
    /// doesn't exist then create one.
    /// 
    /// </summary>
    /// <param name="interp">the interp that holds the variable
    /// </param>
    /// <param name="part1">1st part of the variable name.
    /// </param>
    /// <param name="part2">2nd part of the variable name.
    /// </param>
    /// <param name="newValue">the new value for the variable
    /// </param>
    /// <param name="flags">misc flags that control the actions of this method
    /// 
    /// Returns a pointer to the TclObject holding the new value of the
    /// variable. If the write operation was disallowed because an array was
    /// expected but not found (or vice versa), then null is returned; if
    /// the TCL.VarFlag.LEAVE_ERR_MSG flag is set, then an exception will be raised.
    /// Note that the returned object may not be the same one referenced
    /// by newValue because variable traces may modify the variable's value.
    /// The value of the given variable is set. If either the array or the
    /// entry didn't exist then a new variable is created.
    /// 
    /// The reference count is decremented for any old value of the variable
    /// and incremented for its new value. If the new value for the variable
    /// is not the same one referenced by newValue (perhaps as a result
    /// of a variable trace), then newValue's ref count is left unchanged
    /// by TCL.Tcl_SetVar2Ex. newValue's ref count is also left unchanged if
    /// we are appending it as a string value: that is, if "flags" includes
    /// TCL.VarFlag.APPEND_VALUE but not TCL.VarFlag.LIST_ELEMENT.
    /// 
    /// The reference count for the returned object is _not_ incremented: if
    /// you want to keep a reference to the object you must increment its
    /// ref count yourself.
    /// </param>

    internal static TclObject setVar( Interp interp, string part1, string part2, TclObject newValue, TCL.VarFlag flags )
    {
      Var var;
      Var array;
      TclObject oldValue;
      string bytes;

      Var[] result = lookupVar( interp, part1, part2, flags, "set", true, true );
      if ( result == null )
      {
        return null;
      }

      var = result[0];
      array = result[1];

      // If the variable is in a hashtable and its table field is null, then we
      // may have an upvar to an array element where the array was deleted
      // or an upvar to a namespace variable whose namespace was deleted.
      // Generate an error (allowing the variable to be reset would screw up
      // our storage allocation and is meaningless anyway).

      if ( ( ( var.flags & VarFlags.IN_HASHTABLE ) != 0 ) && ( var.table == null ) )
      {
        if ( ( flags & TCL.VarFlag.LEAVE_ERR_MSG ) != 0 )
        {
          if ( var.isVarArrayElement() )
          {
            throw new TclVarException( interp, part1, part2, "set", danglingElement );
          }
          else
          {
            throw new TclVarException( interp, part1, part2, "set", danglingVar );
          }
        }
        return null;
      }

      // It's an error to try to set an array variable itself.

      if ( var.isVarArray() && !var.isVarUndefined() )
      {
        if ( ( flags & TCL.VarFlag.LEAVE_ERR_MSG ) != 0 )
        {
          throw new TclVarException( interp, part1, part2, "set", isArray );
        }
        return null;
      }


      // At this point, if we were appending, we used to call read traces: we
      // treated append as a read-modify-write. However, it seemed unlikely to
      // us that a real program would be interested in such reads being done
      // during a set operation.

      // Set the variable's new value. If appending, append the new value to
      // the variable, either as a list element or as a string. Also, if
      // appending, then if the variable's old value is unshared we can modify
      // it directly, otherwise we must create a new copy to modify: this is
      // "copy on write".

      try
      {
        if ( var.isSQLITE3_Link() )
        {
          var.sqlite3_set( newValue );
          return var.sqlite3_get();
        }
        else
        {
          oldValue = (TclObject)var.value;

          if ( ( flags & TCL.VarFlag.APPEND_VALUE ) != 0 )
          {
            if ( var.isVarUndefined() && ( oldValue != null ) )
            {
              oldValue.release(); // discard old value
              var.value = null;
              oldValue = null;
            }
            if ( ( flags & TCL.VarFlag.LIST_ELEMENT ) != 0 )
            {
              // append list element
              if ( oldValue == null )
              {
                oldValue = TclList.newInstance();
                var.value = oldValue;
                oldValue.preserve(); // since var is referenced
              }
              else if ( oldValue.Shared )
              {
                // append to copy
                var.value = oldValue.duplicate();
                oldValue.release();
                oldValue = (TclObject)var.value;
                oldValue.preserve(); // since var is referenced
              }
              TclList.append( interp, oldValue, newValue );
            }
            else
            {
              // append string
              // We append newValuePtr's bytes but don't change its ref count.


              bytes = newValue.ToString();
              if ( oldValue == null )
              {
                var.value = TclString.newInstance( bytes );
                ( (TclObject)var.value ).preserve();
              }
              else
              {
                if ( oldValue.Shared )
                {
                  // append to copy
                  var.value = oldValue.duplicate();
                  oldValue.release();
                  oldValue = (TclObject)var.value;
                  oldValue.preserve(); // since var is referenced
                }
                TclString.append( oldValue, newValue );
              }
            }
          }
          else
          {
            if ( ( flags & TCL.VarFlag.LIST_ELEMENT ) != 0 )
            {
              // set var to list element
              int listFlags;

              // We set the variable to the result of converting newValue's
              // string rep to a list element. We do not change newValue's
              // ref count.

              if ( oldValue != null )
              {
                oldValue.release(); // discard old value
              }

              bytes = newValue.ToString();
              listFlags = Util.scanElement( interp, bytes );
              oldValue = TclString.newInstance( Util.convertElement( bytes, listFlags ) );
              var.value = oldValue;
              ( (TclObject)var.value ).preserve();
            }
            else if ( newValue != oldValue )
            {
              var.value = newValue.duplicate();
              ( (TclObject)var.value ).preserve(); // var is another ref
              if ( oldValue != null )
              {
                oldValue.release(); // discard old value
              }
            }
          }
          var.setVarScalar();
          var.clearVarUndefined();
          if ( array != null )
          {
            array.clearVarUndefined();
          }

          // Invoke any write traces for the variable.

          if ( ( var.traces != null ) || ( ( array != null ) && ( array.traces != null ) ) )
          {

            string msg = callTraces( interp, array, var, part1, part2, ( flags & ( TCL.VarFlag.GLOBAL_ONLY | TCL.VarFlag.NAMESPACE_ONLY ) ) | TCL.VarFlag.TRACE_WRITES );
            if ( (System.Object)msg != null )
            {
              if ( ( flags & TCL.VarFlag.LEAVE_ERR_MSG ) != 0 )
              {
                throw new TclVarException( interp, part1, part2, "set", msg );
              }
              return null; // Same as "goto cleanup" in C verison
            }
          }

          // Return the variable's value unless the variable was changed in some
          // gross way by a trace (e.g. it was unset and then recreated as an
          // array).

          if ( var.isVarScalar() && !var.isVarUndefined() )
          {
            return (TclObject)var.value;
          }

          // A trace changed the value in some gross way. Return an empty string
          // object.

          return TclString.newInstance( "" );
        }
      }
      finally
      {
        // If the variable doesn't exist anymore and no-one's using it,
        // then free up the relevant structures and hash table entries.

        if ( var.isVarUndefined() )
        {
          cleanupVar( var, array );
        }
      }
    }
Exemple #5
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 ?element element ...?");
            }
            int size  = TclList.getLength(interp, argv[1]);
            int first = Util.getIntForIndex(interp, argv[2], size - 1);
            int last  = Util.getIntForIndex(interp, argv[3], size - 1);
            int numToDelete;

            if (first < 0)
            {
                first = 0;
            }

            // Complain if the user asked for a start element that is greater
            // than the list length. This won't ever trigger for the "end*"
            // case as that will be properly constrained by getIntForIndex
            // because we use size-1 (to allow for replacing the last elem).

            if ((first >= size) && (size > 0))
            {
                throw new TclException(interp, "list doesn't contain element " + argv[2]);
            }
            if (last >= size)
            {
                last = size - 1;
            }
            if (first <= last)
            {
                numToDelete = (last - first + 1);
            }
            else
            {
                numToDelete = 0;
            }

            TclObject list        = argv[1];
            bool      isDuplicate = false;

            // If the list object is unshared we can modify it directly. Otherwise
            // we create a copy to modify: this is "copy on write".

            if (list.Shared)
            {
                list        = list.duplicate();
                isDuplicate = true;
            }

            try
            {
                TclList.replace(interp, list, first, numToDelete, argv, 4, argv.Length - 1);
                interp.setResult(list);
            }
            catch (TclException e)
            {
                if (isDuplicate)
                {
                    list.release();
                }
                throw;
            }
            return(TCL.CompletionCode.RETURN);
        }