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