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