001: //
002: // Copyright (C) 2005 United States Government as represented by the
003: // Administrator of the National Aeronautics and Space Administration
004: // (NASA). All Rights Reserved.
005: //
006: // This software is distributed under the NASA Open Source Agreement
007: // (NOSA), version 1.3. The NOSA has been approved by the Open Source
008: // Initiative. See the file NOSA-1.3-JPF at the top of the distribution
009: // directory tree for the complete NOSA document.
010: //
011: // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
012: // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
013: // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
014: // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
015: // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
016: // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
017: // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
018: //
019: package gov.nasa.jpf.tools;
020:
021: import gov.nasa.jpf.jvm.Types;
022:
023: import java.io.PrintWriter;
024:
025: import java.lang.reflect.*;
026:
027: import java.util.ArrayList;
028:
029: /**
030: * tool to automatically generate the framework of a native peer MJI class,
031: * given it's model class. GenPeer collects all the native methods from the
032: * model class, and creates the corresponding native peer methods
033: */
034: public class GenPeer {
035: static final String SYS_PKG = "gov.nasa.jpf.jvm";
036: static final String MJI_ENV = "gov.nasa.jpf.jvm.MJIEnv";
037: static final String INDENT = " ";
038: static final String METHOD_PREFIX = "public static";
039: static final String ENV_ARG = "MJIEnv env";
040: static final String OBJ_ARG = "int robj";
041: static final String CLS_ARG = "int rcls";
042: static final String REF_TYPE = "int";
043: static final String NULL = "MJIEnv.NULL";
044: static final String EXEC_COND = "$isExecutable_";
045: static final String DETERM_COND = "$isDeterministic_";
046: static String clsName;
047: static String[] mths;
048:
049: // our options
050: static boolean isSystemPkg;
051: static boolean allMethods;
052: static boolean mangleNames;
053: static boolean clinit;
054: static boolean execCond;
055: static boolean determCond;
056:
057: public static void main(String[] args) {
058: if ((args.length == 0) || !readOptions(args)) {
059: showUsage();
060:
061: return;
062: }
063:
064: PrintWriter pw = new PrintWriter(System.out, true);
065: Class cls = getClass(clsName);
066:
067: if (cls != null) {
068: printNativePeer(cls, pw);
069: }
070: }
071:
072: static Class getClass(String cname) {
073: Class clazz = null;
074:
075: try {
076: clazz = Class.forName(cname);
077: } catch (ClassNotFoundException cnfx) {
078: System.err.println("target class not found: " + cname);
079: } catch (Throwable x) {
080: x.printStackTrace();
081: }
082:
083: return clazz;
084: }
085:
086: static boolean isMJICandidate(Method m) {
087: if (allMethods) {
088: return true;
089: }
090:
091: if (mths != null) {
092: String name = m.getName();
093:
094: for (int i = 0; i < mths.length; i++) {
095: if (name.equals(mths[i])) {
096: return true;
097: }
098: }
099: } else {
100: if ((m.getModifiers() & Modifier.NATIVE) != 0) {
101: return true;
102: }
103: }
104:
105: return false;
106: }
107:
108: static void getMangledName(Method m) {
109: StringBuffer sb = new StringBuffer(50);
110:
111: sb.append(m.getName());
112: sb.append("__");
113: }
114:
115: static boolean isPrimitiveType(String t) {
116: return ("int".equals(t) || "long".equals(t)
117: || "boolean".equals(t) || "void".equals(t)
118: || // not really, but useful for returnTypes
119: "byte".equals(t) || "char".equals(t)
120: || "short".equals(t) || "float".equals(t) || "double"
121: .equals(t));
122: }
123:
124: static void printClinit(PrintWriter pw) {
125: pw.print(INDENT);
126: pw.print(METHOD_PREFIX);
127: pw.print(" void $clinit (");
128: pw.print(ENV_ARG);
129: pw.print(", ");
130: pw.print(CLS_ARG);
131: pw.println(") {");
132: pw.print(INDENT);
133: pw.println("}");
134: }
135:
136: static void printFooter(Class cls, PrintWriter pw) {
137: pw.println("}");
138: }
139:
140: static void printHeader(Class cls, PrintWriter pw) {
141: if (isSystemPkg) {
142: pw.print("package ");
143: pw.print(SYS_PKG);
144: pw.println(';');
145: pw.println();
146:
147: pw.print("import ");
148: pw.print(MJI_ENV);
149: pw.println(";");
150: pw.println();
151: }
152:
153: String cname = cls.getName().replace('.', '_');
154:
155: pw.print("class ");
156: pw.print("JPF_");
157: pw.print(cname);
158: pw.println(" {");
159: }
160:
161: static void printMethodBody(String rt, String t, PrintWriter pw) {
162: if (!"void".equals(rt)) {
163: pw.print(INDENT);
164: pw.print(INDENT);
165: pw.print(rt);
166:
167: if ((rt == REF_TYPE) && (rt != t)) {
168: pw.print(" r");
169: pw.print(t);
170: pw.print(" = ");
171: pw.print(NULL);
172: pw.println(";");
173:
174: pw.print(INDENT);
175: pw.print(INDENT);
176: pw.print("return r");
177: pw.print(t);
178: pw.println(";");
179: } else {
180: pw.print(" v = (");
181: pw.print(rt);
182: pw.println(")0;");
183:
184: pw.print(INDENT);
185: pw.print(INDENT);
186: pw.println("return v;");
187: }
188: }
189: }
190:
191: static void printMethodName(Method m, PrintWriter pw) {
192: String name = null;
193:
194: if (mangleNames) {
195: name = Types.getJNIMangledMethodName(m);
196: } else {
197: name = m.getName();
198: }
199:
200: pw.print(name);
201: }
202:
203: static void printMethodStub(String condPrefix, Method m,
204: PrintWriter pw) {
205: String t = null;
206: String rt;
207:
208: pw.print(INDENT);
209: pw.print(METHOD_PREFIX);
210: pw.print(' ');
211:
212: if (condPrefix == null) {
213: t = rt = stripType(m.getReturnType().getName());
214:
215: if (!isPrimitiveType(rt)) {
216: rt = REF_TYPE;
217: }
218: } else {
219: rt = "boolean";
220: }
221:
222: pw.print(rt);
223:
224: pw.print(' ');
225:
226: if (condPrefix != null) {
227: pw.print(condPrefix);
228: }
229:
230: printMethodName(m, pw);
231: pw.print(" (");
232:
233: printStdArgs(m, pw);
234: printTargetArgs(m, pw);
235:
236: pw.println(") {");
237:
238: if (condPrefix == null) {
239: printMethodBody(rt, stripType(null, t), pw);
240: } else {
241: pw.print(INDENT);
242: pw.print(INDENT);
243: pw.println("return true;");
244: }
245:
246: pw.print(INDENT);
247: pw.println('}');
248: }
249:
250: static void printNativePeer(Class cls, PrintWriter pw) {
251: Method[] mths = cls.getDeclaredMethods();
252:
253: printHeader(cls, pw);
254:
255: if (clinit) {
256: printClinit(pw);
257: }
258:
259: for (int i = 0; i < mths.length; i++) {
260: Method m = mths[i];
261:
262: if (isMJICandidate(m)) {
263: if (determCond) {
264: pw.println();
265: printMethodStub(DETERM_COND, m, pw);
266: }
267:
268: if (execCond) {
269: pw.println();
270: printMethodStub(EXEC_COND, m, pw);
271: }
272:
273: pw.println();
274: printMethodStub(null, m, pw);
275: }
276: }
277:
278: printFooter(cls, pw);
279: }
280:
281: static void printStdArgs(Method m, PrintWriter pw) {
282: pw.print(ENV_ARG);
283: pw.print(", ");
284:
285: if ((m.getModifiers() & Modifier.STATIC) != 0) {
286: pw.print(CLS_ARG);
287: } else {
288: pw.print(OBJ_ARG);
289: }
290: }
291:
292: static void printTargetArgs(Method m, PrintWriter pw) {
293: Class[] pt = m.getParameterTypes();
294:
295: for (int i = 0; i < pt.length; i++) {
296: String t = stripType(pt[i].getName());
297: boolean isPrim = isPrimitiveType(t);
298:
299: pw.print(", ");
300:
301: if (isPrim) {
302: pw.print(t);
303: pw.print(" v");
304: pw.print(i);
305: } else {
306: pw.print(REF_TYPE);
307: pw.print(" r");
308: pw.print(stripType(null, t));
309: pw.print(i);
310: }
311: }
312: }
313:
314: static String[] readNames(String[] args, int i) {
315: ArrayList a = null;
316:
317: for (; (i < args.length) && (args[i].charAt(0) != '-'); i++) {
318: if (a == null) {
319: a = new ArrayList();
320: }
321:
322: a.add(args[i]);
323: }
324:
325: if (a != null) {
326: String[] names = new String[a.size()];
327: a.toArray(names);
328:
329: return names;
330: }
331:
332: return null;
333: }
334:
335: static boolean readOptions(String[] args) {
336: for (int i = 0; i < args.length; i++) {
337: String arg = args[i];
338:
339: if ("-s".equals(arg)) {
340: isSystemPkg = true;
341: } else if ("-m".equals(arg)) {
342: mangleNames = true;
343: } else if ("-a".equals(arg)) {
344: allMethods = true;
345: } else if ("-ci".equals(arg)) {
346: clinit = true;
347: } else if ("-dc".equals(arg)) {
348: determCond = true;
349: } else if ("-ec".equals(arg)) {
350: execCond = true;
351: } else if (arg.charAt(0) != '-') {
352: // rather simple
353: if (clsName == null) {
354: clsName = arg;
355: } else {
356: mths = readNames(args, i);
357: i += mths.length;
358: }
359: } else {
360: System.err.println("unknown option: " + arg);
361: showUsage();
362:
363: return false;
364: }
365: }
366:
367: return (clsName != null);
368: }
369:
370: static void showUsage() {
371: System.out
372: .println("usage: 'GenPeer [<option>..] <className> [<method>..]'");
373: System.out
374: .println("options: -s : system peer class (gov.nasa.jpf.jvm)");
375: System.out
376: .println(" -ci : create <clinit> MJI method");
377: System.out
378: .println(" -m : create mangled method names");
379: System.out
380: .println(" -a : create MJI methods for all target class methods");
381: System.out
382: .println(" -dc : create isDeterministic condition methods");
383: System.out
384: .println(" -de : create isExecutable condition methods");
385: System.out
386: .println(" -nd : mark methods as non-deterministic");
387: }
388:
389: static String stripType(String s) {
390: return stripType("java.lang", s);
391: }
392:
393: static String stripType(String prefix, String s) {
394: int i = s.lastIndexOf('.') + 1;
395: int l = s.length() - 1;
396:
397: if (s.charAt(l) == ';') {
398: s = s.substring(0, l);
399: }
400:
401: if (prefix == null) {
402: if (i == 0) {
403: return s;
404: } else {
405: return s.substring(i);
406: }
407: } else {
408: if (s.startsWith(prefix) && (prefix.length() + 1 == i)) {
409: return s.substring(i);
410: } else {
411: return s;
412: }
413: }
414: }
415: }
|