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