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(); }
static extern VlcError __var_Change(IntPtr p_this, String name, VarFlags varFlags, ref vlc_value_t value, ref vlc_value_t value2);