1 /* 2 * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 import java.io.*; 26 import java.util.*; 27 28 class jvmtiEnvFill { 29 main(String[] args)30 public static void main(String[] args) throws IOException { 31 if (args.length != 3) { 32 System.err.println("usage: <filledFile> <stubFile> <resultFile>"); 33 System.exit(1); 34 } 35 String filledFN = args[0]; 36 String stubFN = args[1]; 37 String resultFN = args[2]; 38 39 SourceFile filledSF = new SourceFile(filledFN); 40 SourceFile stubSF = new SourceFile(stubFN); 41 42 43 stubSF.fill(filledSF); 44 45 PrintWriter out = new PrintWriter(new FileWriter(resultFN)); 46 stubSF.output(out); 47 out.close(); 48 } 49 } 50 51 class SourceFile { 52 53 static final String endFilePrefix = "// end file prefix"; 54 static final String functionPrefix = "JvmtiEnv::"; 55 56 final String fn; 57 LineNumberReader in; 58 String line; 59 List<String> top = new ArrayList<String>(); 60 List<String> before = new ArrayList<String>(); 61 boolean inFilePrefix = true; 62 List<Function> functions = new ArrayList<Function>(); 63 Map<String, Function> functionMap = new HashMap<String, Function>(); 64 65 class Function { 66 String name; 67 String args; 68 String compareArgs; 69 List comment; 70 List<String> body = new ArrayList<String>(); 71 Function()72 Function() throws IOException { 73 line = in.readLine(); 74 String trimmed = line.trim(); 75 if (!trimmed.startsWith(functionPrefix)) { 76 error("expected '" + functionPrefix + "'"); 77 } 78 int index = trimmed.indexOf('(', functionPrefix.length()); 79 if (index == -1) { 80 error("missing open paren"); 81 } 82 name = trimmed.substring(functionPrefix.length(), index); 83 int index2 = trimmed.indexOf(')', index); 84 if (index2 == -1) { 85 error("missing close paren - must be on same line"); 86 } 87 args = trimmed.substring(index+1, index2); 88 compareArgs = args.replaceAll("\\s", ""); 89 String tail = trimmed.substring(index2+1).trim(); 90 if (!tail.equals("{")) { 91 error("function declaration first line must end with open bracket '{', instead got '" + 92 tail + "'"); 93 } 94 while(true) { 95 line = in.readLine(); 96 if (line == null) { 97 line = ""; // so error does not look wierd 98 error("unexpected end of file"); 99 } 100 if (line.startsWith("}")) { 101 break; 102 } 103 body.add(line); 104 } 105 String expected = "} /* end " + name + " */"; 106 trimmed = line.replaceAll("\\s",""); 107 if (!trimmed.equals(expected.replaceAll("\\s",""))) { 108 error("function end is malformed - should be: " + expected); 109 } 110 // copy over the comment prefix 111 comment = before; 112 before = new ArrayList<String>(); 113 } 114 remove()115 void remove() { 116 functionMap.remove(name); 117 } 118 fileName()119 String fileName() { 120 return fn; 121 } 122 fill(Function filledFunc)123 void fill(Function filledFunc) { 124 if (filledFunc == null) { 125 System.err.println("Warning: function " + name + " missing from filled file"); 126 body.add(0, " /*** warning: function added and not filled in ***/"); 127 } else { 128 int fbsize = filledFunc.body.size(); 129 int bsize = body.size(); 130 if (fbsize > bsize || !body.subList(bsize-fbsize,bsize).equals(filledFunc.body)) { 131 // it has actually been filled in 132 body = filledFunc.body; 133 if (!compareArgs.equals(filledFunc.compareArgs)) { 134 System.err.println("Warning: function " + name + 135 ": filled and stub arguments differ"); 136 System.err.println(" old (filled): " + filledFunc.args); 137 System.err.println(" new (stub): " + args); 138 body.add(0, " /*** warning: arguments changed, were: " + 139 filledFunc.args + " ***/"); 140 } 141 } 142 filledFunc.remove(); // mark used 143 } 144 } 145 output(PrintWriter out)146 void output(PrintWriter out) { 147 Iterator it = comment.iterator(); 148 while (it.hasNext()) { 149 out.println(it.next()); 150 } 151 out.println("jvmtiError"); 152 out.print(functionPrefix); 153 out.print(name); 154 out.print('('); 155 out.print(args); 156 out.println(") {"); 157 it = body.iterator(); 158 while (it.hasNext()) { 159 out.println(it.next()); 160 } 161 out.print("} /* end "); 162 out.print(name); 163 out.println(" */"); 164 } 165 } 166 SourceFile(String fn)167 SourceFile(String fn) throws IOException { 168 this.fn = fn; 169 Reader reader = new FileReader(fn); 170 in = new LineNumberReader(reader); 171 172 while (readGaps()) { 173 Function func = new Function(); 174 functionMap.put(func.name, func); 175 functions.add(func); 176 } 177 178 in.close(); 179 } 180 error(String msg)181 void error(String msg) { 182 System.err.println("Fatal error parsing file: " + fn); 183 System.err.println("Line number: " + in.getLineNumber()); 184 System.err.println("Error message: " + msg); 185 System.err.println("Source line: " + line); 186 System.exit(1); 187 } 188 readGaps()189 boolean readGaps() throws IOException { 190 while(true) { 191 line = in.readLine(); 192 if (line == null) { 193 return false; // end of file 194 } 195 if (!inFilePrefix && line.startsWith("}")) { 196 error("unexpected close bracket in first column, outside of function.\n"); 197 } 198 String trimmed = line.trim(); 199 if (line.startsWith("jvmtiError")) { 200 if (trimmed.equals("jvmtiError")) { 201 if (inFilePrefix) { 202 error("unexpected 'jvmtiError' line in file prefix.\n" + 203 "is '" + endFilePrefix + "'... line missing?"); 204 } 205 return true; // beginning of a function 206 } else { 207 error("extra characters at end of 'jvmtiError'"); 208 } 209 } 210 if (inFilePrefix) { 211 top.add(line); 212 } else { 213 trimmed = line.trim(); 214 if (!trimmed.equals("") && !trimmed.startsWith("//") && !trimmed.startsWith("#")) { 215 error("only comments and blank lines allowed between functions"); 216 } 217 before.add(line); 218 } 219 if (line.replaceAll("\\s","").toLowerCase().startsWith(endFilePrefix.replaceAll("\\s",""))) { 220 if (!inFilePrefix) { 221 error("excess '" + endFilePrefix + "'"); 222 } 223 inFilePrefix = false; 224 } 225 } 226 } 227 fill(SourceFile filledSF)228 void fill(SourceFile filledSF) { 229 // copy beginning of file straight from filled file 230 top = filledSF.top; 231 232 // file in functions 233 Iterator it = functions.iterator(); 234 while (it.hasNext()) { 235 Function stubFunc = (Function)(it.next()); 236 Function filledFunc = (Function)filledSF.functionMap.get(stubFunc.name); 237 stubFunc.fill(filledFunc); 238 } 239 if (filledSF.functionMap.size() > 0) { 240 System.err.println("Warning: the following functions were present in the " + 241 "filled file but missing in the stub file and thus not copied:"); 242 it = filledSF.functionMap.values().iterator(); 243 while (it.hasNext()) { 244 System.err.println(" " + ((Function)(it.next())).name); 245 } 246 } 247 } 248 output(PrintWriter out)249 void output(PrintWriter out) { 250 Iterator it = top.iterator(); 251 while (it.hasNext()) { 252 out.println(it.next()); 253 } 254 it = functions.iterator(); 255 while (it.hasNext()) { 256 Function stubFunc = (Function)(it.next()); 257 stubFunc.output(out); 258 } 259 } 260 } 261