//============================================================================== // CommandFile.java //============================================================================== package tribble.net.ftp.shell; // System imports import java.io.IOException; import java.io.Reader; import java.io.PrintWriter; import java.lang.Exception; import java.lang.String; /******************************************************************************* * FTP source command script. * Manages the input stream for a single command script. * * * @version $Revision: 1.3 $ $Date: 2007/03/27 23:54:44 $ * @since API 1.0, 2007-03-22 * @author David R. Tribble (david@tribble.com). *

* Copyright ©2007 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 CommandLexer */ class CommandFile { // Identification /** Revision information. */ static final String REV = "@(#)tribble/net/ftp/shell/CommandFile.java $Revision: 1.3 $ $Date: 2007/03/27 23:54:44 $\n"; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Variables /** Source name. */ private String m_srcName = "-"; /** Previous (outer) command script. */ private CommandFile m_prev; /** Input source stream. */ private Reader m_in; /** Error/warning message output stream. */ private PrintWriter m_out; /** Source line number of the next input character. */ int m_lineNo = 1; /** Pushed-back character. */ private int m_nextChar = -1; /** Last character read. */ private int m_lastCh = -1; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Constructors /*************************************************************************** * Constructor. * * @param in * Input source stream. * * @param out * Error/warning message output stream. * * @param prev * Previous source stream that includes this one. * * @since 1.1, 2007-03-22 */ CommandFile(Reader in, PrintWriter out, CommandFile prev) { m_in = in; m_out = out; m_prev = prev; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Methods /*************************************************************************** * Establish the name of this source stream (the command script). * * @param name * Name of the input stream. This is usually a filename, but it can be any * kind of identification for the source stream. * * @since 1.1, 2007-03-22 */ void setSourceName(String name) { m_srcName = name; } /*************************************************************************** * Retrieve the name of this source stream (the command script). * * @return * Name of the input stream. This is usually a filename, but it can be any * kind of identification for the source stream. * * @since 1.3, 2007-03-27 */ String getSourceName() { return (m_srcName); } /*************************************************************************** * Terminate this input source stream. * * @return * The previous source stream that included this one, or null if this was the * first (top-most) source stream. Note that the input stream itself is * not closed. * * @since 1.1, 2007-03-22 */ CommandFile pop() { // Shut down this source stream m_in = null; return (m_prev); } /*************************************************************************** * Read the next input characters from this input source stream. * This also updates {@link #m_lineNo} to reflect the source line number of * the returned character. * *

* Each newline (end of line) sequence (CR, LF, CR/LF) is translated into a * single newline character ('\n'). A newline character * ('\n') is always returned as the last character before the * end of the input stream, even if the stream does not contain a final * newline sequence. * * @return * The next character from the input source stream, or '\n' if an * end of line (newline) is reached, or -1 if the end of the source stream * is reached. Note that the stream is not closed after the end is * reached. * * @since 1.1, 2007-03-22 */ int readChar() throws IOException { int ch; int prev; // Check for a pushed-back character if (m_nextChar >= 0) { ch = m_nextChar; m_nextChar = -1; return (ch); } // Check for end of input if (m_in == null) return (-1); // Read the next input character ch = m_in.read(); // Handle end of input if (ch < 0) { if (m_lastCh != '\r' && m_lastCh != '\n') { // Insert a final newline m_out.println(m_srcName + ":" + m_lineNo + ": warning: Missing a newline at end of file"); m_out.flush(); m_lastCh = '\n'; return ('\n'); } else { m_in = null; return (-1); } } // Handle end of line (newline) prev = m_lastCh; m_lastCh = ch; if (ch == '\r') { m_lineNo++; return ('\n'); } else if (ch == '\n') { if (prev == '\r') { // Ignore LF of CR/LF pair, read another char return (readChar()); } else { m_lineNo++; return ('\n'); } } else if (ch == '\t' || ch == '\f') { return (' '); } else if (Character.isISOControl((char) ch)) { String s; // Unprintable control character, treat like a space s = (ch < 0x10 ? "0" : "") + Integer.toHexString(ch); s = s.toUpperCase(); m_out.println(m_srcName + ":" + m_lineNo + ": warning: Unprintable character (0x" + s + ") replaced with a space"); m_out.flush(); return (' '); } else { // Normal character return (ch); } } /*************************************************************************** * Push back an input character from the source script. * * @see #readChar readChar() * * @since 1.1, 2007-03-22 */ void unReadChar(int ch) { m_nextChar = ch; } } // End CommandFile.java