import java.io.*; /** * This class handles all IO for the compiler application. * Several streams are managed by this class. * * @author Hyung-Joon Kim */ public class CompilerIO { //----------------------------------------------------------------- /** the input file */ private BufferedReader src; /** the current output Writer, either the obj file or the buffer. */ private PrintWriter dst; /** the output file */ private PrintWriter obj; /** the temporary buffer */ private PrintWriter buf; /** the underlying StringWriter used in implementing the buffer */ private StringWriter sw; private boolean echoing = false; private String echoPrefix = null; //----------------------------------------------------------------- /** * Create a new CompilerIO object, using the file name given for the * input file, and creating the output file name based on the input * file name. To create the output file name, the extension is * removed from the input file name, and replaced with the given * extension. * @param srcName the name of the input file * @param objX the extension to use for the output file. Does * not include the dot that separates the name from the extension. * @throws IOException If any input or output exception occurs while * opening the files. */ public CompilerIO(String srcName, String objX) throws IOException { src = new BufferedReader(new FileReader(srcName)); int dot = srcName.lastIndexOf('.'); String objName = (dot > -1) ? srcName.substring(0,dot) : srcName; objName = objName + "." + objX; obj = new PrintWriter(new BufferedWriter(new FileWriter(objName)),true); dst = obj; buf = null; } /** * Create a new CompilerIO object, using the file names given for the * input file and the output file. If the extension is * not null, then the given extension is added to the output file name * after a period. * @param srcName the name of the input file * @param objName the name of the output file * @param objX the extension to use for the output file. Does * not include the dot that separates the name from the extension. * @throws IOException If any input or output exception occurs while * opening the files. */ public CompilerIO(String srcName, String objName, String objX) throws IOException { src = new BufferedReader(new FileReader(srcName)); String dstName = (objX == null) ? objName : objName + "." + objX; obj = new PrintWriter(new BufferedWriter(new FileWriter(dstName)),true); dst = obj; buf = null; } /** * Read one line of input from the input file. * @return A String containing the contents of the line, not including * any line-termination characters, or null if the end of the stream * has been reached. * @throws IOException If an I/O error occurs while reading */ public String readSrcLine() throws IOException { String s = src.readLine(); if (s != null && echoing) { emitWithPrefix(s); } return s; } /** * Write a string to the currently active output Writer. * @param s The String to write out. */ public void emit(String s) { dst.println(s); } /** * Write the contents of the temporary buffer to the output file. * This can only be called when the buffer is closed. This method * will return silently without doing anything if the buffer is the * currently active output Writer. */ public void emitBuffer() { if (buf == null) return; if (sw == null) return; if (buf == dst) return; dst.print(sw.toString()); } /** * Write the prefix and then the given string to * the currently active output Writer. * @param s The String to write out. */ public void emitWithPrefix(String s) { if (echoPrefix != null) { dst.print(echoPrefix); } dst.println(s); } /** * Copy an entire file to the currently active output Writer. * This is a direct copy and nothing is done to the file on * the way out, ie, no prefix is applied. * @param fileName the name of the file to copy * @throws IOException If an IO error occurs */ public void emitFile(String fileName) throws IOException { BufferedReader in = new BufferedReader(new FileReader(fileName)); String line; while ((line = in.readLine()) != null) { dst.println(line); } in.close(); } /** * Set the echoing property. If true, every line read from src stream is * copied to the output stream. * @param e true or false. */ public void setEchoing(boolean e) { echoing = e; } /** * Get the current state of the echoing property. * @return the current echoing state. */ public boolean getEchoing() { return echoing; } /** * Set the echo prefix that is written out before each * echoed line or other String written with emitWithPrefix. * @param p the String prefix */ public void setEchoPrefix(String p) { echoPrefix = p; } /** * Get the echo prefix string. * @return the current value of the echo prefix. */ public String getEchoPrefix() { return echoPrefix; } /** * Create a new temporary Writer for buffering and * set it to be the target of all the emit methods. */ public void openBuffer() { sw = new StringWriter(); buf = new PrintWriter(sw); dst = buf; } /** * Close the temporary Writer that we've been using to * buffer the output and switch back to the output file * as the target of all the emit methods. This method * should be called before using emitBuffer to copy the * contents of the temporary buffer to the output file. */ public void closeBuffer() { buf.flush(); buf.close(); dst = obj; } /** * Close the input, output, and temporary streams. * @throws IOException If an I/O error occurs while closing */ public void closeAll() throws IOException { if (src != null) src.close(); if (obj != null) obj.close(); if (buf != null) buf.close(); src = null; obj = buf = dst = null; } /** * Run a simple test of this CompilerIO class. * @param arg
pathname to read. If not specified, then the program * tries to read "CompilerIO.java". The CompilerIO * constructor builds the output name from the input name. * @throws IOException If an IO error occurs while processing */ public static void main(String[] arg) throws IOException { CompilerIO c; if (arg.length == 0) { c = new CompilerIO("CompilerIO.java","ps"); } else { c = new CompilerIO(arg[0],"ps"); } c.setEchoing(true); c.setEchoPrefix("% "); String s = c.readSrcLine(); while (s != null) { s = c.readSrcLine(); } c.emitFile("CompilerIO.java"); c.closeAll(); } }