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

