//==============================================================================
// 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