/// <summary> TCL.Tcl_TraceVar2 -> traceVar
    /// 
    /// Trace a variable, given a two-part name consisting of array
    /// name and element within array.
    /// 
    /// </summary>
    /// <param name="part1">1st part of the variable name.
    /// </param>
    /// <param name="part2">2nd part of the variable name.
    /// </param>
    /// <param name="flags">misc flags that control the actions of this method.
    /// </param>
    /// <param name="trace">the trace to comand to add.
    /// </param>

    internal static void traceVar( Interp interp, string part1, string part2, TCL.VarFlag flags, VarTrace proc )
    {
      Var[] result;
      Var var, array;

      // FIXME: what about the exception problem here?
      result = lookupVar( interp, part1, part2, ( flags | TCL.VarFlag.LEAVE_ERR_MSG ), "trace", true, true );
      if ( result == null )
      {
        throw new TclException( interp, "" );
      }

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

      // Set up trace information.

      if ( var.traces == null )
      {
        var.traces = new ArrayList( 10 );
      }

      var rec = new TraceRecord();
      rec.trace = proc;
      rec.flags = flags & ( TCL.VarFlag.TRACE_READS | TCL.VarFlag.TRACE_WRITES | TCL.VarFlag.TRACE_UNSETS | TCL.VarFlag.TRACE_ARRAY );

      var.traces.Insert( 0, rec );


      // FIXME: is this needed ?? It was in Jacl but not 8.1

      /*
      // When inserting a trace for an array on an UNDEFINED variable,
      // the search IDs for that array are reset.

      if (array != null && var.isVarUndefined()) {
      array.sidVec = null;
      }
      */
    }
예제 #2
0
        public TCL.CompletionCode cmdProc(Interp interp, TclObject[] objv)
        {
            int len;

            if (objv.Length < 2)
            {
                throw new TclNumArgsException(interp, 1, objv, "option [arg arg ...]");
            }
            int opt = TclIndex.get(interp, objv[1], validCmds, "option", 0);

            switch (opt)
            {
            case OPT_VARIABLE:
            case OPT_VDELETE:
                if (objv.Length != 5)
                {
                    if (opt == OPT_VARIABLE)
                    {
                        throw new TclNumArgsException(interp, 1, objv, "variable name ops command");
                    }
                    else
                    {
                        throw new TclNumArgsException(interp, 1, objv, "vdelete name ops command");
                    }
                }

                TCL.VarFlag flags = 0;

                string ops = objv[3].ToString();
                len = ops.Length;
                {
                    for (int i = 0; i < len; i++)
                    {
                        switch (ops[i])
                        {
                        case 'r':
                            flags |= TCL.VarFlag.TRACE_READS;
                            break;

                        case 'w':
                            flags |= TCL.VarFlag.TRACE_WRITES;
                            break;

                        case 'u':
                            flags |= TCL.VarFlag.TRACE_UNSETS;
                            break;

                        default:
                            flags = 0;
                            goto check_ops_brk;
                        }
                    }
                }

check_ops_brk:
                ;


                if (flags == 0)
                {
                    throw new TclException(interp, "bad operations \"" + objv[3] + "\": should be one or more of rwu");
                }

                if (opt == OPT_VARIABLE)
                {
                    CmdTraceProc trace = new CmdTraceProc(objv[4].ToString(), flags);
                    Var.traceVar(interp, objv[2], flags, trace);
                }
                else
                {
                    // Search through all of our traces on this variable to
                    // see if there's one with the given command.  If so, then
                    // delete the first one that matches.


                    ArrayList traces = Var.getTraces(interp, objv[2].ToString(), 0);
                    if (traces != null)
                    {
                        len = traces.Count;
                        for (int i = 0; i < len; i++)
                        {
                            TraceRecord rec = (TraceRecord)traces[i];

                            if (rec.trace is CmdTraceProc)
                            {
                                CmdTraceProc proc = (CmdTraceProc)rec.trace;

                                if (proc.flags == flags && proc.command.ToString().Equals(objv[4].ToString()))
                                {
                                    Var.untraceVar(interp, objv[2], flags, proc);
                                    break;
                                }
                            }
                        }
                    }
                }
                break;


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

                ArrayList traces2 = Var.getTraces(interp, objv[2].ToString(), 0);
                if (traces2 != null)
                {
                    len = traces2.Count;
                    TclObject list = TclList.newInstance();
                    TclObject cmd  = null;
                    list.preserve();

                    try
                    {
                        for (int i = 0; i < len; i++)
                        {
                            TraceRecord rec = (TraceRecord)traces2[i];

                            if (rec.trace is CmdTraceProc)
                            {
                                CmdTraceProc proc = (CmdTraceProc)rec.trace;
                                TCL.VarFlag  mode = proc.flags;
                                mode &= (TCL.VarFlag.TRACE_READS | TCL.VarFlag.TRACE_WRITES | TCL.VarFlag.TRACE_UNSETS);
                                int modeInt = (int)mode;
                                modeInt /= ((int)TCL.VarFlag.TRACE_READS);

                                cmd = TclList.newInstance();
                                TclList.append(interp, cmd, opStr[modeInt]);
                                TclList.append(interp, cmd, TclString.newInstance(proc.command));
                                TclList.append(interp, list, cmd);
                            }
                        }
                        interp.setResult(list);
                    }
                    finally
                    {
                        list.release();
                    }
                }
                break;
            }
            return(TCL.CompletionCode.RETURN);
        }