2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.tool;
20 import gov.nasa.jpf.vm.Types;
22 import java.io.PrintWriter;
23 import java.lang.reflect.Method;
24 import java.lang.reflect.Modifier;
25 import java.util.ArrayList;
29 * tool to automatically generate the framework of a native peer MJI class,
30 * given it's model class. GenPeer collects all the native methods from the
31 * model class, and creates the corresponding native peer methods
33 public class GenPeer {
34 static final String SYS_PKG = "gov.nasa.jpf.vm";
35 static final String MJI_ENV = "gov.nasa.jpf.vm.MJIEnv";
36 static final String NATIVEPEER = "gov.nasa.jpf.vm.NativePeer";
37 static final String MJI_ANNOTATION = "gov.nasa.jpf.annotation.MJI";
38 static final String INDENT = " ";
39 static final String SUPERCLASS = "NativePeer";
40 static final String MJI_ANN = "@MJI";
41 static final String METHOD_PREFIX = "public";
42 static final String ENV_ARG = "MJIEnv env";
43 static final String OBJ_ARG = "int objRef";
44 static final String CLS_ARG = "int clsObjRef";
45 static final String REF_TYPE = "int";
46 static final String NULL = "MJIEnv.NULL";
48 static String clsName;
52 static boolean isSystemPkg;
53 static boolean allMethods;
54 static boolean mangleNames;
55 static boolean clinit;
57 public static void main (String[] args) {
58 if ((args.length == 0) || !readOptions(args)) {
64 PrintWriter pw = new PrintWriter(System.out, true);
65 Class<?> cls = getClass(clsName);
68 printNativePeer(cls, pw);
72 static Class<?> getClass (String cname) {
73 Class<?> clazz = null;
76 clazz = Class.forName(cname);
77 } catch (ClassNotFoundException cnfx) {
78 System.err.println("target class not found: " + cname);
79 } catch (Throwable x) {
86 static boolean isMJICandidate (Method m) {
92 String name = m.getName();
94 for (int i = 0; i < mths.length; i++) {
95 if (name.equals(mths[i])) {
100 if ((m.getModifiers() & Modifier.NATIVE) != 0) {
108 static void getMangledName (Method m) {
109 StringBuilder sb = new StringBuilder(50);
111 sb.append(m.getName());
115 static boolean isPrimitiveType (String t) {
116 return ("int".equals(t) || "long".equals(t) || "boolean".equals(t) ||
117 "void".equals(t) || // not really, but useful for returnTypes
118 "byte".equals(t) || "char".equals(t) || "short".equals(t) ||
119 "float".equals(t) || "double".equals(t));
122 static void printClinit (PrintWriter pw) {
124 pw.print(METHOD_PREFIX);
125 pw.print(" void $clinit (");
134 static void printFooter (Class<?> cls, PrintWriter pw) {
138 static void printHeader (Class<?> cls, PrintWriter pw) {
140 pw.print("package ");
150 pw.print(NATIVEPEER);
153 pw.print(MJI_ANNOTATION);
157 String cname = cls.getName().replace('.', '_');
159 pw.print("public class ");
162 pw.print(" extends ");
163 pw.print(SUPERCLASS);
167 static void printMethodBody (String rt, String t, PrintWriter pw) {
168 if (!"void".equals(rt)) {
173 if ((rt == REF_TYPE) && (rt != t)) {
182 pw.print("return r");
192 pw.println("return v;");
197 static void printMethodName (Method m, PrintWriter pw) {
201 name = Types.getJNIMangledMethodName(m);
209 static void printMJIAnnotation(PrintWriter pw) {
214 static void printMethodStub (String condPrefix, Method m, PrintWriter pw) {
218 printMJIAnnotation(pw);
221 pw.print(METHOD_PREFIX);
224 if (condPrefix == null) {
225 t = rt = stripType(m.getReturnType().getName());
227 if (!isPrimitiveType(rt)) {
238 if (condPrefix != null) {
239 pw.print(condPrefix);
242 printMethodName(m, pw);
246 printTargetArgs(m, pw);
250 if (condPrefix == null) {
251 printMethodBody(rt, stripType(null, t), pw);
255 pw.println("return true;");
262 static void printNativePeer (Class<?> cls, PrintWriter pw) {
263 Method[] mths = cls.getDeclaredMethods();
265 printHeader(cls, pw);
271 for (int i = 0; i < mths.length; i++) {
274 if (isMJICandidate(m)) {
276 printMethodStub(null, m, pw);
280 printFooter(cls, pw);
283 static void printStdArgs (Method m, PrintWriter pw) {
287 if ((m.getModifiers() & Modifier.STATIC) != 0) {
294 static void printTargetArgs (Method m, PrintWriter pw) {
295 Class<?>[] pt = m.getParameterTypes();
297 for (int i = 0; i < pt.length; i++) {
298 String t = stripType(pt[i].getName());
299 boolean isPrim = isPrimitiveType(t);
310 pw.print(stripType(null, t));
316 static String[] readNames (String[] args, int i) {
317 ArrayList<String> a = null;
319 for (; (i < args.length) && (args[i].charAt(0) != '-'); i++) {
321 a = new ArrayList<String>();
328 String[] names = new String[a.size()];
337 static boolean readOptions (String[] args) {
338 for (int i = 0; i < args.length; i++) {
339 String arg = args[i];
341 if ("-s".equals(arg)) {
343 } else if ("-m".equals(arg)) {
345 } else if ("-a".equals(arg)) {
347 } else if ("-ci".equals(arg)) {
349 } else if (arg.charAt(0) != '-') {
351 if (clsName == null) {
354 mths = readNames(args, i);
358 System.err.println("unknown option: " + arg);
365 return (clsName != null);
368 static void showUsage () {
370 "usage: 'GenPeer [<option>..] <className> [<method>..]'");
371 System.out.println("options: -s : system peer class (gov.nasa.jpf.vm)");
372 System.out.println(" -ci : create <clinit> MJI method");
373 System.out.println(" -m : create mangled method names");
374 System.out.println(" -a : create MJI methods for all target class methods");
377 static String stripType (String s) {
378 return stripType("java.lang", s);
381 static String stripType (String prefix, String s) {
382 int i = s.lastIndexOf('.') + 1;
383 int l = s.length() - 1;
385 if (s.charAt(l) == ';') {
386 s = s.substring(0, l);
389 if (prefix == null) {
393 return s.substring(i);
396 if (s.startsWith(prefix) && (prefix.length() + 1 == i)) {
397 return s.substring(i);