public static void Tcl_LinkVar(Interp interp, string name, Object GetSet, VarFlags flags)
 {
     Debug.Assert(((flags & VarFlags.SQLITE3_LINK_READ_ONLY) != 0) || GetSet.GetType().Name == "SQLITE3_GETSET");
     Var[] linkvar = Var.lookupVar(interp, name, null, VarFlag.GLOBAL_ONLY, "define", true, false);
     linkvar[0].flags          |= VarFlags.SQLITE3_LINK | flags;
     linkvar[0].sqlite3_get_set = GetSet;
     linkvar[0].refCount++;
 }
    /// <summary> NewVar -> Var
    /// 
    /// Construct a variable and initialize its fields.
    /// </summary>

    internal Var()
    {
      value = null;
      //name     = null; // Like hashKey in Jacl
      ns = null;
      hashKey = null; // Like hPtr in the C implementation
      table = null; // Like hPtr in the C implementation
      refCount = 0;
      traces = null;
      //search   = null;
      sidVec = null; // Like search in the C implementation
      flags = ( VarFlags.SCALAR | VarFlags.UNDEFINED | VarFlags.IN_HASHTABLE );
    }
    /// <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();
      }
    }
    /// <summary> TclDeleteVars -> deleteVars
    /// 
    /// This procedure is called to recycle all the storage space
    /// associated with a table of variables. For this procedure
    /// to work correctly, it must not be possible for any of the
    /// variables in the table to be accessed from Tcl commands
    /// (e.g. from trace procedures).
    /// 
    /// </summary>
    /// <param name="interp">Interpreter containing array.
    /// </param>
    /// <param name="table">Hashtbale that holds the Vars to delete
    /// </param>

    static protected internal void deleteVars( Interp interp, Hashtable table )
    {
      IEnumerator search;
      string hashKey;
      Var var;
      Var link;
      TCL.VarFlag flags;
      //ActiveVarTrace active;
      TclObject obj;
      NamespaceCmd.Namespace currNs = NamespaceCmd.getCurrentNamespace( interp );

      // Determine what flags to pass to the trace callback procedures.

      flags = TCL.VarFlag.TRACE_UNSETS;
      if ( table == interp.globalNs.varTable )
      {
        flags |= ( TCL.VarFlag.INTERP_DESTROYED | TCL.VarFlag.GLOBAL_ONLY );
      }
      else if ( table == currNs.varTable )
      {
        flags |= TCL.VarFlag.NAMESPACE_ONLY;
      }


      for ( search = table.Values.GetEnumerator(); search.MoveNext(); )
      {
        var = (Var)search.Current;

        // For global/upvar variables referenced in procedures, decrement
        // the reference count on the variable referred to, and free
        // the referenced variable if it's no longer needed. Don't delete
        // the hash entry for the other variable if it's in the same table
        // as us: this will happen automatically later on.

        if ( var.isVarLink() )
        {
          link = (Var)var.value;
          link.refCount--;
          if ( ( link.refCount == 0 ) && link.isVarUndefined() && ( link.traces == null ) && ( ( link.flags & VarFlags.IN_HASHTABLE ) != 0 ) )
          {

            if ( (System.Object)link.hashKey == null )
            {
              var.value = null; // Drops reference to the link Var
            }
            else if ( link.table != table )
            {
              SupportClass.HashtableRemove( link.table, link.hashKey );
              link.table = null; // Drops the link var's table reference
              var.value = null; // Drops reference to the link Var
            }
          }
        }

        // free up the variable's space (no need to free the hash entry
        // here, unless we're dealing with a global variable: the
        // hash entries will be deleted automatically when the whole
        // table is deleted). Note that we give callTraces the variable's
        // fully-qualified name so that any called trace procedures can
        // refer to these variables being deleted.

        if ( var.traces != null )
        {
          string fullname = getVariableFullName( interp, var );

          callTraces( interp, null, var, fullname, null, flags );

          // The var.traces = null statement later will drop all the
          // references to the traces which will free them up
        }

        if ( var.isVarArray() )
        {
          deleteArray( interp, var.hashKey, var, flags );
          var.value = null;
        }
        if ( var.isVarScalar() && ( var.value != null ) )
        {
          obj = (TclObject)var.value;
          obj.release();
          var.value = null;
        }

        // There is no hPtr member in Jacl, The hPtr combines the table
        // and the key used in a table lookup.
        var.hashKey = null;
        var.table = null;
        var.traces = null;
        var.setVarUndefined();
        var.setVarScalar();

        // If the variable was a namespace variable, decrement its 
        // reference count. We are in the process of destroying its
        // namespace so that namespace will no longer "refer" to the
        // variable.

        if ( ( var.flags & VarFlags.NAMESPACE_VAR ) != 0 )
        {
          var.flags &= ~VarFlags.NAMESPACE_VAR;
          var.refCount--;
        }

        // Recycle the variable's memory space if there aren't any upvar's
        // pointing to it. If there are upvars to this variable, then the
        // variable will get freed when the last upvar goes away.

        if ( var.refCount == 0 )
        {
          // When we drop the last reference it will be freeded
        }
      }
      table.Clear();
    }
Пример #5
0
		static extern VlcError __var_Change(IntPtr p_this, String name, VarFlags varFlags,
			ref vlc_value_t value, ref vlc_value_t value2);