duke@435: /* trims@1907: * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: duke@435: import java.io.*; duke@435: import java.util.*; duke@435: duke@435: class jvmtiEnvFill { duke@435: duke@435: public static void main(String[] args) throws IOException { duke@435: if (args.length != 3) { duke@435: System.err.println("usage: "); duke@435: System.exit(1); duke@435: } duke@435: String filledFN = args[0]; duke@435: String stubFN = args[1]; duke@435: String resultFN = args[2]; duke@435: duke@435: SourceFile filledSF = new SourceFile(filledFN); duke@435: SourceFile stubSF = new SourceFile(stubFN); duke@435: duke@435: duke@435: stubSF.fill(filledSF); duke@435: duke@435: PrintWriter out = new PrintWriter(new FileWriter(resultFN)); duke@435: stubSF.output(out); duke@435: out.close(); duke@435: } duke@435: } duke@435: duke@435: class SourceFile { duke@435: duke@435: static final String endFilePrefix = "// end file prefix"; duke@435: static final String functionPrefix = "JvmtiEnv::"; duke@435: duke@435: final String fn; duke@435: LineNumberReader in; duke@435: String line; duke@435: List top = new ArrayList(); duke@435: List before = new ArrayList(); duke@435: boolean inFilePrefix = true; duke@435: List functions = new ArrayList(); duke@435: Map functionMap = new HashMap(); duke@435: duke@435: class Function { duke@435: String name; duke@435: String args; duke@435: String compareArgs; duke@435: List comment; duke@435: List body = new ArrayList(); duke@435: duke@435: Function() throws IOException { duke@435: line = in.readLine(); duke@435: String trimmed = line.trim(); duke@435: if (!trimmed.startsWith(functionPrefix)) { duke@435: error("expected '" + functionPrefix + "'"); duke@435: } duke@435: int index = trimmed.indexOf('(', functionPrefix.length()); duke@435: if (index == -1) { duke@435: error("missing open paren"); duke@435: } duke@435: name = trimmed.substring(functionPrefix.length(), index); duke@435: int index2 = trimmed.indexOf(')', index); duke@435: if (index2 == -1) { duke@435: error("missing close paren - must be on same line"); duke@435: } duke@435: args = trimmed.substring(index+1, index2); duke@435: compareArgs = args.replaceAll("\\s", ""); duke@435: String tail = trimmed.substring(index2+1).trim(); duke@435: if (!tail.equals("{")) { duke@435: error("function declaration first line must end with open bracket '{', instead got '" + duke@435: tail + "'"); duke@435: } duke@435: while(true) { duke@435: line = in.readLine(); duke@435: if (line == null) { duke@435: line = ""; // so error does not look wierd duke@435: error("unexpected end of file"); duke@435: } duke@435: if (line.startsWith("}")) { duke@435: break; duke@435: } duke@435: body.add(line); duke@435: } duke@435: String expected = "} /* end " + name + " */"; duke@435: trimmed = line.replaceAll("\\s",""); duke@435: if (!trimmed.equals(expected.replaceAll("\\s",""))) { duke@435: error("function end is malformed - should be: " + expected); duke@435: } duke@435: // copy over the comment prefix duke@435: comment = before; duke@435: before = new ArrayList(); duke@435: } duke@435: duke@435: void remove() { duke@435: functionMap.remove(name); duke@435: } duke@435: duke@435: String fileName() { duke@435: return fn; duke@435: } duke@435: duke@435: void fill(Function filledFunc) { duke@435: if (filledFunc == null) { duke@435: System.err.println("Warning: function " + name + " missing from filled file"); duke@435: body.add(0, " /*** warning: function added and not filled in ***/"); duke@435: } else { duke@435: int fbsize = filledFunc.body.size(); duke@435: int bsize = body.size(); duke@435: if (fbsize > bsize || !body.subList(bsize-fbsize,bsize).equals(filledFunc.body)) { duke@435: // it has actually been filled in duke@435: body = filledFunc.body; duke@435: if (!compareArgs.equals(filledFunc.compareArgs)) { duke@435: System.err.println("Warning: function " + name + duke@435: ": filled and stub arguments differ"); duke@435: System.err.println(" old (filled): " + filledFunc.args); duke@435: System.err.println(" new (stub): " + args); duke@435: body.add(0, " /*** warning: arguments changed, were: " + duke@435: filledFunc.args + " ***/"); duke@435: } duke@435: } duke@435: filledFunc.remove(); // mark used duke@435: } duke@435: } duke@435: duke@435: void output(PrintWriter out) { duke@435: Iterator it = comment.iterator(); duke@435: while (it.hasNext()) { duke@435: out.println(it.next()); duke@435: } duke@435: out.println("jvmtiError"); duke@435: out.print(functionPrefix); duke@435: out.print(name); duke@435: out.print('('); duke@435: out.print(args); duke@435: out.println(") {"); duke@435: it = body.iterator(); duke@435: while (it.hasNext()) { duke@435: out.println(it.next()); duke@435: } duke@435: out.print("} /* end "); duke@435: out.print(name); duke@435: out.println(" */"); duke@435: } duke@435: } duke@435: duke@435: SourceFile(String fn) throws IOException { duke@435: this.fn = fn; duke@435: Reader reader = new FileReader(fn); duke@435: in = new LineNumberReader(reader); duke@435: duke@435: while (readGaps()) { duke@435: Function func = new Function(); duke@435: functionMap.put(func.name, func); duke@435: functions.add(func); duke@435: } duke@435: duke@435: in.close(); duke@435: } duke@435: duke@435: void error(String msg) { duke@435: System.err.println("Fatal error parsing file: " + fn); duke@435: System.err.println("Line number: " + in.getLineNumber()); duke@435: System.err.println("Error message: " + msg); duke@435: System.err.println("Source line: " + line); duke@435: System.exit(1); duke@435: } duke@435: duke@435: boolean readGaps() throws IOException { duke@435: while(true) { duke@435: line = in.readLine(); duke@435: if (line == null) { duke@435: return false; // end of file duke@435: } duke@435: if (!inFilePrefix && line.startsWith("}")) { duke@435: error("unexpected close bracket in first column, outside of function.\n"); duke@435: } duke@435: String trimmed = line.trim(); duke@435: if (line.startsWith("jvmtiError")) { duke@435: if (trimmed.equals("jvmtiError")) { duke@435: if (inFilePrefix) { duke@435: error("unexpected 'jvmtiError' line in file prefix.\n" + duke@435: "is '" + endFilePrefix + "'... line missing?"); duke@435: } duke@435: return true; // beginning of a function duke@435: } else { duke@435: error("extra characters at end of 'jvmtiError'"); duke@435: } duke@435: } duke@435: if (inFilePrefix) { duke@435: top.add(line); duke@435: } else { duke@435: trimmed = line.trim(); duke@435: if (!trimmed.equals("") && !trimmed.startsWith("//") && !trimmed.startsWith("#")) { duke@435: error("only comments and blank lines allowed between functions"); duke@435: } duke@435: before.add(line); duke@435: } duke@435: if (line.replaceAll("\\s","").toLowerCase().startsWith(endFilePrefix.replaceAll("\\s",""))) { duke@435: if (!inFilePrefix) { duke@435: error("excess '" + endFilePrefix + "'"); duke@435: } duke@435: inFilePrefix = false; duke@435: } duke@435: } duke@435: } duke@435: duke@435: void fill(SourceFile filledSF) { duke@435: // copy beginning of file straight from filled file duke@435: top = filledSF.top; duke@435: duke@435: // file in functions duke@435: Iterator it = functions.iterator(); duke@435: while (it.hasNext()) { duke@435: Function stubFunc = (Function)(it.next()); duke@435: Function filledFunc = (Function)filledSF.functionMap.get(stubFunc.name); duke@435: stubFunc.fill(filledFunc); duke@435: } duke@435: if (filledSF.functionMap.size() > 0) { duke@435: System.err.println("Warning: the following functions were present in the " + duke@435: "filled file but missing in the stub file and thus not copied:"); duke@435: it = filledSF.functionMap.values().iterator(); duke@435: while (it.hasNext()) { duke@435: System.err.println(" " + ((Function)(it.next())).name); duke@435: } duke@435: } duke@435: } duke@435: duke@435: void output(PrintWriter out) { duke@435: Iterator it = top.iterator(); duke@435: while (it.hasNext()) { duke@435: out.println(it.next()); duke@435: } duke@435: it = functions.iterator(); duke@435: while (it.hasNext()) { duke@435: Function stubFunc = (Function)(it.next()); duke@435: stubFunc.output(out); duke@435: } duke@435: } duke@435: }