Java Q&A by Brad Cox Example 4: CP=/java/jdk/jre/lib/rt.jar:/webapp/WEB-INF/classes:/tomcat/lib/servlet.jar MLS=/tools/mls/mls -d ../mls.java SRC=$(shell find * -name CVS -prune -o -name \*.mls -print) all: $(SRC) jikes -classpath $(CP) -d /webapp/WEB-INF/classes `$(MLS) $(SRC)` Listing One package com.sdi.tools.mls; import java.util.*; import java.io.*; /** Multi-line Java Strings with Executable Inclusions * A Java Preprocessor by Brad Cox, Ph.D. bcox@superdistributed.com */ public class Main { private static int nestingLevel; private static String fileName = ""; private static int lineNumber; private static PushbackInputStream in; private static PrintWriter out; private static final String usage = "Usage: java com.sdi.jp.Main inputFileName..."; /** Insert method's description here. Creation date: (12/27/00 09:37:35) */ private static void doCode() throws Exception { nestingLevel++; int thisInt, nextInt; while((thisInt = in.read()) != -1) { switch(thisInt) { case '\n': lineNumber++; out.print((char)thisInt); break; case '{': nextInt = in.read(); if (nextInt == '{') { doString(lineNumber); break; } else { out.print((char)thisInt); in.unread(nextInt); break; } case '}': nextInt = (char)in.read(); if (nextInt == '}') { if (--nestingLevel <= 1) throw new Exception(fileName + ":: Extraneous }} at line " + lineNumber); return; } else { out.print((char)thisInt); in.unread((char)nextInt); break; } default: out.print((char)thisInt); break; } } } /** Process a PushBackInputStream */ public static void doStream(InputStream is, PrintWriter os) throws Exception { in = new PushbackInputStream(is); out = os; lineNumber = 0; nestingLevel = 0; doCode(); } private static void doString(int line) throws Exception { nestingLevel++; int thisInt, nextInt; out.print("\""); while((thisInt = in.read()) != -1) { switch(thisInt) { case '\n': lineNumber++; out.print("\\n\"+\n\""); break; case '\\': out.print("\\" + (char)thisInt); break; case '"': out.print("\\\""); break; case '{': nextInt = in.read(); if (nextInt == '{') { out.print("\"+"); doCode(); out.print("+\""); break; } else { out.print((char)thisInt); in.unread(nextInt); break; } case '}': nextInt = (char)in.read(); if (nextInt == '}') { out.print("\""); return; } else { out.print((char)thisInt); in.unread((char)nextInt); break; } default: out.print((char)thisInt); break; } } throw new IOException(fileName + ": unterminated {{string}} at line " + line); } /** Insert the method's description here. Creation date: (12/27/00 09:24:51) * @param args java.lang.String[] */ public static void main(String[] args) { File outDirectory = new File("."); try { Vector files = new Vector(); for (int i = 0; i < args.length; i++) { if (args[i].startsWith("-")) { if (args[i].startsWith("-d")) { outDirectory = new File(args[++i]); if (!outDirectory.isDirectory() && !outDirectory.mkdirs()) { System.err.println("Couldn't create " + outDirectory); System.exit(-1); } } else System.err.println(usage + "\n invalid switch: " + args[i]); } else files.addElement(args[i]); } for (Enumeration e = files.elements(); e.hasMoreElements(); ) { fileName = (String)e.nextElement(); lineNumber = 0; File inFile = new File(fileName); BufferedInputStream bis = null; try { FileInputStream fis = new FileInputStream(inFile); bis = new BufferedInputStream(fis); } catch (FileNotFoundException ex) { System.err.println("Cannot read " + fileName); continue; } String base = fileName.substring(0, fileName.lastIndexOf(".")); File outFile = new File(outDirectory, base + ".java"); PrintWriter pw = null; try { FileOutputStream fos = new FileOutputStream(outFile); BufferedOutputStream bos = new BufferedOutputStream(fos); pw = new PrintWriter(bos); } catch (IOException ex) { System.err.println("Cannot write " + outFile); continue; } doStream(bis, pw); bis.close(); pw.close(); /** Print names of output files on stdout to support * the usage pattern: jikes `mls inputfiles` */ System.out.println(outFile); } } catch (Throwable e) { System.err.println(e.getMessage()); e.printStackTrace(); System.exit(-1); } } } 4