//============================================================================== // ExecFrame.java //============================================================================== package tribble.net.ftp.shell; import java.io.PrintWriter; import java.lang.Exception; import java.lang.Integer; import java.lang.String; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /******************************************************************************* * FTP command execution context frame. * * * @version API 1.1 $Revision: 1.16 $ $Date: 2010/07/12 23:42:09 $ * @since API 1.0, 2007-03-15 * @author David R. Tribble (david@tribble.com). *

* Copyright ©2007-2010 by David R. Tribble, all rights reserved.
* Permission is granted to any person or entity except those designated by * by the United States Department of State as a terrorist, or terrorist * government or agency, to use and distribute this source code provided * that the original copyright notice remains present and unaltered. * * @see Interp * @see BlockDef */ class ExecFrame implements CommandCodes { /** Revision information. */ static final String REV = "@(#)tribble/net/ftp/shell/ExecFrame.java API 1.1 $Revision: 1.16 $ $Date: 2010/07/12 23:42:09 $\n"; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Static methods /*************************************************************************** * Print a string value in printable (source) form. * * @since 1.7, 2007-04-11 */ static void dumpString(String s, PrintWriter out) { int len; // Display the runtime contents of the string out.print('\''); len = s.length(); for (int i = 1; i < len; i++) { char ch; // Display the next char in the string ch = s.charAt(i); switch (ch) { case '`': out.print("``"); break; case '\'': out.print("`'"); break; case 0x07: out.print("`a"); break; case '\b': out.print("`b"); break; case 0x7F: out.print("`d"); break; case 0x1B: out.print("`e"); break; case '\f': out.print("`f"); break; case 0x0A: out.print("`l"); break; case '\r': out.print("`r"); break; case '\t': out.print("`t"); break; case 0x0B: out.print("`v"); break; case 0x1A: out.print("`z"); break; default: if (ch > 0x0FFF) out.print("`u" + Integer.toHexString(ch)); else if (ch > 0x00FF) out.print("`u0" + Integer.toHexString(ch)); else if (ch < 0x0010) out.print("`u000" + Integer.toHexString(ch)); else if (ch < 0x0020 || ch >= 0x0080 && ch < 0x00A0) out.print("`u00" + Integer.toHexString(ch)); else out.print(ch); break; } } out.print('\''); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Variables /** Begin/end block or func defining the scope for this frame. */ BlockDef m_scope; /** Scope nesting depth. */ int m_depth; /** Next command to execute. */ CommandNode m_pc; /** Conditional ('while' loop) expression. */ Object m_expr; /** Session number (for a 'foreach' loop). */ int m_sess = -1; /** Remote host name ('foreach' loop). */ String m_host; /** Remote directory name ('foreach' loop). */ String m_dir; /** File list ('foreach' loop entries). */ ArrayList m_files; /** Next file in the {@link #m_files m_files[]} list. */ int m_fileCnt; /** Commands (statements) for this frame. */ private CommandNode m_cmds; /** Local var values. */ private HashMap m_vars; /** Previous nested calling frame. */ private ExecFrame m_prev; /** Outer scopes (the display) of this nested calling frame. */ private ExecFrame[] m_outer; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constructors /*************************************************************************** * Constructor. * * @param scope * Begin/end block or func definition that defines the context and scope for * this frame. The initial (file) frame is the outermost scope for all * execution frames. * * @param cmds * Commands to execute within this frame. This is the first statement of the * begin/end block or func for this frame, or null if there are no commands. * * @param prev * Execution frame that is calling (nesting) this new frame. It is the frame * where execution will resume when the new frame finishes its execution. * The outermost (initial) execution frame has a null calling frame. * * @since 1.2, 2007-03-16 */ ExecFrame(BlockDef scope, CommandNode cmds, ExecFrame prev) { // Initialize m_scope = scope; m_cmds = cmds; m_prev = prev; // Set up m_pc = m_cmds; // Establish this frame's scope (display) from earlier frames // m_outer[0] is the outermost scope, m_outer[depth-1] is the innermost m_depth = scope.m_depth; m_outer = new ExecFrame[m_depth]; if (prev != null) { int i; for (i = 0; i < m_depth && i < prev.m_depth; i++) m_outer[i] = prev.m_outer[i]; if (i < m_depth) m_outer[i] = prev; } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Methods /*************************************************************************** * Reset this execution frame so that it begins executing at its first * command. * * @since 1.6, 2007-03-24 */ void reset() { // Re-initialize m_pc = m_cmds; m_vars = null; } /*************************************************************************** * Terminate this execution frame. * * @return * Execution frame that called (nested) this frame, where execution should * resume. This is null for the initial (outermost) frame. * * @since 1.2, 2007-03-16 */ ExecFrame pop() { // Clean up m_vars = null; return m_prev; } /*************************************************************************** * Define a local var value in this frame. * * @param name * Var name. * * @param val * The initial value of the var. * * @since 1.2, 2007-03-16 */ void defVar(String name, String val) { // Add the var to this frame's var set if (m_vars == null) m_vars = new HashMap(); m_vars.put(name, val); } /*************************************************************************** * Find a local var value in this frame. * * @param name * Var name. * * @param elem * Array element name, for a subscripted array name. This can be null, in * which case the var to be located is not an array element. * * @return * The current value of the var, or null if no such var exists in this frame. * * @since 1.13, 2007-05-31 (1.2, 2007-03-16) */ String findVar(String name, String elem) { // Find a var value within this frame's scope, innermost to outermost for (int i = m_outer.length; i >= 0; i--) { ExecFrame scope; String val; // Search in one of this frame's scopes scope = (i >= m_outer.length ? this : this.m_outer[i]); if (scope.m_vars != null) { val = scope.m_vars.get(name); if (val != null) { if (elem != null) { val = scope.m_vars.get(elem); if (val == null) val = VAL_EMPTY; } return val; } } } // Var was not found return null; } /*************************************************************************** * Set the value of a local var value in this frame. * * @param name * Var name. * * @param nest * Nesting depth, specifying the number of level of block scope nesting that * the var is defined at. * * @param elem * Array element name, for a subscripted array name. This can be null, in * which case the var to be modified is not an array element. * * @param val * Value to set the var to. * * @return * True if the var value was successfully set, otherwise false if no such var * exists in this frame. * * @since 1.13, 2007-05-31 (1.4, 2007-03-17) */ boolean setVar(String name, int nest, String elem, String val) { ExecFrame scope; // Find the var value within this frame's scope, innermost to outermost for (scope = this; nest > 0 && scope != null; nest--) scope = scope.m_prev; if (scope == null || scope.m_vars == null) return false; if (scope.m_vars.get(name) == null && elem == null) return false; // Set the var's new value if (elem != null) scope.m_vars.put(elem, val); else scope.m_vars.put(name, val); return true; } /*************************************************************************** * Print the current vars and their values. * * @since 1.7, 2007-04-11 */ void dumpVars(PrintWriter out) { if (out == null) return; // Display the contents of all user-defined vars for (int i = m_outer.length; i >= 0; i--) { ExecFrame scope; Iterator> list; // Display the vars within the execution frame scope = (i >= m_outer.length ? this : this.m_outer[i]); if (scope.m_vars == null) continue; list = scope.m_vars.entrySet().iterator(); while (list.hasNext()) { Map.Entry ent; String val; int len; // Display the vars within an execution frame ent = list.next(); val = ent.getValue(); out.print("{" + (scope.m_depth+1) + "} "); out.print(ent.getKey() + " = "); dumpString(val, out); out.println(); } } } /*************************************************************************** * Print the currently active stack frames. * * @since 1.11, 2007-04-18 */ void dumpStack(PrintWriter out) { if (out == null) return; // Display the contents of outer frames if (m_prev != null) m_prev.dumpStack(out); // Display the contents of this frame out.print("{" + m_depth + "} " + m_scope.m_name + " /" + m_scope.m_type + " @" + m_scope.m_lineNo); out.print(" pc:"); if (m_pc != null) out.print("@" + m_pc.m_lineNo); else out.print("end"); if (m_files != null) { int n; n = m_fileCnt; out.print(" file:" + n + "/" + m_files.size()); if (n <= m_files.size()) out.print(" '" + m_files.get(n-1) + "'"); } out.println(); } } // End ExecFrame.java