blob: 74f920369373c0973212faa082baed0261c35ec2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.tools.internal;
import java.lang.reflect.*;
import java.util.HashSet;
import java.util.Iterator;
public class StructsGenerator extends JNIGenerator {
public void generate(Class clazz) {
generateHeaderFile(clazz);
generateSourceFile(clazz);
}
public void generateExcludes(Class[] classes) {
HashSet excludes = new HashSet();
for (int i = 0; i < classes.length; i++) {
Class clazz = classes[i];
ClassData classData = getMetaData().getMetaData(clazz);
String exclude = classData.getExclude();
if (exclude.length() != 0) {
excludes.add(exclude);
}
}
for (Iterator iter = excludes.iterator(); iter.hasNext();) {
String exclude = (String)iter.next();
output(exclude);
outputDelimiter();
for (int i = 0; i < classes.length; i++) {
Class clazz = classes[i];
ClassData classData = getMetaData().getMetaData(clazz);
String classExclude = classData.getExclude();
if (exclude.equals(classExclude)) {
output("#define NO_");
output(getClassName(clazz));
outputDelimiter();
}
}
output("#endif");
outputDelimiter();
outputDelimiter();
}
}
public void generateHeaderFile(Class clazz) {
generateSourceStart(clazz);
generatePrototypes(clazz);
generateBlankMacros(clazz);
generateSourceEnd(clazz);
outputDelimiter();
}
public void generateHeaderFile(Class[] classes) {
if (classes.length == 0) return;
sort(classes);
generateMetaData("swt_copyright");
generateMetaData("swt_includes");
generateExcludes(classes);
for (int i = 0; i < classes.length; i++) {
Class clazz = classes[i];
ClassData classData = getMetaData().getMetaData(clazz);
if (classData.getFlag("no_gen")) continue;
generateHeaderFile(clazz);
}
}
public void generateSourceFile(Class clazz) {
generateSourceStart(clazz);
generateFIDsStructure(clazz);
outputDelimiter();
generateGlobalVar(clazz);
outputDelimiter();
generateFunctions(clazz);
generateSourceEnd(clazz);
outputDelimiter();
}
public void generateSourceFile(Class[] classes) {
if (classes.length == 0) return;
sort(classes);
generateMetaData("swt_copyright");
generateMetaData("swt_includes");
for (int i = 0; i < classes.length; i++) {
Class clazz = classes[i];
ClassData classData = getMetaData().getMetaData(clazz);
if (classData.getFlag("no_gen")) continue;
generateSourceFile(clazz);
}
}
void generateSourceStart(Class clazz) {
String clazzName = getClassName(clazz);
output("#ifndef NO_");
output(clazzName);
outputDelimiter();
}
void generateSourceEnd(Class clazz) {
output("#endif");
outputDelimiter();
}
void generateGlobalVar(Class clazz) {
String clazzName = getClassName(clazz);
output(clazzName);
output("_FID_CACHE ");
output(clazzName);
output("Fc;");
outputDelimiter();
}
void generateBlankMacros(Class clazz) {
String clazzName = getClassName(clazz);
output("#else");
outputDelimiter();
output("#define cache");
output(clazzName);
output("Fields(a,b)");
outputDelimiter();
output("#define get");
output(clazzName);
output("Fields(a,b,c) NULL");
outputDelimiter();
output("#define set");
output(clazzName);
output("Fields(a,b,c)");
outputDelimiter();
output("#define ");
output(clazzName);
output("_sizeof() 0");
outputDelimiter();
}
void generatePrototypes(Class clazz) {
String clazzName = getClassName(clazz);
output("void cache");
output(clazzName);
output("Fields(JNIEnv *env, jobject lpObject);");
outputDelimiter();
output(clazzName);
output(" *get");
output(clazzName);
output("Fields(JNIEnv *env, jobject lpObject, ");
output(clazzName);
output(" *lpStruct);");
outputDelimiter();
output("void set");
output(clazzName);
output("Fields(JNIEnv *env, jobject lpObject, ");
output(clazzName);
output(" *lpStruct);");
outputDelimiter();
output("#define ");
output(clazzName);
output("_sizeof() sizeof(");
output(clazzName);
output(")");
outputDelimiter();
}
void generateFIDsStructure(Class clazz) {
String clazzName = getClassName(clazz);
output("typedef struct ");
output(clazzName);
output("_FID_CACHE {");
outputDelimiter();
output("\tint cached;");
outputDelimiter();
output("\tjclass clazz;");
outputDelimiter();
output("\tjfieldID ");
Field[] fields = clazz.getDeclaredFields();
boolean first = true;
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (ignoreField(field)) continue;
if (!first) output(", ");
output(field.getName());
first = false;
}
output(";");
outputDelimiter();
output("} ");
output(clazzName);
output("_FID_CACHE;");
outputDelimiter();
}
void generateCacheFunction(Class clazz) {
String clazzName = getClassName(clazz);
output("void cache");
output(clazzName);
output("Fields(JNIEnv *env, jobject lpObject)");
outputDelimiter();
output("{");
outputDelimiter();
output("\tif (");
output(clazzName);
output("Fc.cached) return;");
outputDelimiter();
Class superclazz = clazz.getSuperclass();
if (superclazz != Object.class) {
String superName = getClassName(superclazz);
output("\tcache");
output(superName);
output("Fields(env, lpObject);");
outputDelimiter();
}
output("\t");
output(clazzName);
output("Fc.clazz = (*env)->GetObjectClass(env, lpObject);");
outputDelimiter();
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (ignoreField(field)) continue;
output("\t");
output(clazzName);
output("Fc.");
output(field.getName());
output(" = (*env)->GetFieldID(env, ");
output(clazzName);
output("Fc.clazz, \"");
output(field.getName());
output("\", \"");
output(getTypeSignature(field));
output("\");");
outputDelimiter();
}
output("\t");
output(clazzName);
output("Fc.cached = 1;");
outputDelimiter();
output("}");
outputDelimiter();
}
void generateGetFields(Class clazz) {
Class superclazz = clazz.getSuperclass();
String clazzName = getClassName(clazz);
String superName = getClassName(superclazz);
if (superclazz != Object.class) {
/* Windows exception - cannot call get/set function of super class in this case */
if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) {
output("\tget");
output(superName);
output("Fields(env, lpObject, (");
output(superName);
output(" *)lpStruct);");
outputDelimiter();
} else {
generateGetFields(superclazz);
}
}
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (ignoreField(field)) continue;
FieldData fieldData = getMetaData().getMetaData(field);
String exclude = fieldData.getExclude();
if (exclude.length() != 0) {
output(exclude);
outputDelimiter();
}
boolean noWinCE = fieldData.getFlag("no_wince");
if (noWinCE) {
output("#ifndef _WIN32_WCE");
outputDelimiter();
}
Class type = field.getType();
String typeName = getClassName(type);
String accessor = fieldData.getAccessor();
if (accessor == null || accessor.length() == 0) accessor = field.getName();
if (type.isPrimitive()) {
output("\tlpStruct->");
output(accessor);
output(" = ");
output(fieldData.getCast());
output("(*env)->Get");
output(getTypeSignature1(field));
output("Field(env, lpObject, ");
output(getClassName(field.getDeclaringClass()));
output("Fc.");
output(field.getName());
output(");");
} else if (type.isArray()) {
Class componentType = type.getComponentType();
if (componentType.isPrimitive()) {
output("\t{");
outputDelimiter();
output("\t");
output(getTypeSignature2(field));
output(" lpObject1 = (*env)->GetObjectField(env, lpObject, ");
output(getClassName(field.getDeclaringClass()));
output("Fc.");
output(field.getName());
output(");");
outputDelimiter();
output("\t(*env)->Get");
output(getTypeSignature1(componentType));
output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->");
output(accessor);
output(")");
int byteCount = getByteCount(componentType);
if (byteCount > 1) {
output(" / ");
output(String.valueOf(byteCount));
}
output(", (void *)lpStruct->");
output(accessor);
output(");");
outputDelimiter();
output("\t}");
} else {
throw new Error("not done");
}
} else {
output("\t{");
outputDelimiter();
output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, ");
output(getClassName(field.getDeclaringClass()));
output("Fc.");
output(field.getName());
output(");");
outputDelimiter();
output("\tget");
output(typeName);
output("Fields(env, lpObject1, &lpStruct->");
output(accessor);
output(");");
outputDelimiter();
output("\t}");
}
outputDelimiter();
if (noWinCE) {
output("#endif");
outputDelimiter();
}
if (exclude.length() != 0) {
output("#endif");
outputDelimiter();
}
}
}
void generateGetFunction(Class clazz) {
String clazzName = getClassName(clazz);
output(clazzName);
output(" *get");
output(clazzName);
output("Fields(JNIEnv *env, jobject lpObject, ");
output(clazzName);
output(" *lpStruct)");
outputDelimiter();
output("{");
outputDelimiter();
output("\tif (!");
output(clazzName);
output("Fc.cached) cache");
output(clazzName);
output("Fields(env, lpObject);");
outputDelimiter();
generateGetFields(clazz);
output("\treturn lpStruct;");
outputDelimiter();
output("}");
outputDelimiter();
}
void generateSetFields(Class clazz) {
Class superclazz = clazz.getSuperclass();
String clazzName = getClassName(clazz);
String superName = getClassName(superclazz);
if (superclazz != Object.class) {
/* Windows exception - cannot call get/set function of super class in this case */
if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) {
output("\tset");
output(superName);
output("Fields(env, lpObject, (");
output(superName);
output(" *)lpStruct);");
outputDelimiter();
} else {
generateSetFields(superclazz);
}
}
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (ignoreField(field)) continue;
FieldData fieldData = getMetaData().getMetaData(field);
String exclude = fieldData.getExclude();
if (exclude.length() != 0) {
output(exclude);
outputDelimiter();
}
boolean noWinCE = fieldData.getFlag("no_wince");
if (noWinCE) {
output("#ifndef _WIN32_WCE");
outputDelimiter();
}
Class type = field.getType();
String typeName = getClassName(type);
String accessor = fieldData.getAccessor();
if (accessor == null || accessor.length() == 0) accessor = field.getName();
if (type.isPrimitive()) {
output("\t(*env)->Set");
output(getTypeSignature1(field));
output("Field(env, lpObject, ");
output(getClassName(field.getDeclaringClass()));
output("Fc.");
output(field.getName());
output(", (");
output(getTypeSignature2(field));
output(")lpStruct->");
output(accessor);
output(");");
} else if (type.isArray()) {
Class componentType = type.getComponentType();
if (componentType.isPrimitive()) {
output("\t{");
outputDelimiter();
output("\t");
output(getTypeSignature2(field));
output(" lpObject1 = (*env)->GetObjectField(env, lpObject, ");
output(getClassName(field.getDeclaringClass()));
output("Fc.");
output(field.getName());
output(");");
outputDelimiter();
output("\t(*env)->Set");
output(getTypeSignature1(componentType));
output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->");
output(accessor);
output(")");
int byteCount = getByteCount(componentType);
if (byteCount > 1) {
output(" / ");
output(String.valueOf(byteCount));
}
output(", (void *)lpStruct->");
output(accessor);
output(");");
outputDelimiter();
output("\t}");
} else {
throw new Error("not done");
}
} else {
output("\t{");
outputDelimiter();
output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, ");
output(getClassName(field.getDeclaringClass()));
output("Fc.");
output(field.getName());
output(");");
outputDelimiter();
output("\tset");
output(typeName);
output("Fields(env, lpObject1, &lpStruct->");
output(accessor);
output(");");
outputDelimiter();
output("\t}");
}
outputDelimiter();
if (noWinCE) {
output("#endif");
outputDelimiter();
}
if (exclude.length() != 0) {
output("#endif");
outputDelimiter();
}
}
}
void generateSetFunction(Class clazz) {
String clazzName = getClassName(clazz);
output("void set");
output(clazzName);
output("Fields(JNIEnv *env, jobject lpObject, ");
output(clazzName);
output(" *lpStruct)");
outputDelimiter();
output("{");
outputDelimiter();
output("\tif (!");
output(clazzName);
output("Fc.cached) cache");
output(clazzName);
output("Fields(env, lpObject);");
outputDelimiter();
generateSetFields(clazz);
output("}");
outputDelimiter();
}
void generateFunctions(Class clazz) {
generateCacheFunction(clazz);
outputDelimiter();
generateGetFunction(clazz);
outputDelimiter();
generateSetFunction(clazz);
}
boolean ignoreField(Field field) {
int mods = field.getModifiers();
return
((mods & Modifier.PUBLIC) == 0) ||
((mods & Modifier.FINAL) != 0) ||
((mods & Modifier.STATIC) != 0);
}
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Usage: java StructsGenerator <className1> <className2>");
return;
}
try {
StructsGenerator gen = new StructsGenerator();
for (int i = 0; i < args.length; i++) {
String clazzName = args[i];
Class clazz = Class.forName(clazzName);
gen.generate(clazz);
}
} catch (Exception e) {
System.out.println("Problem");
e.printStackTrace(System.out);
}
}
}