//============================================================================== // BlockDef.java //============================================================================== package tribble.net.ftp.shell; import java.io.PrintWriter; import java.lang.Exception; import java.lang.String; import java.util.HashMap; /******************************************************************************* * FTP command begin/end block or func definition. * * * @version API 1.1 $Revision: 1.10 $ $Date: 2010/07/12 22:29:52 $ * @since API 1.0, 2007-03-16 * @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 CommandExec * @see ExecFrame */ class BlockDef implements CommandCodes { /** Revision information. */ static final String REV = "@(#)tribble/net/ftp/shell/BlockDef.java API 1.1 $Revision: 1.10 $ $Date: 2010/07/12 22:29:52 $\n"; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constants //---------------------------------------- // Locally defined name types private static final short NAMETYPE_VAR = 1; private static final short NAMETYPE_LABEL = 2; private static final short NAMETYPE_FUNC = 3; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Variables /** Name of this block definition. */ String m_name; /** Block type (begin/end, foreach, repeat). */ String m_type; /** Outer block containing this block definition. */ BlockDef m_outer; /** Parent command enclosing this block. */ CommandNode m_parent; /** Source line number. */ int m_lineNo; /** Scope nesting depth. */ int m_depth; /** Commands (statements) in this block definition. */ private CommandNode m_cmds; /** Local func definitions. */ private HashMap m_funcs; /** Local var definitions. */ private HashMap m_vars; /** Local statement label definitions. */ private HashMap m_labels; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constructors /*************************************************************************** * Constructor. * * @param name * Name of this block. Funcs have user-defined names, while begin/end block * have names such as ".42". * * @param lineNo * Source line number where the block is defined. * * @param outer * Begin/end block or func containing this block. This is null for the * outermost (file) scope, which has no outer scope. * * @param cmd * Parent command containing this block. This is null for the outermost * (file) scope, and for block commands having no controlling command. * * @since 1.7, 2007-08-02 */ BlockDef(String name, int lineNo, BlockDef outer, CommandNode cmd) { // Initialize m_name = name; m_lineNo = lineNo; m_outer = outer; m_parent = cmd; // Set up if (outer != null) m_depth = outer.m_depth+1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Methods /*************************************************************************** * Establish the commands (statements) for this block definition. * * @param cmds * First command (statement) defined within the begin/end block or func, or * null if there are no commands. * * @since 1.1, 2007-03-16 */ void setCmds(CommandNode cmds) { m_cmds = cmds; } /*************************************************************************** * Determine if this block definition is a func body. * * @since 1.2, 2007-03-21 */ boolean isFunc() { // Examine the name of the block return (m_type == CMD_FUNC); } /*************************************************************************** * Add a local func definition to this block definition. * * @param name * Func name. * * @param cmd * Command ({@link #CMD_FUNC CMD_FUNC}) containing the func definition. * * @return * True if the func was added successfully, or false if it is already defined * within this block definition. * * @since 1.1, 2007-03-16 */ boolean addFuncDef(String name, CommandNode cmd) { // Add a func that is local to this block definition if (m_funcs == null) m_funcs = new HashMap(); if (m_funcs.get(name) != null) return false; m_funcs.put(name, cmd); return true; } /*************************************************************************** * Retrieve a func definition within this block's scope. * * @param name * Func name. * * @return * The command node ({@link #CMD_FUNC CMD_FUNC}) containing the func * definition, or null if no such func exists within the scope of this block * definition. * * @since 1.1, 2007-03-16 */ CommandNode findFuncDef(String name) { return findADef(name, NAMETYPE_FUNC); } /*************************************************************************** * Find the block containing a func definition. * * @param name * Var name. * * @return * The block definition containing the func definition ('func' command), or * null if the func is not defined within the scope of this block or any of * its outer blocks. * * @since 1.6, 2007-04-10 */ BlockDef findFuncBlock(String name) { return findABlock(name, NAMETYPE_FUNC); } /*************************************************************************** * Add a local var definition to this block definition. * * @param name * Var name. * * @param cmd * Command ({@link #CMD_VAR CMD_VAR}) containing the var definition. * * @return * True if the var was added successfully, or false if it is already defined * within this block definition. * * @since 1.1, 2007-03-16 */ boolean addVarDef(String name, CommandNode cmd) { // Add a var that is local to this block definition if (m_vars == null) m_vars = new HashMap(); if (m_vars.get(name) != null) return false; m_vars.put(name, cmd); return true; } /*************************************************************************** * Retrieve a var definition within this block's scope. * * @param name * Var name. * * @return * The command node ({@link #CMD_VAR CMD_VAR}) containing the var definition, * or null if no such var exists in the scope of this block definition. * * @since 1.1, 2007-03-16 */ CommandNode findVarDef(String name) { return findADef(name, NAMETYPE_VAR); } /*************************************************************************** * Find the block containing a var definition. * * @param name * Var name. * * @return * The block definition containing the var definition ('var' command), or * null if the var is not defined within the scope of this block or any of * its outer blocks. * * @since 1.4, 2007-04-06 */ BlockDef findVarBlock(String name) { return findABlock(name, NAMETYPE_VAR); } /*************************************************************************** * Add a local label definition to this block definition. * * @param name * Label name. * * @param cmd * Command ({@link #CMD_LABEL CMD_LABEL}) containing the statement label * definition. * * @return * True if the label was added successfully, or false if it is already * defined within this block definition. * * @since 1.1, 2007-03-16 */ boolean addLabelDef(String name, CommandNode cmd) { // Add a label that is local to this block definition if (m_labels == null) m_labels = new HashMap(); if (m_labels.get(name) != null) return false; m_labels.put(name, cmd); return true; } /*************************************************************************** * Retrieve a local label definition in this block definition. * * @param name * Label name. * * @return * The command node ({@link #CMD_LABEL CMD_LABEL}) containing the statement * label, or null if no such label exists in this block definition. * * @since 1.1, 2007-03-16 */ CommandNode findLabelDef(String name) { return findADef(name, NAMETYPE_LABEL); } /*************************************************************************** * Find the block containing a label definition. * * @param name * Label name. * * @return * The block definition containing the label definition, or null if the label * is not defined within the scope of this block or any of its outer blocks. * Blocks outside func bodies are not searched. * * @since 1.5, 2007-04-09 */ BlockDef findLabelBlock(String name) { return findABlock(name, NAMETYPE_LABEL); } /*************************************************************************** * Retrieve a var/label/func definition within this block's scope. * * @param name * Var, label, or func name. * * @param type * One of the {@link #NAMETYPE_VAR NAMETYPE_XXX} constants, specifying * what kind of name name is. * * @return * The command node containing the definition of the name, or null if it does * not exist in the scope of this block. Labels are not searched for outside * func bodies. * * @since 1.6, 2007-04-10 */ private CommandNode findADef(String name, int type) { BlockDef scope; // Search for the definition within this block's scope for (scope = this; scope != null; scope = scope.m_outer) { HashMap list = null; // Search the next block for the definition switch (type) { case NAMETYPE_VAR: list = scope.m_vars; break; case NAMETYPE_LABEL: list = scope.m_labels; break; case NAMETYPE_FUNC: list = scope.m_funcs; break; } if (list != null) { CommandNode def; def = list.get(name); if (def != null) return def; } // Expand the search to the next outer block, // but do not search for labels outside a func block if (type == NAMETYPE_LABEL && scope.isFunc()) break; } // The definition was not found return null; } /*************************************************************************** * Find the block containing a var/label/func definition. * * @param name * Var, label, or func name. * * @param type * One of the {@link #NAMETYPE_VAR NAMETYPE_XXX} constants, specifying * what kind of name name is. * * @return * The block definition containing the definition of the name, or null if it * is not defined within the scope of this block or any of its outer blocks. * Labels are not searched for outside func bodies. * * @since 1.6, 2007-04-10 */ private BlockDef findABlock(String name, int type) { BlockDef scope; // Search for the definition within this block's scope for (scope = this; scope != null; scope = scope.m_outer) { HashMap list = null; // Search the next block for the definition switch (type) { case NAMETYPE_VAR: list = scope.m_vars; break; case NAMETYPE_LABEL: list = scope.m_labels; break; case NAMETYPE_FUNC: list = scope.m_funcs; break; } // Search the next block for the definition if (list != null && list.get(name) != null) return scope; // Expand the search to the next outer block, // but do not search for labels outside a func block if (type == NAMETYPE_LABEL && scope.isFunc()) break; } // The definition was not found return null; } /*************************************************************************** * Release objects that are no longer needed by this block definition after a * successful parse. * * @since 1.8, 2007-08-05 */ void scrub() { m_funcs = null; m_vars = null; m_labels = null; } /*************************************************************************** * Pretty-print this block definition and its subordinate blocks. * * @since 1.9, 2007-08-07 */ void printTree(PrintWriter out) { if (out != null) printTree(out, ""); } /*************************************************************************** * Pretty-print this block definition and its subordinate blocks. * * @since 1.9, 2007-08-07 */ private void printTree(PrintWriter out, String indent) { CommandNode cmd; // Print this block print(out, indent); // Print out this block's local definitions for (cmd = m_cmds; cmd != null; cmd = cmd.m_next) { String type = null; String name = null; if (cmd.m_cmd == CMD_LABEL) { type = "label"; name = (String) cmd.m_args[0]; } else if (cmd.m_cmd == CMD_VAR) { type = "var "; name = (String) cmd.m_args[0]; } else if (cmd.m_cmd == CMD_FUNC) { type = "func "; name = (String) cmd.m_args[0]; } if (type != null) { out.print(indent); out.println(" " + type + " " + name + " @" + cmd.m_lineNo); } } // Print this block's children (nested) blocks for (cmd = m_cmds; cmd != null; cmd = cmd.m_next) { if (cmd.m_cmd == CMD_GOTO) continue; if (cmd.m_args == null) continue; for (int i = 0; i < cmd.m_args.length; i++) { if (cmd.m_args[i] instanceof BlockDef) { BlockDef sub; sub = (BlockDef) cmd.m_args[i]; if (sub.m_lineNo > this.m_lineNo) sub.printTree(out, indent + " "); } } } } /*************************************************************************** * Pretty-print this block definition. * * @since 1.9, 2007-08-07 */ private void print(PrintWriter out, String indent) { // Display the contents of this block definition out.print(indent); out.print(m_lineNo + ": {" + m_depth + "} \"" + m_name + "\" /" + m_type); if (m_parent != null) out.print(" : " + m_parent.m_cmd + " @" + m_parent.m_lineNo); out.println(); } } // End BlockDef.java