import FESI.jslib.*; import java.io.*; import java.util.*; /** * ECMAScript インタプリタ「FESI」を利用した、簡単なプリプロセッサ * 処理プログラムです。 */ class jpre { String source, result; Vector props; final char startingChar = '#'; //プリプロセッサの開始文字 /** * プリプロセッサを構築します。 * * @param source ソースファイル * @param result 出力先のファイル * @param props 分岐のための値定義 */ jpre(String source, String result, Vector props) { this.source = source; this.result = result; this.props = props; } //メイン処理 void process() throws IOException, JSException { BufferedReader reader = null; BufferedWriter writer = null; try { //ファイル入出力の準備 File temp = new File("temp.es"); reader = new BufferedReader(new FileReader(source)); writer = new BufferedWriter(new FileWriter(temp)); //中間ファイルへの書き込み String s, t; while ((s = reader.readLine()) != null) { t = s.replace('\t', ' ').trim(); if (t.equals("")) { writer.write("put(\"" + s + "\");"); } else if (t.charAt(0) == startingChar) { int p = s.indexOf(startingChar); writer.write(s.substring(0, p) + s.substring(p + 1)); } else { writer.write("put(\"" + escape(s) + "\");"); } writer.newLine(); } reader.close(); writer.close(); //インタプリタを生成 JSGlobalObject global = null; try { global = JSUtil.makeEvaluator(); } catch (JSException e) { System.err.println("インタプリタ構築に失敗しました。"); System.exit(1); } writer = new BufferedWriter(new FileWriter(result)); global.setMember("put", new PutFunction(writer)); //コマンドラインで指定した値定義の適用 Enumeration e = props.elements(); while (e.hasMoreElements()) { global.eval((String)e.nextElement()); } //中間ファイルの実行 global.eval(new BufferedReader(new FileReader(temp)), "中間ファイル"); } finally { if (reader != null) reader.close(); if (writer != null) writer.close(); } } /** * 二重引用符と円記号をエスケープシーケンスで置き換えます。 * * @param 対象の文字列 * @return 置換結果 */ String escape(String s) { StringBuffer buf = new StringBuffer(); char[] chars = s.toCharArray(); int n = chars.length; for (int i = 0; i < n; i++) { switch (chars[i]) { case '"': buf.append("\\\""); break; case '\\': buf.append("\\\\"); break; default: buf.append(chars[i]); } } return buf.toString(); } /** * put 関数の内容を定義するオブジェクトです。 */ class PutFunction extends JSFunctionAdapter { BufferedWriter writer = null; PutFunction(BufferedWriter writer) { this.writer = writer; } public Object doCall(JSObject thisObject, Object[] args) throws JSException { try { writer.write(args[0].toString()); writer.newLine(); } catch (IOException e) { throw new JSException("put 関数の入出力失敗", e); } return null; } } public static void main(String[] args) { if (args.length >= 2) { try { Vector props = new Vector(); int n = args.length;; for (int i = 2; i < n; i++) { if ((args[i].indexOf('=')) > -1) { props.addElement(args[i] + ";"); } else { props.addElement(args[i] + " = true;"); } } jpre jp = new jpre(args[0], args[1], props); jp.process(); } catch (Exception e) { System.err.println(e.getMessage()); e.printStackTrace(); } } else { System.err.println("usage: jpre source outfile [property...]"); System.err.println(" property: name[=value]"); } } }