TraceCmd.java :  » Scripting » jacl » tcl » lang » Java Open Source

Java Open Source » Scripting » jacl 
jacl » tcl » lang » TraceCmd.java
/*
 * TraceCmd.java --
 *
 *  This file implements the Tcl "trace" command.
 *
 * Copyright (c) 1997 Sun Microsystems, Inc.
 *
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL
 * WARRANTIES.
 * 
 * RCS: @(#) $Id: TraceCmd.java,v 1.8 2006/01/26 19:49:18 mdejong Exp $
 *
 */

package tcl.lang;

import java.util.*;

/**
 * The TraceCmd class implements the Command interface for specifying
 * a new Tcl command. The method cmdProc implements the built-in Tcl
 * command "trace" which is used to manupilate variable traces.  See
 * user documentation for more details.
 */

class TraceCmd implements Command {

// Valid sub-commands for the trace command.

static final private String[] validCmds = {
    "variable",
    "vdelete",
    "vinfo",
};

static final private int OPT_VARIABLE   = 0;
static final private int OPT_VDELETE    = 1;
static final private int OPT_VINFO      = 2;

// An array for quickly generating the Tcl strings corresponding to
// the TCL.TRACE_READS, TCL.TRACE_WRITES and TCL.TRACE_UNSETS flags.

private static TclObject[] opStr = initOptStr();

/*
 *----------------------------------------------------------------------
 *
 * initOptStr --
 *
 *  This static method is called when the TraceCmd class is loaded
 *  into the VM. It initializes the opStr array.
 *
 * Results:
 *  Initial value for opStr.
 *
 * Side effects:
 *  The TclObjects stored in opStr are preserve()'ed.
 *
 *----------------------------------------------------------------------
 */

private static TclObject[]
initOptStr()
{
    TclObject[] strings = new TclObject[8];
    strings[0] = TclString.newInstance("error");
    strings[1] = TclString.newInstance("r");
    strings[2] = TclString.newInstance("w");
    strings[3] = TclString.newInstance("rw");
    strings[4] = TclString.newInstance("u");
    strings[5] = TclString.newInstance("ru");
    strings[6] = TclString.newInstance("wu");
    strings[7] = TclString.newInstance("rwu");

    for (int i = 0; i < 8; i++) {
  strings[i].preserve();
    }

    return strings;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_TraceObjCmd -> TraceCmd.cmdProc
 *
 *  This procedure is invoked as part of the Command interface to 
 *  process the "trace" Tcl command.  See the user documentation for
 *  details on what it does.
 *
 * Results:
 *  None.
 *
 * Side effects:
 *  See the user documentation.
 *
 *----------------------------------------------------------------------
 */

public void cmdProc(
    Interp interp,  // Current interpreter.
    TclObject[] objv)  // Argument list.
throws 
    TclException   // A standard Tcl exception.
{
    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");
      }
  }

  int flags = 0;
  String ops = objv[3].toString();
  len = ops.length();
    check_ops: {
      for (int i = 0; i < len; i++) {
    switch (ops.charAt(i)) {
    case 'r':
        flags |= TCL.TRACE_READS;
        break;
    case 'w':
        flags |= TCL.TRACE_WRITES;
        break;
    case 'u':
        flags |= TCL.TRACE_UNSETS;
        break;
    default:
        flags = 0;
        break check_ops;
    }
      }
  }

  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].toString(), null, 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(), null, 0);
      if (traces != null) {
    len = traces.size();
    for (int i = 0; i < len; i++) {
        TraceRecord rec = (TraceRecord) traces.get(i);

        if (rec.trace instanceof CmdTraceProc) {
      CmdTraceProc proc = (CmdTraceProc) rec.trace;
      if (proc.flags == flags && proc.command.toString().
        equals(objv[4].toString())) {
          Var.untraceVar(interp, objv[2].toString(), null,
            flags, proc);
          break;
      }
        }
    }
      }
  }
  break;

    case OPT_VINFO:
  if (objv.length != 3) {
      throw new TclNumArgsException(interp, 2, objv, 
        "name");
  }
  ArrayList traces = Var.getTraces(interp, objv[2].toString(), null, 0);
  if (traces != null) {
      len = traces.size();
      TclObject list = TclList.newInstance();
      TclObject cmd = null;
      list.preserve();

      try {
    for (int i = 0; i < len; i++) {
        TraceRecord rec = (TraceRecord) traces.get(i);

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

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

} // TraceCmd

// The CmdTraceProc object holds the information for a specific
// trace.
class CmdTraceProc implements VarTrace {

// The command holds the Tcl script that will execute. The flags
// hold the mode flags that define what conditions to fire under.

String command;
int flags;


/*
 *----------------------------------------------------------------------
 *
 * CmdTraceProc --
 *
 *  This function is a constructor for a CmdTraceProc.  It simply
 *  stores the flags and command used for this trace proc.
 *  details on what it does.
 *
 * Results:
 *  None.
 *
 * Side effects:
 *  None.
 *
 *----------------------------------------------------------------------
 */

CmdTraceProc(String cmd, int newFlags) {
    flags = newFlags;
    command = cmd;
}

/*
 *----------------------------------------------------------------------
 *
 * traceProc --
 *
 *  This function gets called when a variable is used in a way that
 *  would cause this particular trace to fire.  It will evaluate
 *  the script associated with this trace.
 *
 * Results:
 *  None.
 *
 * Side effects:
 *  None.
 *
 *----------------------------------------------------------------------
 */

public void 
traceProc(
    Interp interp,   // The current interpreter.
    String part1,  // A Tcl variable or array name.
    String part2,  // Array element name or NULL.
    int flags)    // Mode flags: TCL.TRACE_READS, TCL.TRACE_WRITES or
      // TCL.TRACE_UNSETS.
throws
    TclException   // A standard Tcl exception.
{
    if (((this.flags & flags) != 0) &&
      ((flags & TCL.INTERP_DESTROYED) == 0)) {
  StringBuffer sbuf = new StringBuffer(command);

  try {
      Util.appendElement(interp, sbuf, part1);
      if (part2 != null) {
    Util.appendElement(interp, sbuf, part2);
      } else {
    Util.appendElement(interp, sbuf, "");
      }

      if ((flags & TCL.TRACE_READS) != 0) {
    Util.appendElement(interp, sbuf, "r");
      } else if ((flags & TCL.TRACE_WRITES) != 0) {
    Util.appendElement(interp, sbuf, "w");
      } else if ((flags & TCL.TRACE_UNSETS) != 0) {
    Util.appendElement(interp, sbuf, "u");
      }
  } catch (TclException e) {
      throw new TclRuntimeError("unexpected TclException: " + e);
  }

  // Execute the command.

  interp.eval(sbuf.toString(), 0);
    }
}

} // CmdTraceProc
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.