aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/build-test.xml2
-rwxr-xr-xmake/scripts/runtest.sh3
-rw-r--r--src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g330
-rw-r--r--src/java/com/jogamp/gluegen/CMethodBindingEmitter.java130
-rw-r--r--src/java/com/jogamp/gluegen/ConstantDefinition.java153
-rw-r--r--src/java/com/jogamp/gluegen/DebugEmitter.java25
-rw-r--r--src/java/com/jogamp/gluegen/FunctionEmitter.java13
-rw-r--r--src/java/com/jogamp/gluegen/GlueEmitter.java7
-rw-r--r--src/java/com/jogamp/gluegen/GlueGen.java103
-rw-r--r--src/java/com/jogamp/gluegen/JavaConfiguration.java327
-rw-r--r--src/java/com/jogamp/gluegen/JavaEmitter.java256
-rw-r--r--src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java43
-rw-r--r--src/java/com/jogamp/gluegen/JavaType.java79
-rw-r--r--src/java/com/jogamp/gluegen/Logging.java32
-rw-r--r--src/java/com/jogamp/gluegen/MethodBinding.java32
-rw-r--r--src/java/com/jogamp/gluegen/ReferencedStructs.java2
-rw-r--r--src/java/com/jogamp/gluegen/TypeConfig.java52
-rw-r--r--src/java/com/jogamp/gluegen/TypeInfo.java2
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java154
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/ArrayType.java44
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/BitType.java39
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/CompoundType.java151
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/DoubleType.java29
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/EnumType.java89
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/Field.java33
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/FloatType.java25
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java60
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/FunctionType.java42
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/IntType.java38
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/MemoryLayoutType.java4
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/PointerType.java96
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/SizeThunk.java141
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/StructType.java11
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/Type.java225
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/TypeComparator.java143
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/TypeDictionary.java35
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/UnionType.java11
-rw-r--r--src/java/com/jogamp/gluegen/cgram/types/VoidType.java20
-rw-r--r--src/java/com/jogamp/gluegen/pcpp/PCPP.java6
-rw-r--r--src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java14
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java109
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg10
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1.c46
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/generation/test1.h73
-rw-r--r--src/junit/com/jogamp/gluegen/test/junit/internals/TestType.java85
45 files changed, 2489 insertions, 835 deletions
diff --git a/make/build-test.xml b/make/build-test.xml
index f9092d0..26cbd3d 100644
--- a/make/build-test.xml
+++ b/make/build-test.xml
@@ -542,7 +542,7 @@ chmod 644 ${results}/* \${line.separator}
includeRefid="stub.includes.fileset.test"
emitter="com.jogamp.gluegen.JavaEmitter"
dumpCPP="false"
- debug="false">
+ debug="true">
<classpath refid="gluegen.classpath" />
</gluegen>
diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh
index 125c163..aa7d539 100755
--- a/make/scripts/runtest.sh
+++ b/make/scripts/runtest.sh
@@ -81,7 +81,7 @@ function onetest() {
echo
}
#
-onetest com.jogamp.common.GlueGenVersion 2>&1 | tee -a $LOG
+#onetest com.jogamp.common.GlueGenVersion 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestSystemPropsAndEnvs 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionInfo 2>&1 | tee -a $LOG
#onetest com.jogamp.common.util.TestVersionNumber 2>&1 | tee -a $LOG
@@ -127,6 +127,7 @@ onetest com.jogamp.common.GlueGenVersion 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestByteBufferOutputStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.nio.TestByteBufferCopyStream 2>&1 | tee -a $LOG
#onetest com.jogamp.common.os.TestElfReader01 $* 2>&1 | tee -a $LOG
+onetest com.jogamp.gluegen.test.junit.internals.TestType 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.PCPPTest 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter 2>&1 | tee -a $LOG
#onetest com.jogamp.gluegen.test.junit.generation.Test1p2ProcAddressEmitter 2>&1 | tee -a $LOG
diff --git a/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g b/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g
index 01f10c3..3088610 100644
--- a/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g
+++ b/src/antlr/com/jogamp/gluegen/cgram/HeaderParser.g
@@ -45,6 +45,7 @@ header {
import java.util.*;
import antlr.CommonAST;
+ import com.jogamp.gluegen.JavaConfiguration;
import com.jogamp.gluegen.cgram.types.*;
}
@@ -67,6 +68,12 @@ options {
this.debug = debug;
}
+ /** Set the configuration for this
+ HeaderParser. Must be done before parsing. */
+ public void setJavaConfiguration(JavaConfiguration cfg) {
+ this.cfg = cfg;
+ }
+
/** Set the dictionary mapping typedef names to types for this
HeaderParser. Must be done before parsing. */
public void setTypedefDictionary(TypeDictionary dict) {
@@ -105,7 +112,7 @@ options {
// the enumerates from each EnumType, and fill in the enumHash
// so that each enumerate maps to the enumType to which it
// belongs.
- throw new RuntimeException("setEnums is Unimplemented!");
+ throw new RuntimeException("setEnums is Unimplemented!");
}
/** Returns the EnumTypes this HeaderParser processed. */
@@ -125,14 +132,13 @@ options {
return functions;
}
- private CompoundType lookupInStructDictionary(String typeName,
+ private CompoundType lookupInStructDictionary(String structName,
CompoundTypeKind kind,
int cvAttrs) {
- CompoundType t = (CompoundType) structDictionary.get(typeName);
+ CompoundType t = (CompoundType) structDictionary.get(structName);
if (t == null) {
- t = CompoundType.create(null, null, kind, cvAttrs);
- t.setStructName(typeName);
- structDictionary.put(typeName, t);
+ t = CompoundType.create(structName, null, kind, cvAttrs);
+ structDictionary.put(structName, t);
}
return t;
}
@@ -153,8 +159,33 @@ options {
this.id = id;
this.type = type;
}
- String id() { return id; }
- Type type() { return type; }
+ String id() { return id; }
+ Type type() { return type; }
+ void setType(final Type t) { type = t; }
+ public String toString() { return "ParamDecl["+id+": "+type.getDebugString()+"]"; }
+ }
+ Type resolveAnonCompound(Type type) {
+ int mode = 0;
+ debugPrint("resolveAnonCompound: "+type.getDebugString());
+ if( !type.hasName() ) {
+ if( type.isCompound() ) {
+ final CompoundType ct = type.asCompound();
+ // return a copy w/ resolved name
+ type = ((CompoundType) ct.clone()).evalStructTypeName();
+ mode = 1;
+ } else if( type.isPointer() ) {
+ // non typedefed PointerType and base-elem w/o name
+ final PointerType pt = type.asPointer();
+ final Type b = pt.getBaseElementType();
+ if( b != null && b.isCompound() && !b.hasName() ) {
+ // return same w/ resolved name
+ b.asCompound().evalStructTypeName();
+ mode = 2;
+ }
+ }
+ }
+ debugPrintln(" -> "+type.getDebugString()+" - MODE "+mode);
+ return type;
}
// A box for a Type. Allows type to be passed down to be modified by recursive rules.
@@ -207,22 +238,27 @@ options {
}
}
+ private String getDebugTypeString(Type t) {
+ if(debug) {
+ return getTypeString(t);
+ } else {
+ return null;
+ }
+ }
private String getTypeString(Type t) {
StringBuilder sb = new StringBuilder();
sb.append("[");
- sb.append(t);
- sb.append(", size: ");
if(null!=t) {
- SizeThunk st = t.getSize();
- if(null!=st) {
- sb.append(st.getClass().getName());
- } else {
- sb.append("undef");
- }
+ sb.append(t.getDebugString());
+ sb.append(", opaque ").append(isOpaque(t)).append("]");
+ } else {
+ sb.append("nil]");
}
- sb.append("]");
return sb.toString();
}
+ private boolean isOpaque(final Type type) {
+ return (cfg.typeInfo(type) != null);
+ }
private void debugPrintln(String msg) {
if(debug) {
@@ -236,14 +272,13 @@ options {
}
}
- private boolean doDeclaration; // Used to only process function typedefs
- private String declId;
- private List parameters;
+ private JavaConfiguration cfg;
private TypeDictionary typedefDictionary;
private TypeDictionary structDictionary;
private List<FunctionSymbol> functions = new ArrayList<FunctionSymbol>();
// hash from name of an enumerated value to the EnumType to which it belongs
private HashMap<String, EnumType> enumHash = new HashMap<String, EnumType>();
+ private HashMap<String, EnumType> enumMap = new HashMap<String, EnumType>();
// Storage class specifiers
private static final int AUTO = 1 << 0;
@@ -259,25 +294,36 @@ options {
private static final int SIGNED = 1 << 8;
private static final int UNSIGNED = 1 << 9;
- private void initDeclaration() {
- doDeclaration = false;
- declId = null;
- }
+ private boolean isFuncDeclaration; // Used to only process function typedefs
+ private String funcDeclName;
+ private List<ParameterDeclaration> funcDeclParams;
- private void doDeclaration() {
- doDeclaration = true;
+ private void resetFuncDeclaration() {
+ isFuncDeclaration = false;
+ funcDeclName = null;
+ funcDeclParams = null;
+ }
+ private void setFuncDeclaration(final String name, final List<ParameterDeclaration> p) {
+ isFuncDeclaration = true;
+ funcDeclName = name;
+ funcDeclParams = p;
}
private void processDeclaration(Type returnType) {
- if (doDeclaration) {
- FunctionSymbol sym = new FunctionSymbol(declId, new FunctionType(null, null, returnType, 0));
- if (parameters != null) { // handle funcs w/ empty parameter lists (e.g., "foo()")
- for (Iterator iter = parameters.iterator(); iter.hasNext(); ) {
- ParameterDeclaration pd = (ParameterDeclaration) iter.next();
+ if (isFuncDeclaration) {
+ final FunctionSymbol sym = new FunctionSymbol(funcDeclName, new FunctionType(null, null, resolveAnonCompound(returnType), 0));
+ debugPrintln("Function ... "+sym.toString());
+ if (funcDeclParams != null) { // handle funcs w/ empty parameter lists (e.g., "foo()")
+ for (Iterator<ParameterDeclaration> iter = funcDeclParams.iterator(); iter.hasNext(); ) {
+ ParameterDeclaration pd = iter.next();
+ pd.setType(resolveAnonCompound(pd.type()));
+ debugPrintln(" add "+pd.toString());
sym.addArgument(pd.type(), pd.id());
}
- }
+ }
+ debugPrintln("Function Added "+sym.toString());
functions.add(sym);
+ resetFuncDeclaration();
}
}
@@ -305,8 +351,7 @@ options {
}
}
tb.setType(canonicalize(new PointerType(SizeThunk.POINTER,
- tb.type(),
- 0)));
+ tb.type(), 0, null)));
}
private int parseIntConstExpr(AST t) throws RecognitionException {
@@ -315,47 +360,49 @@ options {
/** Utility function: creates a new EnumType with the given name, or
returns an existing one if it has already been created. */
- private EnumType getEnumType(String enumTypeName) {
+ private EnumType getEnumType(String enumTypeName) {
EnumType enumType = null;
Iterator<EnumType> it = enumHash.values().iterator();
while (it.hasNext()) {
EnumType potentialMatch = it.next();
if (potentialMatch.getName().equals(enumTypeName)) {
- enumType = potentialMatch;
- break;
+ enumType = potentialMatch;
+ break;
}
}
if (enumType == null) {
- // This isn't quite correct. In theory the enum should expand to
- // the size of the largest element, so if there were a long long
- // entry the enum should expand to e.g. int64. However, using
- // "long" here (which is what used to be the case) was
- // definitely incorrect and caused problems.
+ // This isn't quite correct. In theory the enum should expand to
+ // the size of the largest element, so if there were a long long
+ // entry the enum should expand to e.g. int64. However, using
+ // "long" here (which is what used to be the case) was
+ // definitely incorrect and caused problems.
enumType = new EnumType(enumTypeName, SizeThunk.INT32);
}
return enumType;
- }
+ }
// Map used to canonicalize types. For example, we may typedef
// struct foo { ... } *pfoo; subsequent references to struct foo* should
// point to the same PointerType object that had its name set to "pfoo".
- private Map canonMap = new HashMap();
+ // Opaque canonical types are excluded.
+ private Map<Type, Type> canonMap = new HashMap<Type, Type>();
private Type canonicalize(Type t) {
Type res = (Type) canonMap.get(t);
if (res != null) {
return res;
+ } else {
+ canonMap.put(t, t);
+ return t;
}
- canonMap.put(t, t);
- return t;
}
}
declarator[TypeBox tb] returns [String s] {
- initDeclaration();
+ resetFuncDeclaration();
s = null;
- List params = null;
+ List<ParameterDeclaration> params = null;
String funcPointerName = null;
TypeBox dummyTypeBox = null;
}
@@ -374,28 +421,25 @@ declarator[TypeBox tb] returns [String s] {
RPAREN
) {
if (id != null) {
- declId = id.getText();
- parameters = params; // FIXME: Ken, why are we setting this class member here?
- doDeclaration();
+ setFuncDeclaration(id.getText(), params);
} else if ( funcPointerName != null ) {
/* TypeBox becomes function pointer in this case */
FunctionType ft = new FunctionType(null, null, tb.type(), 0);
if (params == null) {
- // If the function pointer has no declared parameters, it's a
- // void function. I'm not sure if the parameter name is
- // ever referenced anywhere when the type is VoidType, so
+ // If the function pointer has no declared parameters, it's a
+ // void function. I'm not sure if the parameter name is
+ // ever referenced anywhere when the type is VoidType, so
// just in case I'll set it to a comment string so it will
- // still compile if written out to code anywhere.
- ft.addArgument(new VoidType(0), "/*unnamed-void*/");
- } else {
- for (Iterator iter = params.iterator(); iter.hasNext(); ) {
- ParameterDeclaration pd = (ParameterDeclaration) iter.next();
- ft.addArgument(pd.type(), pd.id());
- }
+ // still compile if written out to code anywhere.
+ ft.addArgument(new VoidType(0), "/*unnamed-void*/");
+ } else {
+ for (Iterator iter = params.iterator(); iter.hasNext(); ) {
+ ParameterDeclaration pd = (ParameterDeclaration) iter.next();
+ ft.addArgument(pd.type(), pd.id());
+ }
}
tb.setType(canonicalize(new PointerType(SizeThunk.POINTER,
- ft,
- 0)));
+ ft, 0, null)));
s = funcPointerName;
}
}
@@ -422,8 +466,8 @@ declaration {
) { processDeclaration(tb.type()); }
;
-parameterTypeList returns [List l] { l = new ArrayList(); ParameterDeclaration decl = null; }
- : ( decl = parameterDeclaration { if (decl != null) l.add(decl); } ( COMMA | SEMI )? )+ ( VARARGS )?
+parameterTypeList returns [List<ParameterDeclaration> l] { l = new ArrayList<ParameterDeclaration>(); ParameterDeclaration decl = null; }
+ : ( decl = parameterDeclaration { if (decl != null) { l.add(decl); } } ( COMMA | SEMI )? )+ ( VARARGS )?
;
parameterDeclaration returns [ParameterDeclaration pd] {
@@ -533,9 +577,12 @@ typeSpecifier[int attributes] returns [Type t] {
typedefName[int cvAttrs] returns [Type t] { t = null; }
: #(NTypedefName id : ID)
{
- Type tdict = lookupInTypedefDictionary(id.getText());
- t = canonicalize(tdict.getCVVariant(cvAttrs));
- debugPrintln("Adding typedef canon : [" + id.getText() + "] -> [" + tdict + "] -> "+getTypeString(t));
+ final Type t0 = lookupInTypedefDictionary(id.getText());
+ debugPrint("Adding typedef lookup: [" + id.getText() + "] -> "+getDebugTypeString(t0));
+ final Type t1 = t0.getCVVariant(cvAttrs);
+ debugPrintln(" - cvvar -> "+getDebugTypeString(t1));
+ t = canonicalize(t1);
+ debugPrintln(" - canon -> "+getDebugTypeString(t));
}
;
@@ -549,25 +596,35 @@ unionSpecifier[int cvAttrs] returns [Type t] { t = null; }
structOrUnionBody[CompoundTypeKind kind, int cvAttrs] returns [CompoundType t] {
t = null;
+ boolean addedAny = false;
}
: ( (ID LCURLY) => id:ID LCURLY {
+ // fully declared struct, i.e. not anonymous
t = (CompoundType) canonicalize(lookupInStructDictionary(id.getText(), kind, cvAttrs));
- } ( structDeclarationList[t] )?
- RCURLY { t.setBodyParsed(); }
- | LCURLY { t = CompoundType.create(null, null, kind, cvAttrs); }
- ( structDeclarationList[t] )?
- RCURLY { t.setBodyParsed(); }
- | id2:ID { t = (CompoundType) canonicalize(lookupInStructDictionary(id2.getText(), kind, cvAttrs)); }
+ } ( addedAny = structDeclarationList[t] )?
+ RCURLY { t.setBodyParsed(addedAny); }
+ | LCURLY {
+ // anonymous declared struct
+ t = CompoundType.create(null, null, kind, cvAttrs);
+ } ( structDeclarationList[t] )?
+ RCURLY { t.setBodyParsed(false); }
+ | id2:ID {
+ // anonymous struct
+ t = (CompoundType) canonicalize(lookupInStructDictionary(id2.getText(), kind, cvAttrs));
+ }
)
;
-structDeclarationList[CompoundType t]
- : ( structDeclaration[t] )+
+structDeclarationList[CompoundType t] returns [boolean addedAny] {
+ addedAny = false;
+ boolean addedOne = false;
+}
+ : ( addedOne = structDeclaration[t] { addedAny |= addedOne; } )+
;
-structDeclaration[CompoundType containingType] {
+structDeclaration[CompoundType containingType] returns [boolean addedAny] {
+ addedAny = false;
Type t = null;
- boolean addedAny = false;
}
: t = specifierQualifierList addedAny = structDeclaratorList[containingType, t] {
if (!addedAny) {
@@ -629,13 +686,28 @@ structDeclarator[CompoundType containingType, Type t] returns [boolean addedAny]
// "enumName" *before* executing the enumList rule.
enumSpecifier [int cvAttrs] returns [Type t] {
t = null;
+ EnumType e = null;
}
: #( "enum"
- ( ( ID LCURLY )=> i:ID LCURLY enumList[(EnumType)(t = getEnumType(i.getText()))] RCURLY
- | LCURLY enumList[(EnumType)(t = getEnumType(ANONYMOUS_ENUM_NAME))] RCURLY
- | ID { t = getEnumType(i.getText()); }
- )
- )
+ ( ( ID LCURLY )=> i:ID LCURLY enumList[(EnumType)(e = getEnumType(i.getText()))] RCURLY
+ | LCURLY enumList[(EnumType)(e = getEnumType(ANONYMOUS_ENUM_NAME))] RCURLY
+ | ID { e = getEnumType(i.getText()); }
+ ) {
+ debugPrintln("Adding enum mapping: "+getDebugTypeString(e));
+ if( null != e ) {
+ final String eName = e.getName();
+ if( null != eName && !eName.equals(ANONYMOUS_ENUM_NAME) ) { // validate only non-anonymous enum
+ final EnumType dupE = enumMap.get(eName);
+ if( null != dupE && !dupE.equalSemantics(e) ) {
+ throw new RuntimeException(String.format("Duplicate enum w/ incompatible type:%n have '%s',%n this '%s'",
+ getTypeString(dupE), getTypeString(e)));
+ }
+ enumMap.put(eName, (EnumType)e.clone());
+ }
+ }
+ t = e; // return val
+ }
+ )
;
enumList[EnumType enumeration] {
@@ -648,42 +720,42 @@ enumerator[EnumType enumeration, long defaultValue] returns [long newDefaultValu
newDefaultValue = defaultValue;
}
: eName:ID ( ASSIGN eVal:expr )? {
- long value = 0;
+ final long newValue;
if (eVal != null) {
String vTxt = eVal.getAllChildrenText();
if (enumHash.containsKey(vTxt)) {
EnumType oldEnumType = enumHash.get(vTxt);
- value = oldEnumType.getEnumValue(vTxt);
+ newValue = oldEnumType.getEnumValue(vTxt);
} else {
try {
- value = Long.decode(vTxt).longValue();
+ newValue = Long.decode(vTxt).longValue();
} catch (NumberFormatException e) {
System.err.println("NumberFormatException: ID[" + eName.getText() + "], VALUE=[" + vTxt + "]");
throw e;
}
}
} else {
- value = defaultValue;
+ newValue = defaultValue;
}
- newDefaultValue = value+1;
- String eTxt = eName.getText();
- if (enumHash.containsKey(eTxt)) {
- EnumType oldEnumType = enumHash.get(eTxt);
- long oldValue = oldEnumType.getEnumValue(eTxt);
- System.err.println("WARNING: redefinition of enumerated value '" + eTxt + "';" +
- " existing definition is in enumeration '" + oldEnumType.getName() +
- "' with value " + oldValue + " and new definition is in enumeration '" +
- enumeration.getName() + "' with value " + value);
- // remove old definition
- oldEnumType.removeEnumerate(eTxt);
- }
- // insert new definition
- enumeration.addEnum(eTxt, value);
- enumHash.put(eTxt, enumeration);
- debugPrintln("ENUM [" + enumeration.getName() + "]: " + eTxt + " = " + enumeration.getEnumValue(eTxt) +
- " (new default = " + newDefaultValue + ")");
- }
+ newDefaultValue = newValue+1;
+ String eTxt = eName.getText();
+ if (enumHash.containsKey(eTxt)) {
+ EnumType oldEnumType = enumHash.get(eTxt);
+ final long oldValue = oldEnumType.getEnumValue(eTxt);
+ if( oldValue != newValue ) {
+ throw new RuntimeException(String.format("Duplicate enum value '%s.%s' w/ diff value:%n have %d,%n this %d",
+ oldEnumType.getName(), eTxt, oldValue, newValue));
+ }
+ // remove old definition
+ oldEnumType.removeEnumerate(eTxt);
+ }
+ // insert new definition
+ enumeration.addEnum(eTxt, newValue);
+ enumHash.put(eTxt, enumeration);
+ debugPrintln("ENUM [" + enumeration.getName() + "]: " + eTxt + " = " + enumeration.getEnumValue(eTxt) +
+ " (new default = " + newDefaultValue + ")");
+ }
;
initDeclList[TypeBox tb]
@@ -705,18 +777,48 @@ initDecl[TypeBox tb] {
{
if ((declName != null) && (tb != null) && tb.isTypedef()) {
Type t = tb.type();
- debugPrint("Adding typedef mapping: [" + declName + "] -> "+getTypeString(t));
+ debugPrint("Adding typedef mapping: [" + declName + "] -> "+getDebugTypeString(t));
if (!t.hasTypedefName()) {
- t.setName(declName);
- debugPrint(" - declName -> "+getTypeString(t));
+ if( t.isCompound() ) {
+ // Allow redefinition of newly defined struct, i.e. use same instance.
+ // This aliases '_a' -> 'A' for 'typedef struct _a { } A, *B;', where '*B' will become also '*A'.
+ t.setTypedefName(declName);
+ debugPrint(" - redefine -> "+getDebugTypeString(t));
+ } else {
+ // Use new typedef, using a copy to preserve canonicalized base type
+ t = (Type) t.clone();
+ t.setTypedefName(declName);
+ debugPrint(" - newdefine -> "+getDebugTypeString(t));
+ }
} else {
- // copy type to preserve declName !
- t = (Type) t.clone();
- t.setName(declName);
- debugPrint(" - copy -> "+getTypeString(t));
+ // Adds typeInfo alias w/ t's typeInfo, if exists
+ cfg.addTypeInfo(declName, t);
+ final Type alias;
+ if( t.isCompound() ) {
+ // Attempt to find a previous declared compound typedef
+ // This aliases 'D' -> 'A' for 'typedef struct _a { } A, D;'
+ alias = typedefDictionary.getEqualSemantics1(t, cfg, true);
+ } else {
+ alias = null;
+ }
+ if( null != alias ) {
+ // use previous typedef
+ t = alias;
+ debugPrint(" - alias -> "+getDebugTypeString(t));
+ } else {
+ // copy to preserve canonicalized base type
+ t = (Type) t.clone();
+ t.setTypedefName(declName);
+ debugPrint(" - copy -> "+getDebugTypeString(t));
+ }
+ }
+ final Type dupT = typedefDictionary.get(declName);
+ if( null != dupT && !dupT.equalSemantics(t) ) {
+ throw new RuntimeException(String.format("Duplicate typedef w/ incompatible type:%n have '%s',%n this '%s'",
+ getTypeString(dupT), getTypeString(t)));
}
t = canonicalize(t);
- debugPrintln(" - canon -> "+getTypeString(t));
+ debugPrintln(" - canon -> "+getDebugTypeString(t));
typedefDictionary.put(declName, t);
// Clear out PointerGroup effects in case another typedef variant follows
tb.reset();
@@ -731,7 +833,7 @@ pointerGroup[TypeBox tb] { int x = 0; int y = 0; }
if (tb != null) {
tb.setType(canonicalize(new PointerType(SizeThunk.POINTER,
tb.type(),
- attrs2CVAttrs(x))));
+ attrs2CVAttrs(x), null)));
}
}
)+ )
diff --git a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
index 93a1ecc..734f536 100644
--- a/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/CMethodBindingEmitter.java
@@ -51,13 +51,14 @@ import java.util.logging.Logger;
/** Emits the C-side component of the Java<->C JNI binding. */
public class CMethodBindingEmitter extends FunctionEmitter {
- protected static final Logger LOG = Logger.getLogger(CMethodBindingEmitter.class.getPackage().getName());
protected static final CommentEmitter defaultCommentEmitter = new DefaultCommentEmitter();
protected static final String arrayResLength = "_array_res_length";
protected static final String arrayRes = "_array_res";
protected static final String arrayIdx = "_array_idx";
+ protected final Logger LOG;
+
protected MethodBinding binding;
/** Name of the package in which the corresponding Java method resides.*/
@@ -124,9 +125,11 @@ public class CMethodBindingEmitter extends FunctionEmitter {
final boolean isJavaMethodStatic,
final boolean forImplementingMethodCall,
final boolean forIndirectBufferAndArrayImplementation,
- final MachineDataInfo machDesc)
+ final MachineDataInfo machDesc,
+ final JavaConfiguration configuration)
{
- super(output, false);
+ super(output, false, configuration);
+ LOG = Logging.getLogger(CMethodBindingEmitter.class.getPackage().getName());
assert(binding != null);
assert(javaClassName != null);
@@ -152,6 +155,11 @@ public class CMethodBindingEmitter extends FunctionEmitter {
return binding.getName();
}
+ @Override
+ public FunctionSymbol getCSymbol() {
+ return binding.getCSymbol();
+ }
+
/**
* Get the expression for the capacity of the returned java.nio.Buffer.
*/
@@ -451,7 +459,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
if (!cReturnType.isVoid()) {
writer.print(" ");
// Note we must respect const/volatile for return argument
- writer.print(binding.getCSymbol().getReturnType().getName(true));
+ writer.print(binding.getCSymbol().getReturnType().getCName(true));
writer.println(" _res;");
if (javaReturnType.isNIOByteBufferArray() ||
javaReturnType.isArrayOfCompoundTypeWrappers()) {
@@ -569,7 +577,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
writer.println(" if ( NULL != " + javaArgName + " ) {");
final Type cArgType = binding.getCArgumentType(i);
- String cArgTypeName = cArgType.getName();
+ String cArgTypeName = cArgType.getCName();
final String convName = pointerConversionArgumentName(javaArgName);
@@ -654,7 +662,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
emitMalloc(
writer,
convName+"_copy",
- cArgElementType.getName(),
+ cArgElementType.getCName(),
isBaseTypeConst(cArgType),
arrayLenName,
"Could not allocate buffer for copying data in argument \\\""+javaArgName+"\\\"");
@@ -692,7 +700,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
in the method binding. */
emitGetDirectBufferAddress(writer,
"_tmpObj",
- cArgElementType.getName(),
+ cArgElementType.getCName(),
convName + "_copy[_copyIndex]",
true,
"_offsetHandle[_copyIndex]", true);
@@ -702,7 +710,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
// offset argument
emitGetDirectBufferAddress(writer,
"_tmpObj",
- cArgElementType.getName(),
+ cArgElementType.getCName(),
"("+convName + "_copy + _copyIndex)",
false /* !receivingIsPtrPtr -> linear layout -> use memcpy */,
null, true);
@@ -719,13 +727,13 @@ public class CMethodBindingEmitter extends FunctionEmitter {
emitMalloc(
writer,
convName+"_copy[_copyIndex]",
- cArgElementType2.getName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !!
+ cArgElementType2.getCName(), // assumes cArgPtrType is ptr-to-ptr-to-primitive !!
isBaseTypeConst(cArgType),
"(*env)->GetArrayLength(env, _tmpObj)",
"Could not allocate buffer during copying of data in argument \\\""+javaArgName+"\\\"");
// FIXME: copy the data (use matched Get/ReleasePrimitiveArrayCritical() calls)
if (true) {
- throw new RuntimeException("Cannot yet handle type \"" + cArgType.getName() +
+ throw new RuntimeException("Cannot yet handle type \"" + cArgType.getCName() +
"\"; need to add support for copying ptr-to-ptr-to-primitiveType subarrays");
}
@@ -804,7 +812,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
writer.println(" _tmpObj = (*env)->GetObjectArrayElement(env, " + javaArgName + ", _copyIndex);");
emitReturnDirectBufferAddress(writer,
"_tmpObj",
- cArgType.asArray().getBaseElementType().getName(),
+ cArgType.asArray().getBaseElementType().getCName(),
"("+convName + "_copy + _copyIndex)",
false /* receivingIsPtrPtr */,
null);
@@ -855,7 +863,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
writer.println(");");
} else {
if (true) throw new RuntimeException(
- "Cannot yet handle type \"" + cArgType.getName() +
+ "Cannot yet handle type \"" + cArgType.getCName() +
"\"; need to add support for cleaning up copied ptr-to-ptr-to-primitiveType subarrays");
}
writer.println(" }");
@@ -927,7 +935,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
}
}
- writer.print(cArgType.getName());
+ writer.print(cArgType.getCName());
writer.print(") ");
if (cArgType.isPointer() && javaArgType.isPrimitive()) {
writer.print("(intptr_t) ");
@@ -1020,7 +1028,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
if (returnValueCapacityExpression != null) {
returnSizeOf = returnValueCapacityExpression.format(argumentNameArray());
} else {
- returnSizeOf = "sizeof(" + cReturnType.getName() + ")";
+ returnSizeOf = "sizeof(" + cReturnType.getCName() + ")";
}
writer.println(" return JVMUtil_NewDirectByteBufferCopy(env, &_res, "+returnSizeOf+");");
} else if (javaReturnType.isNIOBuffer() || javaReturnType.isCompoundTypeWrapper()) {
@@ -1029,27 +1037,66 @@ public class CMethodBindingEmitter extends FunctionEmitter {
// See whether capacity has been specified
if (returnValueCapacityExpression != null) {
- writer.print( returnValueCapacityExpression.format( argumentNameArray() ) );
+ writer.println( returnValueCapacityExpression.format( argumentNameArray() ) + ");");
} else {
- if (cReturnType.isPointer() &&
- cReturnType.asPointer().getTargetType().isCompound()) {
- if (cReturnType.asPointer().getTargetType().getSize() == null) {
- throw new RuntimeException(
- "Error emitting code for compound return type "+
- "for function \"" + binding + "\": " +
- "Structs to be emitted should have been laid out by this point " +
- "(type " + cReturnType.asPointer().getTargetType().getName() + " / " +
- cReturnType.asPointer().getTargetType() + " was not) for "+binding
- );
+ final Type cReturnTargetType = cReturnType.isPointer() ? cReturnType.getTargetType() : null;
+ int mode = 0;
+ if ( 1 == cReturnType.pointerDepth() && null != cReturnTargetType ) {
+ if( cReturnTargetType.isCompound() ) {
+ if( !cReturnTargetType.isAnonymous() &&
+ cReturnTargetType.asCompound().getNumFields() > 0 )
+ {
+ // fully declared non-anonymous struct pointer: pass content
+ if ( cReturnTargetType.getSize() == null ) {
+ throw new RuntimeException(
+ "Error emitting code for compound return type "+
+ "for function \"" + binding + "\": " +
+ "Structs to be emitted should have been laid out by this point " +
+ "(type " + cReturnTargetType.getCName() + " / " +
+ cReturnTargetType.getDebugString() + " was not) for "+binding
+ );
+ }
+ writer.println("sizeof(" + cReturnTargetType.getCName() + ") );");
+ mode = 10;
+ } else if( cReturnTargetType.asCompound().getNumFields() == 0 ) {
+ // anonymous struct pointer: pass pointer
+ writer.println("sizeof(" + cReturnType.getCName() + ") );");
+ mode = 11;
+ }
+ }
+ if( 0 == mode ) {
+ if( cReturnTargetType.isPrimitive() ) {
+ // primitive pointer: pass primitive
+ writer.println("sizeof(" + cReturnTargetType.getCName() + ") );");
+ mode = 20;
+ } else if( cReturnTargetType.isVoid() ) {
+ // void pointer: pass pointer
+ writer.println("sizeof(" + cReturnType.getCName() + ") );");
+ mode = 21;
+ }
+ }
+ }
+ if( 0 == mode ) {
+ if( null != cfg.typeInfo(cReturnType) ) {
+ // Opaque
+ writer.println("sizeof(" + cReturnType.getCName() + ") );");
+ mode = 88;
+ } else {
+ final String wmsg = "Assumed return size of equivalent C return type";
+ writer.println("sizeof(" + cReturnType.getCName() + ") ); // WARNING: "+wmsg);
+ mode = 99;
+ LOG.warning(
+ "No capacity specified for java.nio.Buffer return " +
+ "value for function \"" + binding.getName() + "\". " + wmsg + " (sizeof(" + cReturnType.getCName() + ")): " + binding);
}
}
- writer.print("sizeof(" + cReturnType.getName() + ")");
- LOG.warning(
- "No capacity specified for java.nio.Buffer return " +
- "value for function \"" + binding.getName() + "\"" +
- " assuming size of equivalent C return type (sizeof(" + cReturnType.getName() + ")): " + binding);
+ writer.println(" /** ");
+ writer.println(" * mode: "+mode);
+ writer.println(" * cReturnType: "+cReturnType.getDebugString());
+ writer.println(" * cReturnTargetType: "+cReturnTargetType.getDebugString());
+ writer.println(" * javaReturnType: "+javaReturnType.getDebugString());
+ writer.println(" */");
}
- writer.println(");");
} else if (javaReturnType.isString()) {
writer.println(" if (NULL == _res) return NULL;");
writer.println(" return (*env)->NewStringUTF(env, _res);");
@@ -1071,7 +1118,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
pointerType = retType.asArray().getBaseElementType();
}
writer.println(" (*env)->SetObjectArrayElement(env, " + arrayRes + ", " + arrayIdx +
- ", (*env)->NewDirectByteBuffer(env, (void *)_res[" + arrayIdx + "], sizeof(" + pointerType.getName() + ")));");
+ ", (*env)->NewDirectByteBuffer(env, (void *)_res[" + arrayIdx + "], sizeof(" + pointerType.getCName() + ")));");
writer.println(" }");
writer.println(" return " + arrayRes + ";");
} else if (javaReturnType.isArray()) {
@@ -1386,33 +1433,34 @@ public class CMethodBindingEmitter extends FunctionEmitter {
// Note that we don't need to obey const/volatile for outgoing arguments
//
if (javaType.isNIOBuffer()) {
- ptrTypeString = cType.getName();
+ // primitive NIO object
+ ptrTypeString = cType.getCName();
} else if (javaType.isArray() || javaType.isArrayOfCompoundTypeWrappers()) {
needsDataCopy = javaArgTypeNeedsDataCopy(javaType);
if (javaType.isPrimitiveArray() ||
javaType.isNIOBufferArray() ||
javaType.isArrayOfCompoundTypeWrappers()) {
- ptrTypeString = cType.getName();
+ ptrTypeString = cType.getCName();
} else if (!javaType.isStringArray()) {
final Class<?> elementType = javaType.getJavaClass().getComponentType();
if (elementType.isArray()) {
final Class<?> subElementType = elementType.getComponentType();
if (subElementType.isPrimitive()) {
// type is pointer to pointer to primitive
- ptrTypeString = cType.getName();
+ ptrTypeString = cType.getCName();
} else {
// type is pointer to pointer of some type we don't support (maybe
// it's an array of pointers to structs?)
- throw new RuntimeException("Unsupported pointer type: \"" + cType.getName() + "\"");
+ throw new RuntimeException("Unsupported pointer type: \"" + cType.getCName() + "\"");
}
} else {
// type is pointer to pointer of some type we don't support (maybe
// it's an array of pointers to structs?)
- throw new RuntimeException("Unsupported pointer type: \"" + cType.getName() + "\"");
+ throw new RuntimeException("Unsupported pointer type: \"" + cType.getCName() + "\"");
}
}
} else {
- ptrTypeString = cType.getName();
+ ptrTypeString = cType.getCName();
}
writer.print(" ");
@@ -1434,7 +1482,7 @@ public class CMethodBindingEmitter extends FunctionEmitter {
String cElementTypeName = "char *";
final PointerType cPtrType = cType.asPointer();
if (cPtrType != null) {
- cElementTypeName = cPtrType.getTargetType().asPointer().getName();
+ cElementTypeName = cPtrType.getTargetType().asPointer().getCName();
}
if (isBaseTypeConst(cType)) {
writer.print("const ");
@@ -1470,9 +1518,9 @@ public class CMethodBindingEmitter extends FunctionEmitter {
final String cVariableType;
if( !cType.isPointer() && type.isCompoundTypeWrapper() ) { // FIXME: Compound call-by-value
- cVariableType = cType.getName()+" *";
+ cVariableType = cType.getCName()+" *";
} else {
- cVariableType = cType.getName();
+ cVariableType = cType.getCName();
}
emitGetDirectBufferAddress(writer,
incomingArgumentName,
diff --git a/src/java/com/jogamp/gluegen/ConstantDefinition.java b/src/java/com/jogamp/gluegen/ConstantDefinition.java
index ca67001..78d2e43 100644
--- a/src/java/com/jogamp/gluegen/ConstantDefinition.java
+++ b/src/java/com/jogamp/gluegen/ConstantDefinition.java
@@ -33,100 +33,131 @@
package com.jogamp.gluegen;
-import java.util.*;
+import com.jogamp.gluegen.cgram.types.AliasedSymbol.AliasedSymbolImpl;
+import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
/** Represents the definition of a constant which was provided either
via a #define statement or through an enum definition. */
-public class ConstantDefinition {
-
- private final String origName;
- private final HashSet<String> aliasedNames;
- private String name;
- private final String value;
+public class ConstantDefinition extends AliasedSymbolImpl implements AliasedSemanticSymbol {
+ private final boolean relaxedEqSem;
+ private final String sValue;
+ private final long iValue;
+ private final boolean hasIntValue;
private final boolean isEnum;
private final String enumName;
- private Set<String> aliases;
+ /** Covering enums */
public ConstantDefinition(final String name,
- final String value,
- final boolean isEnum,
+ final long value,
final String enumName) {
- this.origName = name;
- this.name = name;
- this.value = value;
- this.isEnum = isEnum;
+ super(name);
+ this.relaxedEqSem = TypeConfig.relaxedEqualSemanticsTest();
+ this.sValue = String.valueOf(value);
+ this.iValue = value;
+ this.hasIntValue = true;
+ this.isEnum = true;
this.enumName = enumName;
- this.aliasedNames=new HashSet<String>();
- }
-
- public boolean equals(final ConstantDefinition other) {
- return (equals(name, other.name) &&
- equals(value, other.value) &&
- equals(enumName, other.enumName));
}
- private boolean equals(final String s1, final String s2) {
- if (s1 == null || s2 == null) {
- if (s1 == null && s2 == null) {
- return true;
+ /** Covering defines */
+ public ConstantDefinition(final String name,
+ final String value) {
+ super(name);
+ this.relaxedEqSem = TypeConfig.relaxedEqualSemanticsTest();
+ this.sValue = value;
+ {
+ // Attempt to parse define string as number
+ long v;
+ boolean b;
+ try {
+ v = Long.decode(value).longValue();
+ b = true;
+ } catch (final NumberFormatException e) {
+ v = 0;
+ b = false;
}
- return false;
+ this.iValue = v;
+ this.hasIntValue = b;
}
-
- return s1.equals(s2);
+ this.isEnum = false;
+ this.enumName = null;
}
+ /**
+ * Hash by its given {@link #getName() name}.
+ */
@Override
- public int hashCode() {
- return name.hashCode();
- }
-
- /** Supports renaming in Java binding. */
- public void rename(final String name) {
- if(null!=name) {
- this.name = name;
- aliasedNames.add(origName);
- }
+ public final int hashCode() {
+ return getName().hashCode();
}
- public void addAliasedName(final String name) {
- aliasedNames.add(name);
- }
- public Collection<String> getAliasedNames() {
- return aliasedNames;
+ /**
+ * Equality test by its given {@link #getName() name}.
+ */
+ @Override
+ public final boolean equals(final Object arg) {
+ if (arg == this) {
+ return true;
+ } else if ( !(arg instanceof ConstantDefinition) ) {
+ return false;
+ } else {
+ final ConstantDefinition t = (ConstantDefinition)arg;
+ return equals(getName(), t.getName());
+ }
}
- public String getOrigName() {
- return origName;
+ @Override
+ public final int hashCodeSemantics() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + ( null != getName() ? getName().hashCode() : 0 );
+ hash = ((hash << 5) - hash) + ( null != sValue ? sValue.hashCode() : 0 );
+ return ((hash << 5) - hash) + ( null != enumName ? enumName.hashCode() : 0 );
}
- public String getName() {
- return name;
+ @Override
+ public final boolean equalSemantics(final SemanticEqualityOp arg) {
+ if (arg == this) {
+ return true;
+ } else if ( !(arg instanceof ConstantDefinition) ) {
+ return false;
+ } else {
+ final ConstantDefinition t = (ConstantDefinition) arg;
+ if( !equals(getName(), t.getName()) ||
+ !equals(enumName, t.enumName) ) {
+ return false;
+ }
+ if( hasIntValue ) {
+ return iValue == t.iValue;
+ } else {
+ // define's string value may be semantical equal .. but formatted differently!
+ return relaxedEqSem || equals(sValue, t.sValue);
+ }
+ }
}
- public String getValue() { return value; }
+ public String getValue() { return sValue; }
/** Returns null if this definition was not part of an
enumeration, or if the enum was anonymous. */
public String getEnumName() { return enumName; }
public boolean isEnum() { return isEnum; }
- public Set<String> getAliases() {
- return aliases;
+ @Override
+ public String toString() {
+ return "ConstantDefinition [name " + getName()
+ + ", value " + sValue + " (isInt " + hasIntValue
+ + "), enumName " + enumName + ", isEnum " + isEnum + "]";
}
- public void addAlias(final String alias) {
- if (aliases == null) {
- aliases = new LinkedHashSet<String>();
+ private static boolean equals(final String s1, final String s2) {
+ if (s1 == null || s2 == null) {
+ if (s1 == null && s2 == null) {
+ return true;
+ }
+ return false;
}
- aliases.add(alias);
- }
- @Override
- public String toString() {
- return "ConstantDefinition [name " + name + " origName " + origName + " value " + value
- + " aliasedNames " + aliasedNames + " aliases " + aliases
- + " enumName " + enumName + " isEnum " + isEnum + "]";
+ return s1.equals(s2);
}
-
}
diff --git a/src/java/com/jogamp/gluegen/DebugEmitter.java b/src/java/com/jogamp/gluegen/DebugEmitter.java
index 6381c8c..582a1d7 100644
--- a/src/java/com/jogamp/gluegen/DebugEmitter.java
+++ b/src/java/com/jogamp/gluegen/DebugEmitter.java
@@ -39,6 +39,7 @@
package com.jogamp.gluegen;
+import java.io.IOException;
import java.util.*;
import com.jogamp.gluegen.cgram.types.*;
@@ -46,9 +47,16 @@ import com.jogamp.gluegen.cgram.types.*;
/** Debug emitter which prints the parsing results to standard output. */
public class DebugEmitter implements GlueEmitter {
+ protected JavaConfiguration cfg;
@Override
- public void readConfigurationFile(final String filename) {}
+ public void readConfigurationFile(final String filename) throws IOException {
+ cfg = createConfig();
+ cfg.read(filename);
+ }
+
+ @Override
+ public JavaConfiguration getConfiguration() { return cfg; }
@Override
public void beginEmission(final GlueEmitterControls controls) {
@@ -110,10 +118,10 @@ public class DebugEmitter implements GlueEmitter {
}
@Override
- public void emitStruct(final CompoundType t, final String alternateName) {
+ public void emitStruct(final CompoundType t, final Type typedefType) {
String name = t.getName();
- if (name == null && alternateName != null) {
- name = alternateName;
+ if (name == null && typedefType != null) {
+ name = typedefType.getName();
}
System.out.println("Referenced type \"" + name + "\"");
@@ -121,4 +129,13 @@ public class DebugEmitter implements GlueEmitter {
@Override
public void endStructs() {}
+
+ /**
+ * Create the object that will read and store configuration information for
+ * this JavaEmitter.
+ */
+ protected JavaConfiguration createConfig() {
+ return new JavaConfiguration();
+ }
+
}
diff --git a/src/java/com/jogamp/gluegen/FunctionEmitter.java b/src/java/com/jogamp/gluegen/FunctionEmitter.java
index 8e9d306..5655e0e 100644
--- a/src/java/com/jogamp/gluegen/FunctionEmitter.java
+++ b/src/java/com/jogamp/gluegen/FunctionEmitter.java
@@ -42,6 +42,7 @@ package com.jogamp.gluegen;
import java.util.*;
import java.io.*;
+import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.cgram.types.Type;
public abstract class FunctionEmitter {
@@ -52,25 +53,29 @@ public abstract class FunctionEmitter {
private final ArrayList<EmissionModifier> modifiers;
private CommentEmitter commentEmitter = null;
private final PrintWriter defaultOutput;
+ // Only present to provide more clear comments
+ protected final JavaConfiguration cfg;
/**
* Constructs the FunctionEmitter with a CommentEmitter that emits nothing.
*/
- public FunctionEmitter(final PrintWriter defaultOutput, final boolean isInterface) {
+ public FunctionEmitter(final PrintWriter defaultOutput, final boolean isInterface, final JavaConfiguration configuration) {
assert(defaultOutput != null);
+ this.isInterfaceVal = isInterface;
this.modifiers = new ArrayList<EmissionModifier>();
this.defaultOutput = defaultOutput;
- this.isInterfaceVal = isInterface;
+ this.cfg = configuration;
}
/**
* Makes this FunctionEmitter a copy of the passed one.
*/
public FunctionEmitter(final FunctionEmitter arg) {
+ isInterfaceVal = arg.isInterfaceVal;
modifiers = new ArrayList<EmissionModifier>(arg.modifiers);
commentEmitter = arg.commentEmitter;
defaultOutput = arg.defaultOutput;
- isInterfaceVal = arg.isInterfaceVal;
+ cfg = arg.cfg;
}
public boolean isInterface() { return isInterfaceVal; }
@@ -113,6 +118,8 @@ public abstract class FunctionEmitter {
public abstract String getName();
+ public abstract FunctionSymbol getCSymbol();
+
/**
* Emit the function to the specified output (instead of the default
* output).
diff --git a/src/java/com/jogamp/gluegen/GlueEmitter.java b/src/java/com/jogamp/gluegen/GlueEmitter.java
index bb46cf5..0e8d61f 100644
--- a/src/java/com/jogamp/gluegen/GlueEmitter.java
+++ b/src/java/com/jogamp/gluegen/GlueEmitter.java
@@ -50,6 +50,7 @@ import com.jogamp.gluegen.cgram.types.*;
public interface GlueEmitter {
public void readConfigurationFile(String filename) throws Exception;
+ public JavaConfiguration getConfiguration();
/**
* Begin the emission of glue code. This might include opening files,
@@ -91,11 +92,11 @@ public interface GlueEmitter {
public void beginStructs(TypeDictionary typedefDictionary,
TypeDictionary structDictionary,
Map<Type, Type> canonMap) throws Exception;
- /** Emit glue code for the given CompoundType. alternateName is
+ /** Emit glue code for the given CompoundType. typedefType is
provided when the CompoundType (e.g. "struct foo_t") has not
been typedefed to anything but the type of "pointer to struct
foo_t" has (e.g. "typedef struct foo_t {} *Foo"); in this case
- alternateName would be set to Foo. */
- public void emitStruct(CompoundType t, String alternateName) throws Exception;
+ typedefType would be set to pointer type Foo. */
+ public void emitStruct(CompoundType t, Type typedefType) throws Exception;
public void endStructs() throws Exception;
}
diff --git a/src/java/com/jogamp/gluegen/GlueGen.java b/src/java/com/jogamp/gluegen/GlueGen.java
index e123910..6428469 100644
--- a/src/java/com/jogamp/gluegen/GlueGen.java
+++ b/src/java/com/jogamp/gluegen/GlueGen.java
@@ -43,8 +43,10 @@ import com.jogamp.common.GlueGenVersion;
import java.io.*;
import java.util.*;
+import java.util.logging.Level;
import antlr.*;
+
import com.jogamp.gluegen.cgram.*;
import com.jogamp.gluegen.cgram.types.*;
import com.jogamp.gluegen.pcpp.*;
@@ -64,8 +66,8 @@ public class GlueGen implements GlueEmitterControls {
private PCPP preprocessor;
// State for SymbolFilters
- private List<ConstantDefinition> constants;
- private List<FunctionSymbol> functions;
+ private List<ConstantDefinition> allConstants;
+ private List<FunctionSymbol> allFunctions;
private static boolean debug = false;
@@ -83,14 +85,14 @@ public class GlueGen implements GlueEmitterControls {
@Override
public void runSymbolFilter(final SymbolFilter filter) {
- filter.filterSymbols(constants, functions);
+ filter.filterSymbols(allConstants, allFunctions);
final List<ConstantDefinition> newConstants = filter.getConstants();
final List<FunctionSymbol> newFunctions = filter.getFunctions();
if (newConstants != null) {
- constants = newConstants;
+ allConstants = newConstants;
}
if (newFunctions != null) {
- functions = newFunctions;
+ allFunctions = newFunctions;
}
}
@@ -99,6 +101,25 @@ public class GlueGen implements GlueEmitterControls {
public void run(final Reader reader, final String filename, final Class<?> emitterClass, final List<String> includePaths, final List<String> cfgFiles, final String outputRootDir, final boolean copyPCPPOutput2Stderr) {
try {
+ if(debug) {
+ Logging.getLogger().setLevel(Level.ALL);
+ }
+ final GlueEmitter emit;
+ if (emitterClass == null) {
+ emit = new JavaEmitter();
+ } else {
+ try {
+ emit = (GlueEmitter) emitterClass.newInstance();
+ } catch (final Exception e) {
+ throw new RuntimeException("Exception occurred while instantiating emitter class.", e);
+ }
+ }
+
+ for (final String config : cfgFiles) {
+ emit.readConfigurationFile(config);
+ }
+ final JavaConfiguration cfg = emit.getConfiguration();
+
final File out = File.createTempFile("PCPPTemp", ".pcpp");
final FileOutputStream outStream = new FileOutputStream(out);
@@ -115,6 +136,9 @@ public class GlueGen implements GlueEmitterControls {
preprocessor.run(reader, filename);
outStream.flush();
outStream.close();
+ if(debug) {
+ System.err.println("PCPP done");
+ }
final FileInputStream inStream = new FileInputStream(out);
final DataInputStream dis = new DataInputStream(inStream);
@@ -140,6 +164,7 @@ public class GlueGen implements GlueEmitterControls {
final HeaderParser headerParser = new HeaderParser();
headerParser.setDebug(debug);
+ headerParser.setJavaConfiguration(cfg);
final TypeDictionary td = new TypeDictionary();
headerParser.setTypedefDictionary(td);
final TypeDictionary sd = new TypeDictionary();
@@ -162,21 +187,6 @@ public class GlueGen implements GlueEmitterControls {
// generate glue code: the #defines to constants, the set of
// typedefs, and the set of functions.
- GlueEmitter emit = null;
- if (emitterClass == null) {
- emit = new JavaEmitter();
- } else {
- try {
- emit = (GlueEmitter) emitterClass.newInstance();
- } catch (final Exception e) {
- throw new RuntimeException("Exception occurred while instantiating emitter class.", e);
- }
- }
-
- for (final String config : cfgFiles) {
- emit.readConfigurationFile(config);
- }
-
if (null != outputRootDir && outputRootDir.trim().length() > 0) {
if (emit instanceof JavaEmitter) {
// FIXME: hack to interfere with the *Configuration setting via commandlines
@@ -189,7 +199,7 @@ public class GlueGen implements GlueEmitterControls {
// Repackage the enum and #define statements from the parser into a common format
// so that SymbolFilters can operate upon both identically
- constants = new ArrayList<ConstantDefinition>();
+ allConstants = new ArrayList<ConstantDefinition>();
for (final EnumType enumeration : headerParser.getEnums()) {
String enumName = enumeration.getName();
if (enumName.equals("<anonymous>")) {
@@ -198,32 +208,56 @@ public class GlueGen implements GlueEmitterControls {
// iterate over all values in the enumeration
for (int i = 0; i < enumeration.getNumEnumerates(); ++i) {
final String enumElementName = enumeration.getEnumName(i);
- final String value = String.valueOf(enumeration.getEnumValue(i));
- constants.add(new ConstantDefinition(enumElementName, value, true, enumName));
+ allConstants.add(new ConstantDefinition(enumElementName, enumeration.getEnumValue(i), enumName));
}
}
for (final Object elem : lexer.getDefines()) {
final Define def = (Define) elem;
- constants.add(new ConstantDefinition(def.getName(), def.getValue(), false, null));
+ allConstants.add(new ConstantDefinition(def.getName(), def.getValue()));
}
- functions = headerParser.getParsedFunctions();
+ allFunctions = headerParser.getParsedFunctions();
- // begin emission of glue code
+ // begin emission of glue code,
+ // incl. firing up 'runSymbolFilter(SymbolFilter)' calls, which:
+ // - filters all ConstantDefinition
+ // - filters all FunctionSymbol
emit.beginEmission(this);
+ if( debug() ) {
+ int i=0;
+ System.err.println("Filtered Constants: "+allConstants.size());
+ for (final ConstantDefinition def : allConstants) {
+ if( debug() ) {
+ System.err.println("Filtered ["+i+"]: "+def.getAliasedString());
+ i++;
+ }
+ }
+ i=0;
+ System.err.println("Filtered Functions: "+allFunctions.size());
+ for (final FunctionSymbol cFunc : allFunctions) {
+ System.err.println("Filtered ["+i+"]: "+cFunc.getAliasedString());
+ i++;
+ }
+ }
+
emit.beginDefines();
final Set<String> emittedDefines = new HashSet<String>(100);
// emit java equivalent of enum { ... } statements
final StringBuilder comment = new StringBuilder();
- for (final ConstantDefinition def : constants) {
+ for (final ConstantDefinition def : allConstants) {
if (!emittedDefines.contains(def.getName())) {
emittedDefines.add(def.getName());
- final Set<String> aliases = def.getAliases();
- if (aliases != null) {
+ final Set<String> aliases = cfg.getAliasedDocNames(def);
+ if (aliases != null && aliases.size() > 0 ) {
+ int i=0;
comment.append("Alias for: <code>");
for (final String alias : aliases) {
- comment.append(" ").append(alias);
+ if(0 < i) {
+ comment.append("</code>, <code>");
+ }
+ comment.append(alias);
+ i++;
}
comment.append("</code>");
}
@@ -249,7 +283,7 @@ public class GlueGen implements GlueEmitterControls {
// Iterate through the functions finding structs that are referenced in
// the function signatures; these will be remembered for later emission
final ReferencedStructs referencedStructs = new ReferencedStructs();
- for (final FunctionSymbol sym : functions) {
+ for (final FunctionSymbol sym : allFunctions) {
// FIXME: this doesn't take into account the possibility that some of
// the functions we send to emitMethodBindings() might not actually be
// emitted (e.g., if an Ignore directive in the JavaEmitter causes it
@@ -290,19 +324,20 @@ public class GlueGen implements GlueEmitterControls {
for (final Iterator<Type> iter = referencedStructs.results(); iter.hasNext();) {
final Type t = iter.next();
if (t.isCompound()) {
+ assert t.hasTypedefName() && t.getName() == null : "ReferencedStructs incorrectly recorded compound type " + t;
emit.emitStruct(t.asCompound(), null);
} else if (t.isPointer()) {
final PointerType p = t.asPointer();
final CompoundType c = p.getTargetType().asCompound();
- assert p.hasTypedefedName() && c.getName() == null : "ReferencedStructs incorrectly recorded pointer type " + p;
- emit.emitStruct(c, p.getName());
+ assert p.hasTypedefName() && c.getName() == null : "ReferencedStructs incorrectly recorded pointer type " + p;
+ emit.emitStruct(c, p);
}
}
emit.endStructs();
// emit java and C code to interface with the native functions
emit.beginFunctions(td, sd, headerParser.getCanonMap());
- emit.emitFunctions(functions);
+ emit.emitFunctions(allFunctions);
emit.endFunctions();
// end emission of glue code
diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java
index 346920d..5eadf94 100644
--- a/src/java/com/jogamp/gluegen/JavaConfiguration.java
+++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java
@@ -46,7 +46,6 @@ import com.jogamp.gluegen.JavaEmitter.MethodAccess;
import java.io.*;
import java.lang.reflect.Array;
import java.util.*;
-import java.util.Map.Entry;
import java.util.regex.*;
import com.jogamp.gluegen.jgram.*;
@@ -54,7 +53,6 @@ import com.jogamp.gluegen.cgram.types.*;
import java.util.logging.Logger;
-import jogamp.common.os.MachineDataInfoRuntime;
import static java.util.logging.Level.*;
import static com.jogamp.gluegen.JavaEmitter.MethodAccess.*;
import static com.jogamp.gluegen.JavaEmitter.EmissionStyle.*;
@@ -73,7 +71,7 @@ public class JavaConfiguration {
private String className;
private String implClassName;
- protected static final Logger LOG = Logger.getLogger(JavaConfiguration.class.getPackage().getName());
+ protected final Logger LOG;
public static String NEWLINE = System.getProperty("line.separator");
@@ -108,6 +106,13 @@ public class JavaConfiguration {
private boolean tagNativeBinding;
/**
+ * If true, {@link TypeConfig.SemanticEqualityOp#equalSemantics(TypeConfig.SemanticEqualityOp)}
+ * will attempt to perform a relaxed semantic equality test, e.g. skip the {@code const} and {@code volatile} qualifiers.
+ * Otherwise a full semantic equality test will be performed.
+ */
+ private boolean relaxedEqualSemanticsTest;
+
+ /**
* Style of code emission. Can emit everything into one class
* (AllStatic), separate interface and implementing classes
* (InterfaceAndImpl), only the interface (InterfaceOnly), or only
@@ -180,6 +185,10 @@ public class JavaConfiguration {
private final Map<String, List<String>> javaPrologues = new HashMap<String, List<String>>();
private final Map<String, List<String>> javaEpilogues = new HashMap<String, List<String>>();
+ public JavaConfiguration() {
+ LOG = Logging.getLogger(JavaConfiguration.class.getPackage().getName());
+ }
+
/** Reads the configuration file.
@param filename path to file that should be read
*/
@@ -317,6 +326,15 @@ public class JavaConfiguration {
return tagNativeBinding;
}
+ /**
+ * Returns whether {@link TypeConfig.SemanticEqualityOp#equalSemantics(TypeConfig.SemanticEqualityOp)}
+ * shall attempt to perform a relaxed semantic equality test, e.g. skip the {@code const} and {@code volatile} qualifier
+ * - or not.
+ */
+ public boolean relaxedEqualSemanticsTest() {
+ return relaxedEqualSemanticsTest;
+ }
+
/** Returns the code emission style (constants in JavaEmitter) parsed from the configuration file. */
public EmissionStyle emissionStyle() {
return emissionStyle;
@@ -361,12 +379,12 @@ public class JavaConfiguration {
/** If this type should be considered opaque, returns the TypeInfo
describing the replacement type. Returns null if this type
should not be considered opaque. */
- public TypeInfo typeInfo(Type type, final TypeDictionary typedefDictionary) {
+ public TypeInfo typeInfo(Type type) {
// Because typedefs of pointer types can show up at any point,
// walk the pointer chain looking for a typedef name that is in
// the TypeInfo map.
if (DEBUG_TYPE_INFO)
- System.err.println("Incoming type = " + type);
+ System.err.println("Incoming type = " + type + ", " + type.getDebugString());
final int pointerDepth = type.pointerDepth();
for (int i = 0; i <= pointerDepth; i++) {
String name = type.getName();
@@ -377,12 +395,13 @@ public class JavaConfiguration {
if (name != null) {
final TypeInfo info = closestTypeInfo(name, i + type.pointerDepth());
if (info != null) {
+ final TypeInfo res = promoteTypeInfo(info, i);
if (DEBUG_TYPE_INFO) {
- System.err.println(" info.name=" + info.name() + ", name=" + name +
+ System.err.println(" [1] info.name=" + info.name() + ", name=" + name +
", info.pointerDepth=" + info.pointerDepth() +
- ", type.pointerDepth=" + type.pointerDepth());
+ ", type.pointerDepth=" + type.pointerDepth() + " -> "+res);
}
- return promoteTypeInfo(info, i);
+ return res;
}
}
@@ -392,33 +411,13 @@ public class JavaConfiguration {
if (name != null) {
final TypeInfo info = closestTypeInfo(name, i + type.pointerDepth());
if (info != null) {
+ final TypeInfo res = promoteTypeInfo(info, i);
if (DEBUG_TYPE_INFO) {
- System.err.println(" info.name=" + info.name() + ", name=" + name +
- ", info.pointerDepth=" + info.pointerDepth() +
- ", type.pointerDepth=" + type.pointerDepth());
- }
- return promoteTypeInfo(info, i);
- }
- }
- }
-
- // Try all typedef names that map to this type
- final Set<Entry<String, Type>> entrySet = typedefDictionary.entrySet();
- for (final Map.Entry<String, Type> entry : entrySet) {
- // "eq" equality is OK to use here since all types have been canonicalized
- if (entry.getValue() == type) {
- name = entry.getKey();
- if (DEBUG_TYPE_INFO) {
- System.err.println("Looking under typedef name " + name);
- }
- final TypeInfo info = closestTypeInfo(name, i + type.pointerDepth());
- if (info != null) {
- if (DEBUG_TYPE_INFO) {
- System.err.println(" info.name=" + info.name() + ", name=" + name +
+ System.err.println(" [2] info.name=" + info.name() + ", name=" + name +
", info.pointerDepth=" + info.pointerDepth() +
- ", type.pointerDepth=" + type.pointerDepth());
+ ", type.pointerDepth=" + type.pointerDepth() + " -> "+res);
}
- return promoteTypeInfo(info, i);
+ return res;
}
}
}
@@ -427,7 +426,9 @@ public class JavaConfiguration {
type = type.asPointer().getTargetType();
}
}
-
+ if (DEBUG_TYPE_INFO) {
+ System.err.println(" [X] NULL");
+ }
return null;
}
@@ -782,120 +783,184 @@ public class JavaConfiguration {
}
/**
- * Returns true if this #define, function, struct, or field within
- * a struct should be ignored during glue code generation of interfaces and implementation.
+ * Returns true if the given struct, or field within a struct
+ * should be ignored during glue code generation of interfaces and implementation.
+ * For other types, use {@link #shouldIgnoreInInterface(AliasedSymbol)}.
+ * <p>
+ * This method only considers the {@link AliasedSymbol#getName() current-name}
+ * of the given symbol, i.e. does not test the {@link #getJavaSymbolRename(String) renamed-symbol}.
+ * </p>
* <p>
* For struct fields see {@link #canonicalStructFieldSymbol(String, String)}.
* </p>
+ * <p>
+ * Implementation calls {@link #shouldIgnoreInInterface(AliasedSymbol)}
+ * </p>
+ * @param symbol the symbolic name to check for exclusion
+ *
+ */
+ public final boolean shouldIgnoreInInterface(final String symbol) {
+ return shouldIgnoreInInterface( new AliasedSymbol.NoneAliasedSymbol(symbol) );
+ }
+ /**
+ * Returns true if this aliased symbol should be ignored
+ * during glue code generation of interfaces and implementation.
+ * <p>
+ * Both, the {@link AliasedSymbol#getName() current-name}
+ * and all {@link AliasedSymbol#getAliasedNames() aliases} shall be considered.
+ * </p>
+ * <p>
+ * Implementation calls {@link #shouldIgnoreInInterface_Int(AliasedSymbol)}
+ * and overriding implementations shall ensure its being called as well!
+ * </p>
+ * @param symbol the symbolic aliased name to check for exclusion
*/
- public boolean shouldIgnoreInInterface(final String symbol) {
- if(DEBUG_IGNORES) {
- dumpIgnoresOnce();
- }
- // Simple case-1; the entire symbol (orig or renamed) is in the interface ignore table
- final String renamedSymbol = getJavaSymbolRename(symbol);
- if ( extendedIntfSymbolsIgnore.contains( symbol ) ||
- extendedIntfSymbolsIgnore.contains( renamedSymbol ) ) {
+ public boolean shouldIgnoreInInterface(final AliasedSymbol symbol) {
+ return shouldIgnoreInInterface_Int(symbol);
+ }
+ private static boolean oneInSet(final Set<String> ignoreSymbols, final Set<String> symbols) {
+ if( null != ignoreSymbols && ignoreSymbols.size() > 0 &&
+ null != symbols && symbols.size() > 0 ) {
+ for(final String sym : symbols) {
+ if( ignoreSymbols.contains( sym ) ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ /** private static boolean allInSet(final Set<String> ignoreSymbols, final Set<String> symbols) {
+ if( null != ignoreSymbols && ignoreSymbols.size() > 0 &&
+ null != symbols && symbols.size() > 0 ) {
+ return ignoreSymbols.containsAll(symbols);
+ }
+ return false;
+ } */
+ private static boolean onePatternMatch(final Pattern ignoreRegexp, final Set<String> symbols) {
+ if( null != ignoreRegexp && null != symbols && symbols.size() > 0 ) {
+ for(final String sym : symbols) {
+ final Matcher matcher = ignoreRegexp.matcher(sym);
+ if (matcher.matches()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ protected final boolean shouldIgnoreInInterface_Int(final AliasedSymbol symbol) {
if(DEBUG_IGNORES) {
- System.err.println("Ignore Intf ignore : "+symbol);
+ dumpIgnoresOnce();
}
- return true;
- }
- // Simple case-2; the entire symbol (orig or renamed) is _not_ in the not-empty interface only table
- if ( !extendedIntfSymbolsOnly.isEmpty() &&
- !extendedIntfSymbolsOnly.contains( symbol ) &&
- !extendedIntfSymbolsOnly.contains( renamedSymbol ) ) {
+ final String name = symbol.getName();
+ final Set<String> aliases = symbol.getAliasedNames();
+
+ // Simple case-1; the symbol (orig or renamed) is in the interface ignore table
+ if ( extendedIntfSymbolsIgnore.contains( name ) ||
+ oneInSet(extendedIntfSymbolsIgnore, aliases)
+ )
+ {
if(DEBUG_IGNORES) {
- System.err.println("Ignore Intf !extended: " + symbol);
+ System.err.println("Ignore Intf ignore (one): "+symbol.getAliasedString());
}
return true;
- }
- return shouldIgnoreInImpl_Int(symbol);
+ }
+ // Simple case-2; the entire symbol (orig and renamed) is _not_ in the not-empty interface only table
+ if ( !extendedIntfSymbolsOnly.isEmpty() &&
+ !extendedIntfSymbolsOnly.contains( name ) &&
+ !oneInSet(extendedIntfSymbolsOnly, aliases) ) {
+ if(DEBUG_IGNORES) {
+ System.err.println("Ignore Intf !extended (all): " + symbol.getAliasedString());
+ }
+ return true;
+ }
+ return shouldIgnoreInImpl_Int(symbol);
}
/**
- * Returns true if this #define, function, struct, or field within
- * a struct should be ignored during glue code generation of implementation only.
+ * Returns true if this aliased symbol should be ignored
+ * during glue code generation of implementation only.
* <p>
- * For struct fields see {@link #canonicalStructFieldSymbol(String, String)}.
+ * Both, the {@link AliasedSymbol#getName() current-name}
+ * and all {@link AliasedSymbol#getAliasedNames() aliases} shall be considered.
+ * </p>
+ * <p>
+ * Implementation calls {@link #shouldIgnoreInImpl_Int(AliasedSymbol)}
+ * and overriding implementations shall ensure its being called as well!
* </p>
+ * @param symbol the symbolic aliased name to check for exclusion
*/
- public boolean shouldIgnoreInImpl(final String symbol) {
+ public boolean shouldIgnoreInImpl(final AliasedSymbol symbol) {
return shouldIgnoreInImpl_Int(symbol);
}
+ protected final boolean shouldIgnoreInImpl_Int(final AliasedSymbol symbol) {
+ final String name = symbol.getName();
+ final Set<String> aliases = symbol.getAliasedNames();
- private boolean shouldIgnoreInImpl_Int(final String symbol) {
-
- if(DEBUG_IGNORES) {
- dumpIgnoresOnce();
- }
-
- // Simple case-1; the entire symbol (orig or renamed) is in the implementation ignore table
- final String renamedSymbol = getJavaSymbolRename(symbol);
- if ( extendedImplSymbolsIgnore.contains( symbol ) ||
- extendedImplSymbolsIgnore.contains( renamedSymbol ) ) {
- if(DEBUG_IGNORES) {
- System.err.println("Ignore Impl ignore : "+symbol);
+ // Simple case-1; the symbol (orig or renamed) is in the interface ignore table
+ if ( extendedImplSymbolsIgnore.contains( name ) ||
+ oneInSet(extendedImplSymbolsIgnore, aliases)
+ )
+ {
+ if(DEBUG_IGNORES) {
+ System.err.println("Ignore Impl ignore (one): "+symbol.getAliasedString());
+ }
+ return true;
}
- return true;
- }
- // Simple case-2; the entire symbol (orig or renamed) is _not_ in the not-empty implementation only table
- if ( !extendedImplSymbolsOnly.isEmpty() &&
- !extendedImplSymbolsOnly.contains( symbol ) &&
- !extendedImplSymbolsOnly.contains( renamedSymbol ) ) {
+ // Simple case-2; the entire symbol (orig and renamed) is _not_ in the not-empty interface only table
+ if ( !extendedImplSymbolsOnly.isEmpty() &&
+ !extendedImplSymbolsOnly.contains( name ) &&
+ !oneInSet(extendedImplSymbolsOnly, aliases) ) {
if(DEBUG_IGNORES) {
- System.err.println("Ignore Impl !extended: " + symbol);
+ System.err.println("Ignore Impl !extended (all): " + symbol.getAliasedString());
}
return true;
- }
-
- // Ok, the slow case. We need to check the entire table, in case the table
- // contains an regular expression that matches the symbol.
- for (final Pattern regexp : ignores) {
- final Matcher matcher = regexp.matcher(symbol);
- if (matcher.matches()) {
- if(DEBUG_IGNORES) {
- System.err.println("Ignore Impl RegEx: "+symbol);
- }
- return true;
}
- }
- // Check negated ignore table if not empty
- if (ignoreNots.size() > 0) {
// Ok, the slow case. We need to check the entire table, in case the table
// contains an regular expression that matches the symbol.
- for (final Pattern regexp : ignoreNots) {
- final Matcher matcher = regexp.matcher(symbol);
- if (!matcher.matches()) {
- // Special case as this is most often likely to be the case.
- // Unignores are not used very often.
- if(unignores.isEmpty()) {
- if(DEBUG_IGNORES) {
- System.err.println("Ignore Impl unignores==0: "+symbol);
- }
- return true;
+ for (final Pattern ignoreRegexp : ignores) {
+ final Matcher matcher = ignoreRegexp.matcher(name);
+ if ( matcher.matches() || onePatternMatch(ignoreRegexp, aliases) ) {
+ if(DEBUG_IGNORES) {
+ System.err.println("Ignore Impl RegEx: "+symbol.getAliasedString());
+ }
+ return true;
}
+ }
- boolean unignoreFound = false;
- for (final Pattern unignoreRegexp : unignores) {
- final Matcher unignoreMatcher = unignoreRegexp.matcher(symbol);
- if (unignoreMatcher.matches()) {
- unignoreFound = true;
- break;
- }
+ // Check negated ignore table if not empty
+ if (ignoreNots.size() > 0) {
+ // Ok, the slow case. We need to check the entire table, in case the table
+ // contains an regular expression that matches the symbol.
+ for (final Pattern ignoreNotRegexp : ignoreNots) {
+ final Matcher matcher = ignoreNotRegexp.matcher(name);
+ if ( !matcher.matches() && !onePatternMatch(ignoreNotRegexp, aliases) ) {
+ // Special case as this is most often likely to be the case.
+ // Unignores are not used very often.
+ if(unignores.isEmpty()) {
+ if(DEBUG_IGNORES) {
+ System.err.println("Ignore Impl unignores==0: "+symbol.getAliasedString()+" -> "+name);
+ }
+ return true;
+ }
+ boolean unignoreFound = false;
+ for (final Pattern unignoreRegexp : unignores) {
+ final Matcher unignoreMatcher = unignoreRegexp.matcher(name);
+ if ( unignoreMatcher.matches() || onePatternMatch(unignoreRegexp, aliases) ) {
+ unignoreFound = true;
+ break;
+ }
+ }
+
+ if (!unignoreFound)
+ if(DEBUG_IGNORES) {
+ System.err.println("Ignore Impl !unignore: "+symbol.getAliasedString()+" -> "+name);
+ }
+ return true;
+ }
}
-
- if (!unignoreFound)
- if(DEBUG_IGNORES) {
- System.err.println("Ignore Impl !unignore: "+symbol);
- }
- return true;
- }
}
- }
-
- return false;
+ return false;
}
/** Returns true if this function should be given a body which
@@ -914,6 +979,19 @@ public class JavaConfiguration {
return false;
}
+ /**
+ * Return a set of aliased-name for comment in docs.
+ * <p>
+ * This is usually {@link AliasedSymbol#addAliasedName(String)},
+ * however an implementation may choose otherwise.
+ * </p>
+ * @param symbol the aliased symbol to retrieve the aliases
+ * @return set of aliased-names or {@code null}.
+ */
+ public Set<String> getAliasedDocNames(final AliasedSymbol symbol) {
+ return symbol.getAliasedNames();
+ }
+
/** Returns a replacement name for this type, which should be the
name of a Java wrapper class for a C struct, or the name
unchanged if no RenameJavaType directive was specified for this
@@ -1033,6 +1111,9 @@ public class JavaConfiguration {
nativeOutputUsesJavaHierarchy = Boolean.valueOf(tmp).booleanValue();
} else if (cmd.equalsIgnoreCase("TagNativeBinding")) {
tagNativeBinding = readBoolean("TagNativeBinding", tok, filename, lineNo).booleanValue();
+ } else if (cmd.equalsIgnoreCase("RelaxedEqualSemanticsTest")) {
+ relaxedEqualSemanticsTest = readBoolean("RelaxedEqualSemanticsTest", tok, filename, lineNo).booleanValue();
+ TypeConfig.setRelaxedEqualSemanticsTest(relaxedEqualSemanticsTest); // propagate ..
} else if (cmd.equalsIgnoreCase("Style")) {
try{
emissionStyle = EmissionStyle.valueOf(readString("Style", tok, filename, lineNo));
@@ -1222,7 +1303,7 @@ public class JavaConfiguration {
protected void readOpaque(final StringTokenizer tok, final String filename, final int lineNo) {
try {
- final JavaType javaType = JavaType.createForClass(stringToPrimitiveType(tok.nextToken()));
+ final JavaType javaType = JavaType.createForOpaqueClass(stringToPrimitiveType(tok.nextToken()));
String cType = null;
while (tok.hasMoreTokens()) {
if (cType == null) {
@@ -1755,6 +1836,16 @@ public class JavaConfiguration {
return new TypeInfo(typeName, pointerDepth, javaType);
}
+ public TypeInfo addTypeInfo(final String alias, final Type superType) {
+ final TypeInfo superInfo = typeInfo(superType);
+ if( null != superInfo ) {
+ final TypeInfo res = new TypeInfo(alias, superInfo.pointerDepth(), superInfo.javaType());
+ addTypeInfo(res);
+ return res;
+ } else {
+ return null;
+ }
+ }
protected void addTypeInfo(final TypeInfo info) {
TypeInfo tmp = typeInfoMap.get(info.name());
if (tmp == null) {
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index d2dc4ba..4db0482 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -49,6 +49,7 @@ import java.util.*;
import java.text.MessageFormat;
import com.jogamp.gluegen.cgram.types.*;
+import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol;
import java.nio.Buffer;
import java.util.logging.Logger;
@@ -70,7 +71,6 @@ import static com.jogamp.gluegen.JavaEmitter.MethodAccess.*;
public class JavaEmitter implements GlueEmitter {
private StructLayout layout;
- private TypeDictionary typedefDictionary;
private Map<Type, Type> canonMap;
protected JavaConfiguration cfg;
private boolean requiresStaticInitialization = false;
@@ -103,7 +103,11 @@ public class JavaEmitter implements GlueEmitter {
private final MachineDataInfo machDescJava = MachineDataInfo.StaticConfig.LP64_UNIX.md;
private final MachineDataInfo.StaticConfig[] machDescTargetConfigs = MachineDataInfo.StaticConfig.values();
- protected final static Logger LOG = Logger.getLogger(JavaEmitter.class.getPackage().getName());
+ protected final Logger LOG;
+
+ public JavaEmitter() {
+ LOG = Logging.getLogger(JavaEmitter.class.getPackage().getName());
+ }
@Override
public void readConfigurationFile(final String filename) throws Exception {
@@ -111,39 +115,83 @@ public class JavaEmitter implements GlueEmitter {
cfg.read(filename);
}
- class ConstantRenamer implements SymbolFilter {
+ @Override
+ public JavaConfiguration getConfiguration() { return cfg; }
+ class ConstFuncRenamer implements SymbolFilter {
private List<ConstantDefinition> constants;
-
- @Override
- public void filterSymbols(final List<ConstantDefinition> constants, final List<FunctionSymbol> functions) {
- this.constants = constants;
- doWork();
- }
+ private List<FunctionSymbol> functions;
@Override
public List<ConstantDefinition> getConstants() {
return constants;
}
-
@Override
public List<FunctionSymbol> getFunctions() {
- return null;
+ return functions;
+ }
+
+ private <T extends AliasedSemanticSymbol> List<T> filterSymbolsInt(final List<T> inList, final List<T> outList) {
+ final JavaConfiguration cfg = getConfig();
+ final HashMap<String, T> symMap = new HashMap<String, T>(100);
+ for (final T sym : inList) {
+ final String origName = sym.getName();
+ final String newName = cfg.getJavaSymbolRename(origName);
+ if( null != newName ) {
+ // Alias Name
+ final T dupSym = symMap.get(newName);
+ if( null != dupSym ) {
+ // Duplicate alias .. check and add aliased name
+ sym.rename(newName); // only rename to allow 'equalSemantics' to not care ..
+ if( !dupSym.equalSemantics(sym) ) {
+ throw new RuntimeException(
+ String.format("Duplicate Name (alias) w/ incompatible value:%n have '%s',%n this '%s'",
+ dupSym.getAliasedString(), sym.getAliasedString()));
+ }
+ dupSym.addAliasedName(origName);
+ } else {
+ // No duplicate .. rename and add
+ sym.rename(newName);
+ symMap.put(newName, sym);
+ }
+ } else {
+ // Original Name
+ final T dupSym = symMap.get(origName);
+ if( null != dupSym ) {
+ // Duplicate orig .. check and drop
+ if( !dupSym.equalSemantics(sym) ) {
+ throw new RuntimeException(
+ String.format("Duplicate Name (orig) w/ incompatible value:%n have '%s',%n this '%s'",
+ dupSym.getAliasedString(), sym.getAliasedString()));
+ }
+ } else {
+ // No duplicate orig .. add
+ symMap.put(origName, sym);
+ }
+ }
+ }
+ outList.addAll(symMap.values());
+ // sort constants to make them easier to find in native code
+ Collections.sort(outList, new Comparator<T>() {
+ @Override
+ public int compare(final T o1, final T o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ });
+ return outList;
}
- private void doWork() {
- final List<ConstantDefinition> newConstants = new ArrayList<ConstantDefinition>();
- final JavaConfiguration cfg = getConfig();
- for (final ConstantDefinition def : constants) {
- def.rename(cfg.getJavaSymbolRename(def.getName()));
- newConstants.add(def);
- }
- constants = newConstants;
+ @Override
+ public void filterSymbols(final List<ConstantDefinition> inConstList, final List<FunctionSymbol> inFuncList) {
+ constants = filterSymbolsInt(inConstList, new ArrayList<ConstantDefinition>(100));
+ functions = filterSymbolsInt(inFuncList, new ArrayList<FunctionSymbol>(100));
}
}
@Override
public void beginEmission(final GlueEmitterControls controls) throws IOException {
+ // Handle renaming of constants and functions
+ controls.runSymbolFilter(new ConstFuncRenamer());
// Request emission of any structs requested
for (final String structs : cfg.forcedStructs()) {
@@ -157,9 +205,6 @@ public class JavaEmitter implements GlueEmitter {
throw new RuntimeException("Unable to open files for writing", e);
}
emitAllFileHeaders();
-
- // Handle renaming of constants
- controls.runSymbolFilter(new ConstantRenamer());
}
}
@@ -374,7 +419,7 @@ public class JavaEmitter implements GlueEmitter {
final String name = def.getName();
String value = def.getValue();
- if (!cfg.shouldIgnoreInInterface(name)) {
+ if ( !cfg.shouldIgnoreInInterface(def) ) {
final String type = getJavaType(name, value);
if (optionalComment != null && optionalComment.length() != 0) {
javaWriter().println(" /** " + optionalComment + " */");
@@ -402,7 +447,7 @@ public class JavaEmitter implements GlueEmitter {
final TypeDictionary structDictionary,
final Map<Type, Type> canonMap) throws Exception {
- this.typedefDictionary = typedefDictionary;
+ // this.typedefDictionary = typedefDictionary;
this.canonMap = canonMap;
this.requiresStaticInitialization = false; // reset
@@ -412,55 +457,44 @@ public class JavaEmitter implements GlueEmitter {
}
@Override
- public Iterator<FunctionSymbol> emitFunctions(final List<FunctionSymbol> originalCFunctions) throws Exception {
-
- // Sometimes headers will have the same function prototype twice, once
- // with the argument names and once without. We'll remember the signatures
- // we've already processed we don't generate duplicate bindings.
- //
- // Note: this code assumes that on the equals() method in FunctionSymbol
- // only considers function name and argument types (i.e., it does not
- // consider argument *names*) when comparing FunctionSymbols for equality
- final Set<FunctionSymbol> funcsToBindSet = new HashSet<FunctionSymbol>(100);
- for (final FunctionSymbol cFunc : originalCFunctions) {
- if (!funcsToBindSet.contains(cFunc)) {
- funcsToBindSet.add(cFunc);
- }
- }
-
- // validateFunctionsToBind(funcsToBindSet);
-
- final ArrayList<FunctionSymbol> funcsToBind = new ArrayList<FunctionSymbol>(funcsToBindSet);
- // sort functions to make them easier to find in native code
- Collections.sort(funcsToBind, new Comparator<FunctionSymbol>() {
- @Override
- public int compare(final FunctionSymbol o1, final FunctionSymbol o2) {
- return o1.getName().compareTo(o2.getName());
- }
- });
-
+ public Iterator<FunctionSymbol> emitFunctions(final List<FunctionSymbol> funcsToBind) throws Exception {
// Bind all the C funcs to Java methods
final HashSet<MethodBinding> methodBindingSet = new HashSet<MethodBinding>();
final ArrayList<FunctionEmitter> methodBindingEmitters = new ArrayList<FunctionEmitter>(2*funcsToBind.size());
- for (final FunctionSymbol cFunc : funcsToBind) {
- // Check to see whether this function should be ignored
- if (!cfg.shouldIgnoreInImpl(cFunc.getName())) {
- methodBindingEmitters.addAll(generateMethodBindingEmitters(methodBindingSet, cFunc));
- }
+ {
+ int i=0;
+ for (final FunctionSymbol cFunc : funcsToBind) {
+ // Check to see whether this function should be ignored
+ if ( !cfg.shouldIgnoreInImpl(cFunc) ) {
+ methodBindingEmitters.addAll(generateMethodBindingEmitters(methodBindingSet, cFunc));
+ if( GlueGen.debug() ) {
+ System.err.println("Non-Ignored Impl["+i+"]: "+cFunc.getAliasedString());
+ i++;
+ }
+ }
+ }
}
// Emit all the methods
- for (final FunctionEmitter emitter : methodBindingEmitters) {
- try {
- if (!emitter.isInterface() || !cfg.shouldIgnoreInInterface(emitter.getName())) {
- emitter.emit();
- emitter.getDefaultOutput().println(); // put newline after method body
+ {
+ int i=0;
+ for (final FunctionEmitter emitter : methodBindingEmitters) {
+ try {
+ final FunctionSymbol cFunc = emitter.getCSymbol();
+ if ( !emitter.isInterface() || !cfg.shouldIgnoreInInterface(cFunc) ) {
+ emitter.emit();
+ emitter.getDefaultOutput().println(); // put newline after method body
+ if( GlueGen.debug() ) {
+ System.err.println("Non-Ignored Intf["+i+"]: "+cFunc.getAliasedString());
+ i++;
+ }
+ }
+ } catch (final Exception e) {
+ throw new RuntimeException(
+ "Error while emitting binding for \"" + emitter.getName() + "\"", e);
+ }
}
- } catch (final Exception e) {
- throw new RuntimeException(
- "Error while emitting binding for \"" + emitter.getName() + "\"", e);
- }
}
// Return the list of FunctionSymbols that we generated gluecode for
@@ -658,7 +692,7 @@ public class JavaEmitter implements GlueEmitter {
cfg.allStatic(),
(binding.needsNIOWrappingOrUnwrapping() || hasPrologueOrEpilogue),
!cfg.useNIODirectOnly(binding.getName()),
- machDescJava);
+ machDescJava, getConfiguration());
prepCEmitter(binding.getName(), binding.getJavaReturnType(), cEmitter);
allEmitters.add(cEmitter);
}
@@ -821,40 +855,69 @@ public class JavaEmitter implements GlueEmitter {
public void beginStructs(final TypeDictionary typedefDictionary,
final TypeDictionary structDictionary,
final Map<Type, Type> canonMap) throws Exception {
- this.typedefDictionary = typedefDictionary;
+ // this.typedefDictionary = typedefDictionary;
this.canonMap = canonMap;
}
@Override
- public void emitStruct(final CompoundType structCType, final String alternateName) throws Exception {
- final String structCTypeName;
+ public void emitStruct(final CompoundType structCType, final Type typedefed) throws Exception {
+ final String structCTypeName, typedefedName;
{
- String _name = structCType.getName();
- if (_name == null && alternateName != null) {
- _name = alternateName;
+ final String _name = structCType.getName();
+ if ( null == _name && null != typedefed && null != typedefed.getName() ) {
+ // use typedef'ed name
+ typedefedName = typedefed.getName();
+ structCTypeName = typedefedName;
+ } else {
+ // use actual struct type name
+ typedefedName = null;
+ structCTypeName = _name;
}
- structCTypeName = _name;
}
-
- if (structCTypeName == null) {
+ if ( null == structCTypeName ) {
final String structName = structCType.getStructName();
if ( null != structName && cfg.shouldIgnoreInInterface(structName) ) {
+ LOG.log(INFO, "skipping emission of unnamed ignored struct \"{0}\": {1}", new Object[] { structName, structCType.getDebugString() });
+ return;
+ } else {
+ final String d1 = null != typedefed ? typedefed.getDebugString() : null;
+ LOG.log(INFO, "skipping emission of unnamed struct {0}, typedef {1} ", new Object[] { structCType.getDebugString(), d1 });
return;
}
- LOG.log(WARNING, "skipping emission of unnamed struct \"{0}\"", structCType);
+ }
+ if ( cfg.shouldIgnoreInInterface(structCTypeName) ) {
+ LOG.log(INFO, "skipping emission of ignored \"{0}\": {1}", new Object[] { structCTypeName, structCType.getDebugString() });
return;
}
-
- if (cfg.shouldIgnoreInInterface(structCTypeName)) {
- return;
+ if( null != typedefed && isOpaque(typedefed) ) {
+ LOG.log(INFO, "skipping emission of opaque typedef {0}, c-struct {1}", new Object[] { typedefed.getDebugString(), structCType.getDebugString() });
+ return;
}
- final Type containingCType = canonicalize(new PointerType(SizeThunk.POINTER, structCType, 0));
+ final Type containingCType = canonicalize(new PointerType(SizeThunk.POINTER, structCType, 0, typedefedName));
final JavaType containingJType = typeToJavaType(containingCType, null);
- if (!containingJType.isCompoundTypeWrapper()) {
- return;
+ if( containingJType.isOpaqued() ) {
+ LOG.log(INFO, "skipping emission of opaque {0}, {1}", new Object[] { containingJType.getDebugString(), structCType.getDebugString() });
+ return;
+ }
+ if( !containingJType.isCompoundTypeWrapper() ) {
+ LOG.log(WARNING, "skipping emission of non-compound {0}, {1}", new Object[] { containingJType.getDebugString(), structCType.getDebugString() });
+ return;
}
final String containingJTypeName = containingJType.getName();
+ LOG.log(INFO, "perform emission of \"{0}\" -> \"{1}\": {2}", new Object[] { structCTypeName, containingJTypeName, structCType.getDebugString()});
+ if( GlueGen.debug() ) {
+ if( null != typedefed ) {
+ LOG.log(INFO, " typedefed {0}", typedefed.getDebugString());
+ } else {
+ LOG.log(INFO, " typedefed NULL");
+ }
+ LOG.log(INFO, " containingCType {0}", containingCType.getDebugString());
+ LOG.log(INFO, " containingJType {0}", containingJType.getDebugString());
+ }
+ if( 0 == structCType.getNumFields() ) {
+ LOG.log(INFO, "emission of \"{0}\" with zero fields {1}", new Object[] { containingJTypeName, structCType.getDebugString() });
+ }
this.requiresStaticInitialization = false; // reset
@@ -1355,7 +1418,7 @@ public class JavaEmitter implements GlueEmitter {
false,
true,
false, // forIndirectBufferAndArrayImplementation
- machDescJava);
+ machDescJava, getConfiguration());
cEmitter.setIsCStructFunctionPointer(true);
prepCEmitter(returnSizeLookupName, binding.getJavaReturnType(), cEmitter);
cEmitter.emit();
@@ -1420,7 +1483,7 @@ public class JavaEmitter implements GlueEmitter {
false,
true,
false, // forIndirectBufferAndArrayImplementation
- machDescJava);
+ machDescJava, getConfiguration());
cEmitter.setIsCStructFunctionPointer(false);
final String lenExprSet;
if( null != nativeArrayLenExpr ) {
@@ -1947,10 +2010,9 @@ public class JavaEmitter implements GlueEmitter {
}
}
- private static final boolean DEBUG_TYPEC2JAVA = false;
private JavaType typeToJavaType(final Type cType, final MachineDataInfo curMachDesc) {
final JavaType jt = typeToJavaTypeImpl(cType, curMachDesc);
- if( DEBUG_TYPEC2JAVA ) {
+ if( GlueGen.debug() ) {
System.err.println("typeToJavaType: "+cType.getDebugString()+" -> "+jt.getDebugString());
}
return jt;
@@ -1968,7 +2030,7 @@ public class JavaEmitter implements GlueEmitter {
}
// Opaque specifications override automatic conversions
// in case the identity is being used .. not if ptr-ptr
- final TypeInfo info = cfg.typeInfo(cType, typedefDictionary);
+ final TypeInfo info = cfg.typeInfo(cType);
if (info != null) {
boolean isPointerPointer = false;
if (cType.pointerDepth() > 0 || cType.arrayDimension() > 0) {
@@ -1986,16 +2048,15 @@ public class JavaEmitter implements GlueEmitter {
// target type)
if (targetType.isPointer()) {
isPointerPointer = true;
-
- // t is<type>**, targetType is <type>*, we need to get <type>
- final Type bottomType = targetType.asPointer().getTargetType();
if( GlueGen.debug() ) {
+ // t is<type>**, targetType is <type>*, we need to get <type>
+ final Type bottomType = targetType.asPointer().getTargetType();
LOG.log(INFO, "Opaque Type: {0}, targetType: {1}, bottomType: {2} is ptr-ptr", new Object[]{cType.getDebugString(), targetType, bottomType});
}
}
}
}
- if(!isPointerPointer) {
+ if( !isPointerPointer ) {
return info.javaType();
}
}
@@ -2066,7 +2127,6 @@ public class JavaEmitter implements GlueEmitter {
throw new RuntimeException("Couldn't find a proper type name for pointer type " + cType.getDebugString());
}
}
-
return JavaType.createForCStruct(cfg.renameJavaType(name));
} else {
throw new RuntimeException("Don't know how to convert pointer/array type \"" +
@@ -2189,7 +2249,7 @@ public class JavaEmitter implements GlueEmitter {
}
private boolean isOpaque(final Type type) {
- return (cfg.typeInfo(type, typedefDictionary) != null);
+ return (cfg.typeInfo(type) != null);
}
private String compatiblePrimitiveJavaTypeName(final Type fieldType,
@@ -2586,9 +2646,6 @@ public class JavaEmitter implements GlueEmitter {
final MachineDataInfo curMachDesc) {
final MethodBinding binding = new MethodBinding(sym, containingType, containingCType);
-
- binding.renameMethodName(cfg.getJavaSymbolRename(sym.getName()));
-
// System.out.println("bindFunction(0) "+sym.getReturnType());
if (cfg.returnsString(binding.getName())) {
@@ -2779,10 +2836,11 @@ public class JavaEmitter implements GlueEmitter {
private Type canonicalize(final Type t) {
final Type res = canonMap.get(t);
if (res != null) {
- return res;
+ return res;
+ } else {
+ canonMap.put(t, t);
+ return t;
}
- canonMap.put(t, t);
- return t;
}
/**
diff --git a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java
index 6966315..9d02c14 100644
--- a/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaMethodBindingEmitter.java
@@ -40,14 +40,17 @@
package com.jogamp.gluegen;
import com.jogamp.gluegen.cgram.HeaderParser;
+import com.jogamp.gluegen.cgram.types.AliasedSymbol;
import com.jogamp.gluegen.cgram.types.ArrayType;
import com.jogamp.gluegen.cgram.types.EnumType;
+import com.jogamp.gluegen.cgram.types.FunctionSymbol;
import com.jogamp.gluegen.cgram.types.Type;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
/**
* An emitter that emits only the interface for a Java<->C JNI binding.
@@ -97,9 +100,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
// represent an array of compound type wrappers
private static final String COMPOUND_ARRAY_SUFFIX = "_buf_array_copy";
- // Only present to provide more clear comments
- private final JavaConfiguration cfg;
-
public JavaMethodBindingEmitter(final MethodBinding binding,
final PrintWriter output,
final String runtimeExceptionType,
@@ -115,7 +115,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
final boolean isUnimplemented,
final boolean isInterface,
final JavaConfiguration configuration) {
- super(output, isInterface);
+ super(output, isInterface, configuration);
this.binding = binding;
this.runtimeExceptionType = runtimeExceptionType;
this.unsupportedExceptionType = unsupportedExceptionType;
@@ -133,7 +133,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
} else {
setCommentEmitter(defaultInterfaceCommentEmitter);
}
- cfg = configuration;
}
public JavaMethodBindingEmitter(final JavaMethodBindingEmitter arg) {
@@ -154,7 +153,6 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
epilogue = arg.epilogue;
returnedArrayLengthExpression = arg.returnedArrayLengthExpression;
returnedArrayLengthExpressionOnlyForComments = arg.returnedArrayLengthExpressionOnlyForComments;
- cfg = arg.cfg;
}
public final MethodBinding getBinding() { return binding; }
@@ -168,6 +166,11 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
return binding.getName();
}
+ @Override
+ public FunctionSymbol getCSymbol() {
+ return binding.getCSymbol();
+ }
+
protected String getArgumentName(final int i) {
return binding.getArgumentName(i);
}
@@ -812,6 +815,26 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
* emitter java method.
*/
protected class DefaultCommentEmitter implements CommentEmitter {
+ protected void emitAliasedDocNamesComment(final AliasedSymbol sym, final PrintWriter writer) {
+ writer.print(emitAliasedDocNamesComment(sym, new StringBuilder()).toString());
+ }
+ protected StringBuilder emitAliasedDocNamesComment(final AliasedSymbol sym, final StringBuilder sb) {
+ final Set<String> aliases = cfg.getAliasedDocNames(sym);
+ if (aliases != null && aliases.size() > 0 ) {
+ int i=0;
+ sb.append("Alias for: <code>");
+ for (final String alias : aliases) {
+ if(0 < i) {
+ sb.append("</code>, <code>");
+ }
+ sb.append(alias);
+ i++;
+ }
+ sb.append("</code>");
+ }
+ return sb;
+ }
+
@Override
public void emit(final FunctionEmitter emitter, final PrintWriter writer) {
emitBeginning(emitter, writer);
@@ -826,9 +849,11 @@ public class JavaMethodBindingEmitter extends FunctionEmitter {
writer.print("Entry point to C language function: ");
}
protected void emitBindingCSignature(final MethodBinding binding, final PrintWriter writer) {
- writer.print("<code> ");
- writer.print(binding.getCSymbol().toString(tagNativeBinding));
- writer.print(" </code> ");
+ final FunctionSymbol funcSym = binding.getCSymbol();
+ writer.print("<code>");
+ writer.print(funcSym.toString(tagNativeBinding));
+ writer.print("</code><br>");
+ emitAliasedDocNamesComment(funcSym, writer);
}
protected void emitEnding(final FunctionEmitter emitter, final PrintWriter writer) {
// If argument type is a named enum, then emit a comment detailing the
diff --git a/src/java/com/jogamp/gluegen/JavaType.java b/src/java/com/jogamp/gluegen/JavaType.java
index 87804bd..9bcd663 100644
--- a/src/java/com/jogamp/gluegen/JavaType.java
+++ b/src/java/com/jogamp/gluegen/JavaType.java
@@ -63,6 +63,7 @@ public class JavaType {
private final String structName; // Types we're generating glue code for (i.e., C structs)
private final Type elementType; // Element type if this JavaType represents a C array
private final C_PTR primitivePointerType;
+ private final boolean opaqued;
private static JavaType nioBufferType;
private static JavaType nioByteBufferType;
@@ -107,12 +108,20 @@ public class JavaType {
return elementType;
}
+ /** Creates a JavaType corresponding to the given opaque Java type. This
+ can be used to represent arrays of primitive values or Strings;
+ the emitters understand how to perform proper conversion from
+ the corresponding C type. */
+ public static JavaType createForOpaqueClass(final Class<?> clazz) {
+ return new JavaType(clazz, true);
+ }
+
/** Creates a JavaType corresponding to the given Java type. This
can be used to represent arrays of primitive values or Strings;
the emitters understand how to perform proper conversion from
the corresponding C type. */
public static JavaType createForClass(final Class<?> clazz) {
- return new JavaType(clazz);
+ return new JavaType(clazz, false);
}
/** Creates a JavaType corresponding to the specified C CompoundType
@@ -336,6 +345,8 @@ public class JavaType {
return "jobject";
}
+ public boolean isOpaqued() { return opaqued; }
+
public boolean isNIOBuffer() {
return clazz != null && ( java.nio.Buffer.class.isAssignableFrom(clazz) ||
com.jogamp.common.nio.NativeBuffer.class.isAssignableFrom(clazz)) ;
@@ -528,34 +539,39 @@ public class JavaType {
append(sb, "primitivePointerType = "+primitivePointerType, prepComma); prepComma=true;
}
append(sb, "is[", prepComma); prepComma=false;
- if( isArray() ) {
- append(sb, "array", prepComma); prepComma=true;
- }
- if( isArrayOfCompoundTypeWrappers() ) {
- append(sb, "compoundArray", prepComma); prepComma=true;
- }
- if( isCompoundTypeWrapper() ) {
- append(sb, "compound", prepComma); prepComma=true;
- }
- if( isArray() ) {
- append(sb, "array", prepComma); prepComma=true;
- }
- if( isPrimitive() ) {
- append(sb, "primitive", prepComma); prepComma=true;
- }
- if( isPrimitiveArray() ) {
- append(sb, "primitiveArray", prepComma); prepComma=true;
- }
- if( isNIOBuffer() ) {
- append(sb, "nioBuffer", prepComma); prepComma=true;
- }
- if( isNIOBufferArray() ) {
- append(sb, "nioBufferArray", prepComma); prepComma=true;
- }
- if( isCPrimitivePointerType() ) {
- append(sb, "C-Primitive-Pointer", prepComma); prepComma=true;
+ {
+ if( isOpaqued() ) {
+ append(sb, "opaque", prepComma); prepComma=true;
+ }
+ if( isArray() ) {
+ append(sb, "array", prepComma); prepComma=true;
+ }
+ if( isArrayOfCompoundTypeWrappers() ) {
+ append(sb, "compoundArray", prepComma); prepComma=true;
+ }
+ if( isCompoundTypeWrapper() ) {
+ append(sb, "compound", prepComma); prepComma=true;
+ }
+ if( isArray() ) {
+ append(sb, "array", prepComma); prepComma=true;
+ }
+ if( isPrimitive() ) {
+ append(sb, "primitive", prepComma); prepComma=true;
+ }
+ if( isPrimitiveArray() ) {
+ append(sb, "primitiveArray", prepComma); prepComma=true;
+ }
+ if( isNIOBuffer() ) {
+ append(sb, "nioBuffer", prepComma); prepComma=true;
+ }
+ if( isNIOBufferArray() ) {
+ append(sb, "nioBufferArray", prepComma); prepComma=true;
+ }
+ if( isCPrimitivePointerType() ) {
+ append(sb, "C-Primitive-Pointer", prepComma); prepComma=true;
+ }
}
- append(sb, "descriptor '"+getDescriptor()+"'", prepComma); prepComma=true;
+ append(sb, "], descriptor '"+getDescriptor()+"']", prepComma); prepComma=true;
return sb.toString();
}
@@ -563,11 +579,12 @@ public class JavaType {
* Constructs a representation for a type corresponding to the given Class
* argument.
*/
- private JavaType(final Class<?> clazz) {
+ private JavaType(final Class<?> clazz, final boolean opaqued) {
this.primitivePointerType = null;
this.clazz = clazz;
this.structName = null;
this.elementType = null;
+ this.opaqued = opaqued;
}
/** Constructs a type representing a named C struct. */
@@ -576,6 +593,7 @@ public class JavaType {
this.clazz = null;
this.structName = structName;
this.elementType = null;
+ this.opaqued = false;
}
/** Constructs a type representing a pointer to a C primitive
@@ -585,6 +603,7 @@ public class JavaType {
this.clazz = null;
this.structName = null;
this.elementType = null;
+ this.opaqued = false;
}
/** Constructs a type representing an array of C pointers. */
@@ -593,6 +612,7 @@ public class JavaType {
this.clazz = null;
this.structName = null;
this.elementType = elementType;
+ this.opaqued = false;
}
/** clone only */
@@ -601,6 +621,7 @@ public class JavaType {
this.clazz = clazz;
this.structName = name;
this.elementType = elementType;
+ this.opaqued = false;
}
private String arrayName(Class<?> clazz) {
diff --git a/src/java/com/jogamp/gluegen/Logging.java b/src/java/com/jogamp/gluegen/Logging.java
index 40eadcb..77856f4 100644
--- a/src/java/com/jogamp/gluegen/Logging.java
+++ b/src/java/com/jogamp/gluegen/Logging.java
@@ -33,6 +33,7 @@ package com.jogamp.gluegen;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
+import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
@@ -41,11 +42,13 @@ import com.jogamp.common.util.PropertyAccess;
/**
*
- * @author Michael Bien
+ * @author Michael Bien, et.al.
*/
public class Logging {
- static void init() {
+ final static Logger rootPackageLogger;
+
+ static {
final String packageName = Logging.class.getPackage().getName();
final String property = PropertyAccess.getProperty(packageName+".level", true);
Level level;
@@ -64,12 +67,35 @@ public class Logging {
handler.setFormatter(new PlainLogFormatter());
handler.setLevel(level);
- final Logger rootPackageLogger = Logger.getLogger(packageName);
+ rootPackageLogger = Logger.getLogger(packageName);
rootPackageLogger.setUseParentHandlers(false);
rootPackageLogger.setLevel(level);
rootPackageLogger.addHandler(handler);
}
+ /** provokes static initialization */
+ static void init() { }
+
+ /** Returns the <i>root package logger</i>. */
+ public static Logger getLogger() {
+ return rootPackageLogger;
+ }
+ /** Returns the demanded logger, while aligning its log-level to the root logger's level. */
+ public static synchronized Logger getLogger(final String name) {
+ final Logger l = Logger.getLogger(name);
+ alignLevel(l);
+ return l;
+ }
+ /** Align log-level of given logger to the root logger's level. */
+ public static void alignLevel(final Logger l) {
+ final Level level = rootPackageLogger.getLevel();
+ l.setLevel(level);
+ final Handler[] hs = l.getHandlers();
+ for(final Handler h:hs) {
+ h.setLevel(level);
+ }
+ }
+
/**
* This log formatter needs usually one line per log record.
* @author Michael Bien
diff --git a/src/java/com/jogamp/gluegen/MethodBinding.java b/src/java/com/jogamp/gluegen/MethodBinding.java
index 93c55d5..56b4fc8 100644
--- a/src/java/com/jogamp/gluegen/MethodBinding.java
+++ b/src/java/com/jogamp/gluegen/MethodBinding.java
@@ -44,7 +44,6 @@ import com.jogamp.gluegen.cgram.types.Type;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
/** Represents the binding of a C function to a Java method. Also used
@@ -54,8 +53,6 @@ import java.util.List;
public class MethodBinding {
private final FunctionSymbol sym;
- private String renamedMethodName;
- private final HashSet<String> aliasedNames;
private JavaType javaReturnType;
private List<JavaType> javaArgumentTypes;
private boolean computedSignatureProperties;
@@ -81,8 +78,6 @@ public class MethodBinding {
public MethodBinding(final MethodBinding bindingToCopy) {
this.sym = bindingToCopy.sym;
- this.renamedMethodName = bindingToCopy.renamedMethodName;
- this.aliasedNames = new HashSet<String>(bindingToCopy.aliasedNames);
this.containingType = bindingToCopy.containingType;
this.containingCType = bindingToCopy.containingCType;
this.javaReturnType = bindingToCopy.javaReturnType;
@@ -104,7 +99,6 @@ public class MethodBinding {
/** Constructor for calling a C function. */
public MethodBinding(final FunctionSymbol sym) {
this.sym = sym;
- this.aliasedNames = new HashSet<String>();
}
/** Constructor for calling a function pointer contained in a
@@ -113,7 +107,6 @@ public class MethodBinding {
this.sym = sym;
this.containingType = containingType;
this.containingCType = containingCType;
- this.aliasedNames = new HashSet<String>();
}
public void setJavaReturnType(final JavaType type) {
@@ -166,34 +159,13 @@ public class MethodBinding {
return "arg" + i;
}
- public String getOrigName() {
- return sym.getName();
+ public Collection<String> getAliasedNames() {
+ return sym.getAliasedNames();
}
-
public String getName() {
- // Defaults to same as C symbol unless renamed
- if (renamedMethodName != null) {
- return renamedMethodName;
- }
return sym.getName();
}
- /** Supports renaming C function in Java binding. */
- public void renameMethodName(final String name) {
- if (null != name) {
- renamedMethodName = name;
- aliasedNames.add(sym.getName());
- }
- }
-
- public void addAliasedName(final String name) {
- aliasedNames.add(name);
- }
-
- public Collection<String> getAliasedNames() {
- return aliasedNames;
- }
-
/** Creates a new MethodBinding replacing the specified Java
argument type with a new argument type. If argumentNumber is
less than 0 then replaces the return type. */
diff --git a/src/java/com/jogamp/gluegen/ReferencedStructs.java b/src/java/com/jogamp/gluegen/ReferencedStructs.java
index d06d47f..546726f 100644
--- a/src/java/com/jogamp/gluegen/ReferencedStructs.java
+++ b/src/java/com/jogamp/gluegen/ReferencedStructs.java
@@ -58,7 +58,7 @@ public class ReferencedStructs implements TypeVisitor {
public void visitType(final Type t) {
if (t.isPointer()) {
final PointerType p = t.asPointer();
- if (p.hasTypedefedName()) {
+ if (p.hasTypedefName()) {
final CompoundType c = p.getTargetType().asCompound();
if (c != null && c.getName() == null) {
// This otherwise-unnamed CompoundType is referred to by a
diff --git a/src/java/com/jogamp/gluegen/TypeConfig.java b/src/java/com/jogamp/gluegen/TypeConfig.java
new file mode 100644
index 0000000..5f389f4
--- /dev/null
+++ b/src/java/com/jogamp/gluegen/TypeConfig.java
@@ -0,0 +1,52 @@
+/**
+ * Copyright 2015 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.gluegen;
+
+import com.jogamp.gluegen.cgram.types.SizeThunk;
+import com.jogamp.gluegen.cgram.types.Type;
+
+/**
+ * Static {@link Type} config helper
+ * binding {@link JavaConfiguration#relaxedEqualSemanticsTest()} system wide.
+ */
+public class TypeConfig {
+ private static boolean relaxedEqualSemanticsTest = false;
+
+ /**
+ * Returns whether {@link TypeConfig.SemanticEqualityOp#equalSemantics(TypeConfig.SemanticEqualityOp)}
+ * shall attempt to perform a relaxed semantic equality test, e.g. skip the {@code const} and {@code volatile} qualifier
+ * - or not.
+ */
+ public static boolean relaxedEqualSemanticsTest() {
+ return relaxedEqualSemanticsTest;
+ }
+ /* pp */ static void setRelaxedEqualSemanticsTest(final boolean v) {
+ relaxedEqualSemanticsTest = v;
+ SizeThunk.setRelaxedEqualSemanticsTest(v);
+ }
+}
diff --git a/src/java/com/jogamp/gluegen/TypeInfo.java b/src/java/com/jogamp/gluegen/TypeInfo.java
index d89ac79..52fdc04 100644
--- a/src/java/com/jogamp/gluegen/TypeInfo.java
+++ b/src/java/com/jogamp/gluegen/TypeInfo.java
@@ -66,7 +66,7 @@ public class TypeInfo {
buf.append(name);
buf.append(" pointerDepth ");
buf.append(pointerDepth);
- buf.append(" JavaType " + javaType);
+ buf.append(" JavaType " + javaType.getDebugString());
return buf.toString();
}
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java b/src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java
new file mode 100644
index 0000000..a924876
--- /dev/null
+++ b/src/java/com/jogamp/gluegen/cgram/types/AliasedSymbol.java
@@ -0,0 +1,154 @@
+/**
+ * Copyright 2015 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.gluegen.cgram.types;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Supports symbol aliasing, i.e. renaming,
+ * while preserving all its original names, i.e. aliases.
+ */
+public interface AliasedSymbol {
+ /**
+ * Rename this symbol with the given {@code newName} if not equal {@link #getName() current-name}.
+ * <p>
+ * Before renaming the {@link #getName() current-name} will be added
+ * to the list of {@link #getAliasedNames() aliases}.
+ * while the given {@code newName} will be removed.
+ * </p>
+ * @param newName the new {@link #getName() current-name}
+ */
+ void rename(final String newName);
+ /**
+ * Add the given {@code origName} to the list of {@link #getAliasedNames() aliases}
+ * if not equal {@link #getName() current-name}.
+ * @param origName the new alias to be added
+ */
+ void addAliasedName(final String origName);
+ /**
+ *
+ * Returns {@code true} if this symbol has aliases, i.e. either being {@link #rename(String) renamed}
+ * or {@link #addAliasedName(String) aliases-added}.
+ * <p>
+ * Otherwise {@code false} is being returned.
+ * </p>
+ */
+ boolean hasAliases();
+ /**
+ * Return all aliases for this symbol, i.e. original names, for this symbol.
+ * <p>
+ * Exclusive {@link #getName() current-name}.
+ * </p>
+ * <p>
+ * May return {@code null} or a zero sized {@link Set} for no aliases.
+ * </p>
+ */
+ Set<String> getAliasedNames();
+ /**
+ * Return the current-name, which is the last {@link #rename(String) renamed-name} if issued,
+ * or the original-name.
+ */
+ String getName();
+ /**
+ * Return this object's {@link #toString()} wrapped w/ the {@link #getName() current-name}
+ * and all {@link #getAliasedNames() aliases}.
+ */
+ String getAliasedString();
+
+ public static class AliasedSymbolImpl implements AliasedSymbol {
+ private final HashSet<String> aliasedNames;
+ private String name;
+
+ public AliasedSymbolImpl(final String origName) {
+ this.aliasedNames=new HashSet<String>();
+ this.name = origName;
+ }
+ @Override
+ public void rename(final String newName) {
+ if( !name.equals(newName) ) {
+ aliasedNames.add(name);
+ aliasedNames.remove(newName);
+ name = newName;
+ }
+ }
+ @Override
+ public void addAliasedName(final String origName) {
+ if( !name.equals(origName) ) {
+ aliasedNames.add(origName);
+ }
+ }
+ @Override
+ public boolean hasAliases() {
+ return aliasedNames.size() > 0;
+ }
+ @Override
+ public Set<String> getAliasedNames() {
+ return aliasedNames;
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getAliasedString() {
+ return "["+name+", aliases "+aliasedNames.toString()+", "+toString()+"]";
+ }
+ }
+ public static class NoneAliasedSymbol implements AliasedSymbol {
+ private final String name;
+
+ public NoneAliasedSymbol(final String origName) {
+ this.name = origName;
+ }
+ @Override
+ public void rename(final String newName) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public void addAliasedName(final String origName) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean hasAliases() {
+ return false;
+ }
+ @Override
+ public Set<String> getAliasedNames() {
+ return null;
+ }
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getAliasedString() {
+ return toString();
+ }
+ }
+}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java b/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java
index d867b40..281c68d 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/ArrayType.java
@@ -48,7 +48,6 @@ package com.jogamp.gluegen.cgram.types;
public class ArrayType extends MemoryLayoutType implements Cloneable {
private final Type elementType;
private final int length;
- private String computedName;
public ArrayType(final Type elementType, final SizeThunk sizeInBytes, final int length, final int cvAttributes) {
super(elementType.getName() + " *", sizeInBytes, cvAttributes);
@@ -57,24 +56,39 @@ public class ArrayType extends MemoryLayoutType implements Cloneable {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) return true;
- if (arg == null || (!(arg instanceof ArrayType))) {
- return false;
- }
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = elementType.hashCode();
+ return ((hash << 5) - hash) + length;
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type arg) {
+ final ArrayType t = (ArrayType) arg;
+ return elementType.equals(t.elementType) &&
+ length == t.length;
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = elementType.hashCodeSemantics();
+ return ((hash << 5) - hash) + length;
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type arg) {
final ArrayType t = (ArrayType) arg;
- return (super.equals(arg) && elementType.equals(t.elementType) && (length == t.length));
+ return elementType.equalSemantics(t.elementType) &&
+ length == t.length;
}
@Override
+ public boolean hasName() { return null != elementType.getName(); }
+
+ @Override
public String getName(final boolean includeCVAttrs) {
- // Lazy computation of name due to lazy setting of compound type
- // names during parsing
- // Note: don't think cvAttributes can be set for array types (unlike pointer types)
- if (computedName == null) {
- computedName = (elementType.getName() + " *").intern();
- }
- return computedName;
+ return elementType.getName() + " *";
}
@Override
@@ -114,7 +128,7 @@ public class ArrayType extends MemoryLayoutType implements Cloneable {
if(elementType.isConst()) {
buf.append("const ");
}
- buf.append(elementType.getName());
+ buf.append(elementType.getCName());
if (variableName != null) {
buf.append(" ");
buf.append(variableName);
diff --git a/src/java/com/jogamp/gluegen/cgram/types/BitType.java b/src/java/com/jogamp/gluegen/cgram/types/BitType.java
index 2644551..87eb8ce 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/BitType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/BitType.java
@@ -40,6 +40,8 @@
package com.jogamp.gluegen.cgram.types;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
+
/** Represents a bitfield in a struct. */
public class BitType extends IntType implements Cloneable {
@@ -55,14 +57,35 @@ public class BitType extends IntType implements Cloneable {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) return true;
- if (arg == null || (!(arg instanceof BitType))) {
- return false;
- }
- final BitType t = (BitType) arg;
- return (super.equals(arg) && underlyingType.equals(t.underlyingType) &&
- (sizeInBits == t.sizeInBits) && (offset == t.offset));
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ int hash = underlyingType.hashCode();
+ hash = ((hash << 5) - hash) + sizeInBits;
+ return ((hash << 5) - hash) + offset;
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type arg) {
+ final BitType t = (BitType) arg;
+ return underlyingType.equals(t.underlyingType) &&
+ sizeInBits == t.sizeInBits &&
+ offset == t.offset;
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ // 31 * x == (x << 5) - x
+ int hash = underlyingType.hashCodeSemantics();
+ hash = ((hash << 5) - hash) + sizeInBits;
+ return ((hash << 5) - hash) + offset;
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type arg) {
+ final BitType t = (BitType) arg;
+ return underlyingType.equalSemantics(t.underlyingType) &&
+ sizeInBits == t.sizeInBits &&
+ offset == t.offset;
}
@Override
diff --git a/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java b/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java
index 9716f54..c3aca40 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/CompoundType.java
@@ -46,29 +46,67 @@ import java.util.*;
and unions. The boolean type accessors indicate how the type is
really defined. */
-public abstract class CompoundType extends MemoryLayoutType implements Cloneable {
+public abstract class CompoundType extends MemoryLayoutType implements Cloneable, AliasedSymbol {
// The name "foo" in the construct "struct foo { ... }";
- private String structName;
+ private final String structName;
private ArrayList<Field> fields;
private boolean visiting;
private boolean bodyParsed;
- private boolean computedHashcode;
- private int hashcode;
-
+ /**
+ *
+ * @param name
+ * @param size
+ * @param cvAttributes
+ * @param structName
+ */
CompoundType(final String name, final SizeThunk size, final int cvAttributes, final String structName) {
super(name, size, cvAttributes);
this.structName = structName;
}
- public static CompoundType create(final String name, final SizeThunk size, final CompoundTypeKind kind, final int cvAttributes) {
+ @Override
+ public void rename(final String newName) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public void addAliasedName(final String origName) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean hasAliases() {
+ return false;
+ }
+ @Override
+ public Set<String> getAliasedNames() {
+ return null;
+ }
+ @Override
+ public String getAliasedString() {
+ return toString();
+ }
+
+ /**
+ * @param structName struct name of this CompoundType, i.e. the "foo" in the
+ construct {@code struct foo { int a, ... };} or {@code struct foo;} <i>even</i> for anonymous structs.
+ * @param size
+ * @param kind
+ * @param cvAttributes
+ * @return
+ */
+ public static CompoundType create(final String structName, final SizeThunk size, final CompoundTypeKind kind, final int cvAttributes)
+ {
+ final CompoundType res;
switch (kind) {
case STRUCT:
- return new StructType(name, size, cvAttributes);
+ res = new StructType(null, size, cvAttributes, structName);
+ break;
case UNION:
- return new UnionType(name, size, cvAttributes);
+ res = new UnionType(null, size, cvAttributes, structName);
+ break;
default:
throw new RuntimeException("OO relation "+kind+" / Compount not yet supported");
}
+ return res;
}
@Override
@@ -81,34 +119,31 @@ public abstract class CompoundType extends MemoryLayoutType implements Cloneable
}
@Override
- public int hashCode() {
- if (computedHashcode) {
- return hashcode;
- }
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = 31 + ( null != structName ? structName.hashCode() : 0 );
+ return ((hash << 5) - hash) + TypeComparator.listsHashCode(fields);
+ }
- if (structName != null) {
- hashcode = structName.hashCode();
- } else if (getName() != null) {
- hashcode = getName().hashCode();
- } else {
- hashcode = 0;
- }
+ @Override
+ protected boolean equalsImpl(final Type arg) {
+ final CompoundType ct = (CompoundType) arg;
+ return ( (structName == null ? ct.structName == null : structName.equals(ct.structName)) ||
+ (structName != null && structName.equals(ct.structName))
+ ) &&
+ TypeComparator.listsEqual(fields, ct.fields);
+ }
- computedHashcode = true;
- return hashcode;
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ // 31 * x == (x << 5) - x
+ return TypeComparator.listsHashCodeSemantics(fields);
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) return true;
- if (arg == null || !(arg instanceof CompoundType)) {
- return false;
- }
- final CompoundType t = (CompoundType) arg;
- return super.equals(arg) &&
- ((structName == null ? t.structName == null : structName.equals(t.structName)) ||
- (structName != null && structName.equals(t.structName))) &&
- listsEqual(fields, t.fields);
+ protected boolean equalSemanticsImpl(final Type arg) {
+ final CompoundType ct = (CompoundType) arg;
+ return TypeComparator.listsEqualSemantics(fields, ct.fields);
}
/** Returns the struct name of this CompoundType, i.e. the "foo" in
@@ -117,12 +152,6 @@ public abstract class CompoundType extends MemoryLayoutType implements Cloneable
return structName;
}
- /** Sets the struct name of this CompoundType, i.e. the "foo" in the
- construct "struct foo { ... };". */
- public void setStructName(final String structName) {
- this.structName = structName;
- }
-
@Override
public void setSize(final SizeThunk size) {
super.setSize(size);
@@ -131,8 +160,17 @@ public abstract class CompoundType extends MemoryLayoutType implements Cloneable
@Override
public CompoundType asCompound() { return this; }
+ @Override
+ public String getCName(final boolean includeCVAttrs) {
+ if( hasTypedefName() ) {
+ return getName(includeCVAttrs);
+ } else {
+ return (isStruct() ? "struct " : "union ")+getName(includeCVAttrs);
+ }
+ }
+
ArrayList<Field> getFields() { return fields; }
- void setFields(final ArrayList<Field> fields) { this.fields = fields; }
+ void setFields(final ArrayList<Field> fields) { this.fields = fields; clearCache(); }
/** Returns the number of fields in this type. */
public int getNumFields() {
@@ -147,18 +185,42 @@ public abstract class CompoundType extends MemoryLayoutType implements Cloneable
/** Adds a field to this type. */
public void addField(final Field f) {
if (bodyParsed) {
- throw new RuntimeException("Body of this CompoundType has already been parsed; should not be adding more fields");
+ throw new IllegalStateException("Body of this CompoundType has been already closed");
}
if (fields == null) {
fields = new ArrayList<Field>();
}
fields.add(f);
+ clearCache();
}
- /** Indicates to this CompoundType that its body has been parsed and
- that no more {@link #addField} operations will be made. */
- public void setBodyParsed() {
+ /**
+ * Indicates to this CompoundType that its body has been parsed and
+ * that no more {@link #addField} operations will be made.
+ * <p>
+ * If {@code evalStructTypeName} is {@code true}, {@link #evalStructTypeName()} is performed.
+ * </p>
+ * @throws IllegalStateException If called twice.
+ */
+ public void setBodyParsed(final boolean evalStructTypeName) throws IllegalStateException {
+ if (bodyParsed) {
+ throw new IllegalStateException("Body of this CompoundType has been already closed");
+ }
bodyParsed = true;
+ if( evalStructTypeName ) {
+ evalStructTypeName();
+ }
+ }
+ public boolean isBodyParsed() { return bodyParsed; }
+ /**
+ * {@link #getName() name} is set to {@link #getStructName() struct-name},
+ * which promotes this instance for emission by its struct-name.
+ */
+ public Type evalStructTypeName() {
+ if( null == getName() ) {
+ setName(structName);
+ }
+ return this;
}
/** Indicates whether this type was declared as a struct. */
@@ -169,8 +231,9 @@ public abstract class CompoundType extends MemoryLayoutType implements Cloneable
@Override
public String toString() {
final String cvAttributesString = getCVAttributesString();
- if (getName() != null) {
- return cvAttributesString + getName();
+ final String cname = getCName();
+ if ( null != cname ) {
+ return cvAttributesString + cname;
} else if (getStructName() != null) {
return cvAttributesString + "struct " + getStructName();
} else {
diff --git a/src/java/com/jogamp/gluegen/cgram/types/DoubleType.java b/src/java/com/jogamp/gluegen/cgram/types/DoubleType.java
index de42522..1e13701 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/DoubleType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/DoubleType.java
@@ -47,19 +47,28 @@ public class DoubleType extends PrimitiveType implements Cloneable {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) {
- return true;
- }
- if (arg == null || (!(arg instanceof DoubleType))) {
- return false;
- }
- return super.equals(arg);
+ public DoubleType asDouble() {
+ return this;
}
@Override
- public DoubleType asDouble() {
- return this;
+ protected int hashCodeImpl() {
+ return 0;
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type t) {
+ return true;
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ return 0;
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type t) {
+ return true;
}
@Override
diff --git a/src/java/com/jogamp/gluegen/cgram/types/EnumType.java b/src/java/com/jogamp/gluegen/cgram/types/EnumType.java
index 0b1193b..f0e71dc 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/EnumType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/EnumType.java
@@ -42,6 +42,8 @@ package com.jogamp.gluegen.cgram.types;
import java.util.ArrayList;
import java.util.NoSuchElementException;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
+
/** Describes enumerated types. Enumerations are like ints except that
they have a set of named values. */
@@ -49,10 +51,9 @@ public class EnumType extends IntType implements Cloneable {
private IntType underlyingType;
- private static class Enum {
-
- String name;
- long value;
+ private static class Enum implements TypeComparator.SemanticEqualityOp {
+ final String name;
+ final long value;
Enum(final String name, final long value) {
this.name = name;
@@ -66,6 +67,37 @@ public class EnumType extends IntType implements Cloneable {
long getValue() {
return value;
}
+
+ @Override
+ public int hashCode() {
+ // 31 * x == (x << 5) - x
+ final int hash = name.hashCode();
+ return ((hash << 5) - hash) + (int)(value ^ (value >>> 32));
+ }
+
+ @Override
+ public boolean equals(final Object arg) {
+ if (arg == this) {
+ return true;
+ } else if ( !(arg instanceof Enum) ) {
+ return false;
+ }
+ final Enum t = (Enum) arg;
+ return name.equals(t.name) &&
+ value == t.value;
+ }
+
+ @Override
+ public int hashCodeSemantics() {
+ return hashCode();
+ }
+
+ @Override
+ public boolean equalSemantics(final SemanticEqualityOp arg) {
+ return equals(arg);
+ }
+
+ public String toString() { return name+" = "+value; }
}
private ArrayList<Enum> enums;
@@ -98,17 +130,31 @@ public class EnumType extends IntType implements Cloneable {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) {
- return true;
- }
- if (arg == null || (!(arg instanceof EnumType))) {
- return false;
- }
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = underlyingType.hashCode();
+ return ((hash << 5) - hash) + TypeComparator.listsHashCode(enums);
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type arg) {
final EnumType t = (EnumType) arg;
- return (super.equals(arg)
- && underlyingType.equals(t.underlyingType)
- && listsEqual(enums, t.enums));
+ return underlyingType.equals(t.underlyingType) &&
+ TypeComparator.listsEqual(enums, t.enums);
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = underlyingType.hashCodeSemantics();
+ return ((hash << 5) - hash) + TypeComparator.listsHashCodeSemantics(enums);
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type arg) {
+ final EnumType t = (EnumType) arg;
+ return underlyingType.equalSemantics(t.underlyingType) &&
+ TypeComparator.listsEqualSemantics(enums, t.enums);
}
@Override
@@ -116,11 +162,14 @@ public class EnumType extends IntType implements Cloneable {
return this;
}
+ public Type getUnderlyingType() { return this.underlyingType; }
+
public void addEnum(final String name, final long val) {
if (enums == null) {
enums = new ArrayList<Enum>();
}
enums.add(new Enum(name, val));
+ clearCache();
}
/** Number of enumerates defined in this enum. */
@@ -169,12 +218,24 @@ public class EnumType extends IntType implements Cloneable {
final Enum e = enums.get(i);
if (e.getName().equals(name)) {
enums.remove(e);
+ clearCache();
return true;
}
}
return false;
}
+ public StringBuilder appendEnums(final StringBuilder sb, final boolean cr) {
+ for(int i=0; i<enums.size(); i++) {
+ sb.append(enums.get(i)).append(", ");
+ if( cr ) {
+ sb.append(String.format("%n"));
+ }
+ }
+ sb.append("}");
+ return sb;
+ }
+
@Override
public void visit(final TypeVisitor arg) {
super.visit(arg);
diff --git a/src/java/com/jogamp/gluegen/cgram/types/Field.java b/src/java/com/jogamp/gluegen/cgram/types/Field.java
index 858d81a..a8fc599 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/Field.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/Field.java
@@ -40,10 +40,11 @@
package com.jogamp.gluegen.cgram.types;
import com.jogamp.common.os.MachineDataInfo;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
/** Represents a field in a struct or union. */
-public class Field {
+public class Field implements SemanticEqualityOp {
private final String name;
private final Type type;
private SizeThunk offset;
@@ -56,21 +57,41 @@ public class Field {
@Override
public int hashCode() {
- return name.hashCode();
+ // 31 * x == (x << 5) - x
+ final int hash = 31 + ( null != name ? name.hashCode() : 0 );
+ return ((hash << 5) - hash) + type.hashCode();
}
@Override
public boolean equals(final Object arg) {
- if (arg == null || (!(arg instanceof Field))) {
+ if ( !(arg instanceof Field) ) {
return false;
}
final Field f = (Field) arg;
// Note: don't know how to examine offset any more since it's
// implemented in terms of code and they're not canonicalized
- return (((name != null && name.equals(f.name)) ||
- (name == null && f.name == null)) &&
- type.equals(f.type));
+ return ( ( name != null && name.equals(f.name) ) ||
+ ( name == null && f.name == null )
+ ) &&
+ type.equals(f.type);
+ }
+
+ @Override
+ public int hashCodeSemantics() {
+ return type.hashCodeSemantics();
+ }
+
+ @Override
+ public boolean equalSemantics(final SemanticEqualityOp arg) {
+ if ( !(arg instanceof Field) ) {
+ return false;
+ }
+
+ final Field f = (Field) arg;
+ // Note: don't know how to examine offset any more since it's
+ // implemented in terms of code and they're not canonicalized
+ return type.equalSemantics(f.type);
}
/** Name of this field in the containing data structure. */
diff --git a/src/java/com/jogamp/gluegen/cgram/types/FloatType.java b/src/java/com/jogamp/gluegen/cgram/types/FloatType.java
index d8b0b13..0428543 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/FloatType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/FloatType.java
@@ -48,18 +48,27 @@ public class FloatType extends PrimitiveType implements Cloneable {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) {
+ public FloatType asFloat() { return this; }
+
+ @Override
+ protected int hashCodeImpl() {
+ return 0;
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type t) {
return true;
- }
- if (arg == null || (!(arg instanceof FloatType))) {
- return false;
- }
- return super.equals(arg);
}
@Override
- public FloatType asFloat() { return this; }
+ protected int hashCodeSemanticsImpl() {
+ return 0;
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type t) {
+ return true;
+ }
@Override
Type newCVVariant(final int cvAttributes) {
diff --git a/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java b/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java
index d41f2fd..ee68b68 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/FunctionSymbol.java
@@ -38,6 +38,12 @@
*/
package com.jogamp.gluegen.cgram.types;
+import java.util.List;
+
+import com.jogamp.gluegen.cgram.types.AliasedSymbol.AliasedSymbolImpl;
+import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
+
/**
* Describes a function symbol, which includes the name and
@@ -51,20 +57,15 @@ package com.jogamp.gluegen.cgram.types;
* Deep comparison can be performed via {@link #isCompletelyEqual(Object o)};
* </p>
**/
-public class FunctionSymbol {
+public class FunctionSymbol extends AliasedSymbolImpl implements AliasedSemanticSymbol {
- private final String name;
private final FunctionType type;
public FunctionSymbol(final String name, final FunctionType type) {
- this.name = name;
+ super(name);
this.type = type;
}
- public String getName() {
- return name;
- }
-
/** Returns the type of this function. Do not add arguments to it
directly; use addArgument instead. */
public FunctionType getType() {
@@ -109,10 +110,10 @@ public class FunctionSymbol {
@Override
public int hashCode() {
- if (name == null) {
+ if (getName() == null) {
return 0;
}
- return name.hashCode();
+ return getName().hashCode();
}
@Override
@@ -120,25 +121,54 @@ public class FunctionSymbol {
if (arg == this) {
return true;
}
-
- if (arg == null || (!(arg instanceof FunctionSymbol))) {
+ if ( !(arg instanceof FunctionSymbol) ) {
return false;
}
-
final FunctionSymbol other = (FunctionSymbol) arg;
-
if (getName() == null && other.getName() != null) {
return false;
}
-
return getName().equals(other.getName());
}
+ @Override
+ public int hashCodeSemantics() {
+ return type.hashCodeSemantics();
+ }
+ @Override
+ public final boolean equalSemantics(final SemanticEqualityOp arg) {
+ if (arg == this) {
+ return true;
+ }
+ if ( !(arg instanceof FunctionSymbol) ) {
+ return false;
+ }
+ final FunctionSymbol other = (FunctionSymbol) arg;
+ return type.equalSemantics(other.type);
+ }
+
+
+ public static boolean containsExactly(final List<FunctionSymbol> l, final FunctionSymbol s) {
+ return exactIndexOf(l, s) >= 0;
+ }
+
+ public static int exactIndexOf(final List<FunctionSymbol> l, final FunctionSymbol s) {
+ final int size = l.size();
+ for (int i = 0; i < size; i++) {
+ final FunctionSymbol e = l.get(i);
+ if( null == s && null == e ||
+ s.equals( e ) && s.type.equals(e.type) ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
/**
* Compares the function type as well, since {@link #equals(Object)}
* and {@link #hashCode()} won't.
*/
- public boolean isCompletelyEqual(final Object arg) {
+ public boolean exactlyEqual(final Object arg) {
if( !this.equals(arg) ) {
return false;
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java b/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java
index 4b39a34..b0d16e1 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/FunctionType.java
@@ -41,6 +41,8 @@ package com.jogamp.gluegen.cgram.types;
import java.util.*;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
+
/** Describes a function type, used to model both function
declarations and (via PointerType) function pointers. */
public class FunctionType extends Type implements Cloneable {
@@ -67,17 +69,31 @@ public class FunctionType extends Type implements Cloneable {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) {
- return true;
- }
- if (arg == null || (!(arg instanceof FunctionType))) {
- return false;
- }
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = returnType.hashCode();
+ return ((hash << 5) - hash) + TypeComparator.listsHashCode(argumentTypes);
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type arg) {
+ final FunctionType t = (FunctionType) arg;
+ return returnType.equals(t.returnType) &&
+ TypeComparator.listsEqual(argumentTypes, t.argumentTypes);
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = returnType.hashCodeSemantics();
+ return ((hash << 5) - hash) + TypeComparator.listsHashCodeSemantics(argumentTypes);
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type arg) {
final FunctionType t = (FunctionType) arg;
- return (super.equals(arg)
- && returnType.equals(t.returnType)
- && listsEqual(argumentTypes, t.argumentTypes));
+ return returnType.equalSemantics(t.returnType) &&
+ TypeComparator.listsEqualSemantics(argumentTypes, t.argumentTypes);
}
@Override
@@ -115,10 +131,12 @@ public class FunctionType extends Type implements Cloneable {
}
argumentTypes.add(argumentType);
argumentNames.add(argumentName);
+ clearCache();
}
public void setArgumentName(final int i, final String name) {
argumentNames.set(i, name);
+ clearCache();
}
@Override
@@ -136,7 +154,7 @@ public class FunctionType extends Type implements Cloneable {
String toString(final String functionName, final String callingConvention, final boolean emitNativeTag, final boolean isPointer) {
final StringBuilder res = new StringBuilder();
- res.append(getReturnType());
+ res.append(getReturnType().getCName(true));
res.append(" ");
if (isPointer) {
res.append("(");
@@ -169,7 +187,7 @@ public class FunctionType extends Type implements Cloneable {
} else if (t.isArray()) {
res.append(t.asArray().toString(getArgumentName(i)));
} else {
- res.append(t);
+ res.append(t.getCName(true));
final String argumentName = getArgumentName(i);
if (argumentName != null) {
res.append(" ");
diff --git a/src/java/com/jogamp/gluegen/cgram/types/IntType.java b/src/java/com/jogamp/gluegen/cgram/types/IntType.java
index 3f8dddc..502fe2a 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/IntType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/IntType.java
@@ -55,20 +55,36 @@ public class IntType extends PrimitiveType implements Cloneable {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) {
- return true;
- }
- if (arg == null || (!(arg instanceof IntType))) {
- return false;
- }
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = 31 + ( unsigned ? 1 : 0 );
+ return ((hash << 5) - hash) + ( typedefedUnsigned ? 1 : 0 );
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type arg) {
+ final IntType t = (IntType) arg;
+ return unsigned == t.unsigned &&
+ typedefedUnsigned == t.typedefedUnsigned;
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ return hashCodeImpl();
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type arg) {
final IntType t = (IntType) arg;
- return (super.equals(arg) && (unsigned == t.unsigned));
+ return relaxedEqSem ||
+ ( unsigned == t.unsigned &&
+ typedefedUnsigned == t.typedefedUnsigned
+ );
}
@Override
- public void setName(final String name) {
- super.setName(name);
+ public void setTypedefName(final String name) {
+ super.setTypedefName(name);
typedefedUnsigned = unsigned;
}
@@ -89,7 +105,7 @@ public class IntType extends PrimitiveType implements Cloneable {
@Override
public String toString() {
- return getCVAttributesString() + ((isUnsigned() & (!typedefedUnsigned)) ? "unsigned " : "") + getName();
+ return getCVAttributesString() + ((isUnsigned() & (!typedefedUnsigned)) ? "unsigned " : "") + getCName();
}
@Override
diff --git a/src/java/com/jogamp/gluegen/cgram/types/MemoryLayoutType.java b/src/java/com/jogamp/gluegen/cgram/types/MemoryLayoutType.java
index 25d2d1d..fb8c86b 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/MemoryLayoutType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/MemoryLayoutType.java
@@ -36,6 +36,8 @@ public abstract class MemoryLayoutType extends Type {
}
public boolean isLayouted() { return isLayouted; }
- public void setLayouted() { isLayouted = true; }
+ public void setLayouted() {
+ isLayouted = true;
+ }
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/PointerType.java b/src/java/com/jogamp/gluegen/cgram/types/PointerType.java
index d1dfb17..c6496bb 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/PointerType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/PointerType.java
@@ -42,72 +42,68 @@ package com.jogamp.gluegen.cgram.types;
public class PointerType extends Type implements Cloneable {
private final Type targetType;
- private String computedName;
- private boolean hasTypedefedName;
- public PointerType(final SizeThunk size, final Type targetType, final int cvAttributes) {
+ public PointerType(final SizeThunk size, final Type targetType, final int cvAttributes, final String typedefedName) {
// can pass null for the final name parameter because the PointerType's getName()
// completely replaces superclass behavior
- this(size, targetType, cvAttributes, false, null);
- }
-
- private PointerType(final SizeThunk size, final Type targetType, final int cvAttributes, final boolean hasTypedefedName, final String typedefedName) {
super(targetType.getName() + " *", size, cvAttributes);
- this.hasTypedefedName = false;
this.targetType = targetType;
- if (hasTypedefedName) {
- setName(typedefedName);
+ if (null != typedefedName) {
+ setTypedefName(typedefedName);
}
}
@Override
- public int hashCode() {
- return targetType.hashCode();
+ protected int hashCodeImpl() {
+ return targetType.hashCode();
}
@Override
- public boolean equals(final Object arg) {
- if (arg == this) {
- return true;
- }
- if (arg == null || (!(arg instanceof PointerType))) {
- return false;
- }
+ protected boolean equalsImpl(final Type arg) {
final PointerType t = (PointerType) arg;
- // Note we ignore the name of this type (which might be a typedef
- // name) for comparison purposes because this is what allows
- // e.g. a newly-fabricated type "PIXELFORMATDESCRIPTOR *" to be
- // canonicalized to e.g. "LPPIXELFORMATDESCRIPTOR"
- return ((getSize() == t.getSize())
- && (getCVAttributes() == t.getCVAttributes())
- && targetType.equals(t.targetType));
+ return targetType.equals(t.targetType);
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ return targetType.hashCodeSemantics();
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type arg) {
+ final PointerType pt = (PointerType) arg;
+ return targetType.equalSemantics(pt.targetType);
}
@Override
- public void setName(final String name) {
- super.setName(name);
- hasTypedefedName = true;
+ public boolean hasName() {
+ if ( hasTypedefName() ) {
+ return super.hasName();
+ } else {
+ return targetType.hasName();
+ }
}
@Override
public String getName(final boolean includeCVAttrs) {
- if (hasTypedefedName) {
+ if ( hasTypedefName() ) {
return super.getName(includeCVAttrs);
+ } else if (!includeCVAttrs) {
+ return targetType.getName(includeCVAttrs) + " *";
} else {
- // Lazy computation of name due to lazy setting of compound type
- // names during parsing
- if (computedName == null) {
- computedName = (targetType.getName(includeCVAttrs) + " *").intern();
- }
- if (!includeCVAttrs) {
- return computedName;
- }
return targetType.getName(includeCVAttrs) + " * " + getCVAttributesString();
}
}
- public boolean hasTypedefedName() {
- return hasTypedefedName;
+ @Override
+ public String getCName(final boolean includeCVAttrs) {
+ if ( hasTypedefName() ) {
+ return super.getCName(includeCVAttrs);
+ } else if (!includeCVAttrs) {
+ return targetType.getCName(includeCVAttrs) + " *";
+ } else {
+ return targetType.getCName(includeCVAttrs) + " * " + getCVAttributesString();
+ }
}
@Override
@@ -115,6 +111,7 @@ public class PointerType extends Type implements Cloneable {
return this;
}
+ @Override
public Type getTargetType() {
return targetType;
}
@@ -137,13 +134,18 @@ public class PointerType extends Type implements Cloneable {
@Override
public String toString() {
- if (hasTypedefedName) {
- return super.getName(true);
+ if ( hasTypedefName() ) {
+ return super.getCName(true);
+ } else {
+ return toStringInt();
+ }
+ }
+ private String toStringInt() {
+ if (!targetType.isFunction()) {
+ return targetType.getCName(true) + " * " + getCVAttributesString();
} else {
- if (!targetType.isFunction()) {
- return targetType.toString() + " * " + getCVAttributesString();
- }
- return toString(null, null); // this is a pointer to an unnamed function
+ // return toString(null, null); // this is a pointer to an unnamed function
+ return ((FunctionType) targetType).toString(null /* functionName */, null /* callingConvention */, false, true);
}
}
@@ -165,6 +167,6 @@ public class PointerType extends Type implements Cloneable {
@Override
Type newCVVariant(final int cvAttributes) {
- return new PointerType(getSize(), targetType, cvAttributes, hasTypedefedName, (hasTypedefedName ? getName() : null));
+ return new PointerType(getSize(), targetType, cvAttributes, (hasTypedefName() ? getName() : null));
}
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/SizeThunk.java b/src/java/com/jogamp/gluegen/cgram/types/SizeThunk.java
index 9843d6b..7a9c62a 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/SizeThunk.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/SizeThunk.java
@@ -41,17 +41,25 @@
package com.jogamp.gluegen.cgram.types;
import com.jogamp.common.os.MachineDataInfo;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
/** Provides a level of indirection between the definition of a type's
size and the absolute value of this size. Necessary when
generating glue code for two different CPU architectures (e.g.,
32-bit and 64-bit) from the same internal representation of the
various types involved. */
-public abstract class SizeThunk implements Cloneable {
+public abstract class SizeThunk implements Cloneable, SemanticEqualityOp {
+ /* pp */ static boolean relaxedEqSem = false;
private final boolean fixedNativeSize;
+ public static void setRelaxedEqualSemanticsTest(final boolean v) {
+ relaxedEqSem = v;
+ }
+
// Private constructor because there are only a few of these
- private SizeThunk(final boolean fixedNativeSize) { this.fixedNativeSize = fixedNativeSize; }
+ private SizeThunk(final boolean fixedNativeSize) {
+ this.fixedNativeSize = fixedNativeSize;
+ }
@Override
public Object clone() {
@@ -67,6 +75,55 @@ public abstract class SizeThunk implements Cloneable {
public abstract long computeSize(MachineDataInfo machDesc);
public abstract long computeAlignment(MachineDataInfo machDesc);
+ @Override
+ public final int hashCode() {
+ final int hash = 0x02DEAD6F; // magic hash start
+ return ((hash << 5) - hash) + hashCodeImpl();
+ }
+ /* pp */ abstract int hashCodeImpl();
+
+ @Override
+ public final boolean equals(final Object arg) {
+ if (arg == this) {
+ return true;
+ } else if ( !(arg instanceof SizeThunk) ) {
+ return false;
+ } else {
+ final SizeThunk t = (SizeThunk) arg;
+ return hashCodeImpl() == t.hashCodeImpl();
+ }
+ }
+
+ @Override
+ public final int hashCodeSemantics() {
+ final int hash = 0x01DEAD5F; // magic hash start
+ return ((hash << 5) - hash) + hashCodeSemanticsImpl();
+ }
+ /* pp */ abstract int hashCodeSemanticsImpl();
+
+ @Override
+ public final boolean equalSemantics(final SemanticEqualityOp arg) {
+ if (arg == this) {
+ return true;
+ } else if ( !(arg instanceof SizeThunk) ) {
+ return false;
+ } else {
+ final SizeThunk t = (SizeThunk) arg;
+ return hashCodeSemanticsImpl() == t.hashCodeSemanticsImpl();
+ }
+ }
+
+ static final int magic_int08 = 0x00000010;
+ static final int magic_int16 = 0x00000012;
+ static final int magic_int32 = 0x00000014;
+ static final int magic_intxx = 0x00000016;
+ static final int magic_long64 = 0x00000020;
+ static final int magic_longxx = 0x00000022;
+ static final int magic_float32 = 0x00000030;
+ static final int magic_float64 = 0x00000032;
+ static final int magic_aptr64 = 0x00000040;
+ static final int magic_ops = 0x00010000;
+
public static final SizeThunk INT8 = new SizeThunk(true) {
@Override
public long computeSize(final MachineDataInfo machDesc) {
@@ -76,6 +133,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int8AlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 1; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_int32 : magic_int08; }
};
public static final SizeThunk INT16 = new SizeThunk(true) {
@@ -87,6 +148,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int16AlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 2; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_int32 : magic_int16; }
};
public static final SizeThunk INT32 = new SizeThunk(true) {
@@ -98,6 +163,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int32AlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 3; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_int32; }
};
public static final SizeThunk INTxx = new SizeThunk(false) {
@@ -109,6 +178,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.intAlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 4; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_int32 : magic_intxx; }
};
public static final SizeThunk LONG = new SizeThunk(false) {
@@ -120,6 +193,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.longAlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 5; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return relaxedEqSem ? magic_long64 : magic_longxx; }
};
public static final SizeThunk INT64 = new SizeThunk(true) {
@@ -131,6 +208,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.int64AlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 6; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_long64; }
};
public static final SizeThunk FLOAT = new SizeThunk(true) {
@@ -142,6 +223,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.floatAlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 7; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_float32; }
};
public static final SizeThunk DOUBLE = new SizeThunk(true) {
@@ -153,6 +238,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.doubleAlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 8; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_float64; }
};
public static final SizeThunk POINTER = new SizeThunk(false) {
@@ -164,6 +253,10 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return machDesc.pointerAlignmentInBytes();
}
+ @Override
+ protected int hashCodeImpl() { return 9; }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_aptr64; }
};
// Factory methods for performing certain limited kinds of
@@ -181,6 +274,15 @@ public abstract class SizeThunk implements Cloneable {
final long thunk2A = thunk2.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
+ @Override
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + 10;
+ hash = ((hash << 5) - hash) + ( null != thunk1 ? thunk1.hashCode() : 0 );
+ return ((hash << 5) - hash) + ( null != thunk2 ? thunk2.hashCode() : 0 );
+ }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_ops + 1; }
};
}
@@ -197,6 +299,15 @@ public abstract class SizeThunk implements Cloneable {
final long thunk2A = thunk2.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
+ @Override
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + 11;
+ hash = ((hash << 5) - hash) + ( null != thunk1 ? thunk1.hashCode() : 0 );
+ return ((hash << 5) - hash) + ( null != thunk2 ? thunk2.hashCode() : 0 );
+ }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_ops + 2; }
};
}
@@ -239,6 +350,15 @@ public abstract class SizeThunk implements Cloneable {
final long thunk2A = alignmentThunk.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
+ @Override
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + 12;
+ hash = ((hash << 5) - hash) + ( null != offsetThunk ? offsetThunk.hashCode() : 0 );
+ return ((hash << 5) - hash) + ( null != alignmentThunk ? alignmentThunk.hashCode() : 0 );
+ }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_ops + 3; }
};
}
@@ -255,6 +375,15 @@ public abstract class SizeThunk implements Cloneable {
final long thunk2A = thunk2.computeAlignment(machDesc);
return ( thunk1A > thunk2A ) ? thunk1A : thunk2A ;
}
+ @Override
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + 13;
+ hash = ((hash << 5) - hash) + ( null != thunk1 ? thunk1.hashCode() : 0 );
+ return ((hash << 5) - hash) + ( null != thunk2 ? thunk2.hashCode() : 0 );
+ }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_ops + 4; }
};
}
@@ -268,6 +397,14 @@ public abstract class SizeThunk implements Cloneable {
public long computeAlignment(final MachineDataInfo machDesc) {
return 1; // no alignment for constants
}
+ @Override
+ protected int hashCodeImpl() {
+ // 31 * x == (x << 5) - x
+ final int hash = 31 + 14;
+ return ((hash << 5) - hash) + constant;
+ }
+ @Override
+ protected int hashCodeSemanticsImpl() { return magic_ops + 5; }
};
}
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/StructType.java b/src/java/com/jogamp/gluegen/cgram/types/StructType.java
index 27099e9..4998484 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/StructType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/StructType.java
@@ -38,14 +38,6 @@ public class StructType extends CompoundType {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == null || !(arg instanceof StructType)) {
- return false;
- }
- return super.equals(arg);
- }
-
- @Override
public final boolean isStruct() { return true; }
@Override
public final boolean isUnion() { return false; }
@@ -54,6 +46,9 @@ public class StructType extends CompoundType {
Type newCVVariant(final int cvAttributes) {
final StructType t = new StructType(getName(), getSize(), cvAttributes, getStructName());
t.setFields(getFields());
+ if( hasTypedefName() ) {
+ t.setTypedefName( getName() );
+ }
return t;
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/Type.java b/src/java/com/jogamp/gluegen/cgram/types/Type.java
index 28ba6b4..cd48aa0 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/Type.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/Type.java
@@ -40,27 +40,45 @@
package com.jogamp.gluegen.cgram.types;
-import java.util.List;
-
import com.jogamp.common.os.MachineDataInfo;
+import com.jogamp.gluegen.GlueGen;
+import com.jogamp.gluegen.TypeConfig;
+import com.jogamp.gluegen.cgram.types.TypeComparator.SemanticEqualityOp;
/** Models a C type. Primitive types include int, float, and
double. All types have an associated name. Structs and unions are
modeled as "compound" types -- composed of fields of primitive or
other types. */
-public abstract class Type implements Cloneable {
-
+public abstract class Type implements Cloneable, SemanticEqualityOp {
+ public final boolean relaxedEqSem;
+ private final int cvAttributes;
private String name;
private SizeThunk size;
- private final int cvAttributes;
private int typedefedCVAttributes;
private boolean hasTypedefName;
+ private boolean hasCachedHash;
+ private int cachedHash;
+ private boolean hasCachedSemanticHash;
+ private int cachedSemanticHash;
protected Type(final String name, final SizeThunk size, final int cvAttributes) {
setName(name);
- this.size = size;
+ this.relaxedEqSem = TypeConfig.relaxedEqualSemanticsTest();
this.cvAttributes = cvAttributes;
- hasTypedefName = false;
+ this.size = size;
+ this.typedefedCVAttributes = 0;
+ this.hasTypedefName = false;
+ this.hasCachedHash = false;
+ this.cachedHash = 0;
+ this.hasCachedSemanticHash = false;
+ this.cachedSemanticHash = 0;
+ }
+
+ protected final void clearCache() {
+ cachedHash = 0;
+ hasCachedHash = false;
+ cachedSemanticHash = 0;
+ hasCachedHash = false;
}
@Override
@@ -72,14 +90,28 @@ public abstract class Type implements Cloneable {
}
}
+ public final boolean isAnonymous() { return null == name; }
+
+ public boolean hasName() { return null != name; }
+
+ /** Returns the name of this type. The returned string is suitable
+ for use as a type specifier for native C. Does not include any const/volatile
+ attributes. */
+ public final String getCName() { return getCName(false); }
+
+ /** Returns the name of this type, optionally including
+ const/volatile attributes. The returned string is suitable for
+ use as a type specifier for native C. */
+ public String getCName(final boolean includeCVAttrs) { return getName(includeCVAttrs); }
+
/** Returns the name of this type. The returned string is suitable
- for use as a type specifier. Does not include any const/volatile
+ for use as a type specifier for Java. Does not include any const/volatile
attributes. */
public final String getName() { return getName(false); }
/** Returns the name of this type, optionally including
const/volatile attributes. The returned string is suitable for
- use as a type specifier. */
+ use as a type specifier for Java. */
public String getName(final boolean includeCVAttrs) {
if (!includeCVAttrs) {
return name;
@@ -87,6 +119,18 @@ public abstract class Type implements Cloneable {
return getCVAttributesString() + name;
}
+ /**
+ * Returns a string representation of this type.
+ * The returned string is suitable for use as a type specifier for native C.
+ * It does contain an expanded description of structs/unions,
+ * hence may not be suitable for type declarations.
+ */
+ @Override
+ public String toString() {
+ return getCName(true);
+ }
+
+
private void append(final StringBuilder sb, final String val, final boolean prepComma) {
if( prepComma ) {
sb.append(", ");
@@ -98,15 +142,30 @@ public abstract class Type implements Cloneable {
final StringBuilder sb = new StringBuilder();
boolean prepComma = false;
sb.append("CType[");
+ sb.append("(").append(getClass().getSimpleName()).append(") ");
+ if( hasTypedefName() ) {
+ sb.append("typedef ");
+ }
if( null != name ) {
- append(sb, "'"+name+"'", prepComma); prepComma=true;
+ sb.append("'").append(name).append("'");
} else {
- append(sb, "ANON", prepComma); prepComma=true;
+ sb.append("ANON");
}
- if( hasTypedefName() ) {
- sb.append(" (typedef)");
+ final Type targetType = getTargetType();
+ if( null != targetType && this != targetType ) {
+ sb.append(" -> ");
+ if (!targetType.isFunction()) {
+ sb.append(targetType.toString() + " * " + getCVAttributesString());
+ } else {
+ sb.append(((FunctionType) targetType).toString(null /* functionName */, null /* callingConvention */, false, true));
+ }
+ }
+ if( GlueGen.debug() ) {
+ // sb.append(", o=0x"+Integer.toHexString(objHash())+" h=0x"+Integer.toHexString(hashCode()));
+ sb.append(", o=0x"+Integer.toHexString(objHash()));
}
- append(sb, "size ", prepComma); prepComma=true;
+ sb.append(", size ");
+ prepComma=true;
if( null != size ) {
final long mdSize;
{
@@ -137,14 +196,17 @@ public abstract class Type implements Cloneable {
append(sb, "bit", prepComma); prepComma=true;
}
if( isCompound() ) {
- sb.append("struct{").append(asCompound().getNumFields());
+ sb.append("struct{").append(asCompound().getStructName()).append(": ").append(asCompound().getNumFields());
append(sb, "}", prepComma); prepComma=true;
}
if( isDouble() ) {
append(sb, "double", prepComma); prepComma=true;
}
if( isEnum() ) {
- append(sb, "enum", prepComma); prepComma=true;
+ final EnumType eT = asEnum();
+ sb.append("enum ").append(" [").append(eT.getUnderlyingType()).append("] {").append(eT.getNumEnumerates()).append(": ");
+ eT.appendEnums(sb, false);
+ prepComma=true;
}
if( isFloat() ) {
append(sb, "float", prepComma); prepComma=true;
@@ -164,20 +226,33 @@ public abstract class Type implements Cloneable {
sb.append("]]");
return sb.toString();
}
+ private final int objHash() { return super.hashCode(); }
- /** Set the name of this type; used for handling typedefs. */
- public void setName(final String name) {
+
+ protected final void setName(final String name) {
if (name == null) {
this.name = name;
} else {
this.name = name.intern();
}
+ clearCache();
+ }
+
+ /** Set the name of this type; used for handling typedefs. */
+ public void setTypedefName(final String name) {
+ setName(name);
// Capture the const/volatile attributes at the time of typedef so
// we don't redundantly repeat them in the CV attributes string
typedefedCVAttributes = cvAttributes;
hasTypedefName = true;
}
+ /** Indicates whether {@link #setTypedefName(String)} has been called on this type,
+ indicating that it already has a typedef name. */
+ public final boolean hasTypedefName() {
+ return hasTypedefName;
+ }
+
/** SizeThunk which computes size of this type in bytes. */
public SizeThunk getSize() { return size; }
/** Size of this type in bytes according to the given MachineDataInfo. */
@@ -189,7 +264,10 @@ public abstract class Type implements Cloneable {
return thunk.computeSize(machDesc);
}
/** Set the size of this type; only available for CompoundTypes. */
- void setSize(final SizeThunk size) { this.size = size; }
+ void setSize(final SizeThunk size) {
+ this.size = size;
+ clearCache();
+ }
/** Casts this to a BitType or returns null if not a BitType. */
public BitType asBit() { return null; }
@@ -249,43 +327,92 @@ public abstract class Type implements Cloneable {
/** Hashcode for Types. */
@Override
- public int hashCode() {
- if (name == null) {
- return 0;
- }
-
- if (cvAttributes != 0) {
- final String nameWithAttribs = name + cvAttributes;
- return nameWithAttribs.hashCode();
+ public final int hashCode() {
+ if( !hasCachedHash ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + ( hasTypedefName ? 1 : 0 );
+ hash = ((hash << 5) - hash) + ( null != size ? size.hashCode() : 0 );
+ hash = ((hash << 5) - hash) + cvAttributes;
+ hash = ((hash << 5) - hash) + ( null != name ? name.hashCode() : 0 );
+ if( !hasTypedefName ) {
+ hash = ((hash << 5) - hash) + hashCodeImpl();
+ }
+ cachedHash = hash;
+ hasCachedHash = true;
}
- return name.hashCode();
+ return cachedHash;
}
+ protected abstract int hashCodeImpl();
/**
- * Equality test for Types.
+ * Equality test for Types inclusive its given {@link #getName() name}.
*/
@Override
- public boolean equals(final Object arg) {
+ public final boolean equals(final Object arg) {
if (arg == this) {
- return true;
+ return true;
+ } else if ( !getClass().isInstance(arg) ) { // implies null == arg || !(arg instanceof Type)
+ return false;
+ } else {
+ final Type t = (Type)arg;
+ if( hasTypedefName == t.hasTypedefName &&
+ ( ( null != size && size.equals(t.size) ) ||
+ ( null == size && null == t.size )
+ ) &&
+ cvAttributes == t.cvAttributes &&
+ ( null == name ? null == t.name : name.equals(t.name) )
+ )
+ {
+ if( !hasTypedefName ) {
+ return equalsImpl(t);
+ } else {
+ return true;
+ }
+ } else {
+ return false;
+ }
}
+ }
+ protected abstract boolean equalsImpl(final Type t);
- if ( !(arg instanceof Type) ) {
- return false;
+ @Override
+ public final int hashCodeSemantics() {
+ if( !hasCachedSemanticHash ) {
+ // 31 * x == (x << 5) - x
+ int hash = 31 + ( null != size ? size.hashCodeSemantics() : 0 );
+ if( !relaxedEqSem ) {
+ hash = ((hash << 5) - hash) + cvAttributes;
+ }
+ hash = ((hash << 5) - hash) + hashCodeSemanticsImpl();
+ cachedSemanticHash = hash;
+ hasCachedSemanticHash = true;
}
-
- final Type t = (Type)arg;
- return size == t.size && cvAttributes == t.cvAttributes &&
- ( null == name ? null == t.name : name.equals(t.name) ) ;
+ return cachedSemanticHash;
}
+ protected abstract int hashCodeSemanticsImpl();
- /** Returns a string representation of this type. This string is not
- necessarily suitable for use as a type specifier; for example,
- it will contain an expanded description of structs/unions. */
@Override
- public String toString() {
- return getName(true);
+ public final boolean equalSemantics(final SemanticEqualityOp arg) {
+ if (arg == this) {
+ return true;
+ } else if ( !(arg instanceof Type) ||
+ !getClass().isInstance(arg) ) { // implies null == arg
+ return false;
+ } else {
+ final Type t = (Type) arg;
+ if( ( ( null != size && size.equalSemantics(t.size) ) ||
+ ( null == size && null == t.size )
+ ) &&
+ ( relaxedEqSem || cvAttributes == t.cvAttributes )
+ )
+ {
+ return equalSemanticsImpl(t);
+ } else {
+ return false;
+ }
+ }
}
+ protected abstract boolean equalSemanticsImpl(final Type t);
/** Visit this type and all of the component types of this one; for
example, the return type and argument types of a FunctionType. */
@@ -319,12 +446,6 @@ public abstract class Type implements Cloneable {
const/volatile attributes. */
abstract Type newCVVariant(int cvAttributes);
- /** Indicates whether setName() has been called on this type,
- indicating that it already has a typedef name. */
- public boolean hasTypedefName() {
- return hasTypedefName;
- }
-
/** Helper method for determining how many pointer indirections this
type represents (i.e., "void **" returns 2). Returns 0 if this
type is not a pointer type. */
@@ -358,8 +479,10 @@ public abstract class Type implements Cloneable {
return this;
}
- /** Helper routine for list equality comparison */
- static <C> boolean listsEqual(final List<C> a, final List<C> b) {
- return ((a == null && b == null) || (a != null && b != null && a.equals(b)));
+ /**
+ * Helper method to returns the target type of this type, in case another type is being referenced.
+ */
+ public Type getTargetType() {
+ return this;
}
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/TypeComparator.java b/src/java/com/jogamp/gluegen/cgram/types/TypeComparator.java
new file mode 100644
index 0000000..850d953
--- /dev/null
+++ b/src/java/com/jogamp/gluegen/cgram/types/TypeComparator.java
@@ -0,0 +1,143 @@
+/**
+ * Copyright 2015 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package com.jogamp.gluegen.cgram.types;
+
+import java.util.List;
+
+public class TypeComparator {
+ /**
+ * Supports semantic equality and hash functions for types.
+ */
+ public static interface SemanticEqualityOp {
+ /**
+ * Semantic hashcode for Types exclusive its given {@link #getName() name}.
+ * @see #equalSemantics(SemanticEqualityOp)
+ */
+ int hashCodeSemantics();
+
+ /**
+ * Semantic equality test for Types exclusive its given {@link #getName() name}.
+ * @see #hashCodeSemantics()
+ */
+ boolean equalSemantics(final SemanticEqualityOp arg);
+ }
+ /**
+ * Supports common interface for {@link SemanticEqualityOp} and {@link AliasedSymbol}.
+ */
+ public static interface AliasedSemanticSymbol extends AliasedSymbol, SemanticEqualityOp { };
+
+ /** Helper routine for list equality comparison*/
+ static <C> boolean listsEqual(final List<C> a, final List<C> b) {
+ if( a == null ) {
+ if( null != b ) {
+ return false;
+ } else {
+ return true; // elements equal, i.e. both null
+ }
+ }
+ if( b != null && a.size() == b.size() ) {
+ final int count = a.size();
+ for(int i=0; i<count; i++) {
+ final C ac = a.get(i);
+ final C bc = b.get(i);
+ if( null == ac ) {
+ if( null != bc ) {
+ return false;
+ } else {
+ continue; // elements equal, i.e. both null
+ }
+ }
+ if( !ac.equals(bc) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /** Helper routine for list hashCode */
+ static <C extends SemanticEqualityOp> int listsHashCode(final List<C> a) {
+ if( a == null ) {
+ return 0;
+ } else {
+ final int count = a.size();
+ int hash = 31;
+ for(int i=0; i<count; i++) {
+ final C ac = a.get(i);
+ hash = ((hash << 5) - hash) + ( null != ac ? ac.hashCode() : 0 );
+ }
+ return hash;
+ }
+ }
+
+ /** Helper routine for list semantic equality comparison*/
+ static <C extends SemanticEqualityOp> boolean listsEqualSemantics(final List<C> a, final List<C> b) {
+ if( a == null ) {
+ if( null != b ) {
+ return false;
+ } else {
+ return true; // elements equal, i.e. both null
+ }
+ }
+ if( b != null && a.size() == b.size() ) {
+ final int count = a.size();
+ for(int i=0; i<count; i++) {
+ final C ac = a.get(i);
+ final C bc = b.get(i);
+ if( null == ac ) {
+ if( null != bc ) {
+ return false;
+ } else {
+ continue; // elements equal, i.e. both null
+ }
+ }
+ if( !ac.equalSemantics(bc) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /** Helper routine for list hashCode */
+ static <C extends SemanticEqualityOp> int listsHashCodeSemantics(final List<C> a) {
+ if( a == null ) {
+ return 0;
+ } else {
+ final int count = a.size();
+ int hash = 31;
+ for(int i=0; i<count; i++) {
+ final C ac = a.get(i);
+ hash = ((hash << 5) - hash) + ( null != ac ? ac.hashCodeSemantics() : 0 );
+ }
+ return hash;
+ }
+ }
+}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/TypeDictionary.java b/src/java/com/jogamp/gluegen/cgram/types/TypeDictionary.java
index cd03388..c1cfcdf 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/TypeDictionary.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/TypeDictionary.java
@@ -41,6 +41,9 @@ package com.jogamp.gluegen.cgram.types;
import java.util.*;
+import com.jogamp.gluegen.GlueGen;
+import com.jogamp.gluegen.JavaConfiguration;
+
/** Utility class for recording names of typedefs and structs. */
@@ -63,6 +66,38 @@ public class TypeDictionary {
return map.get(name);
}
+ public List<Type> getEqualSemantics(final Type s, final JavaConfiguration cfg, final boolean skipOpaque) {
+ final List<Type> res = new ArrayList<Type>();
+ if( !skipOpaque || null == cfg.typeInfo(s) ) {
+ final Set<Map.Entry<String, Type>> entries = entrySet();
+ for(final Iterator<Map.Entry<String, Type>> iter = entries.iterator(); iter.hasNext(); ) {
+ final Map.Entry<String, Type> entry = iter.next();
+ final Type t = entry.getValue();
+ if( s.equalSemantics(t) ) {
+ if( !skipOpaque || null == cfg.typeInfo(t) ) {
+ if( GlueGen.debug() ) {
+ System.err.println(" tls["+res.size()+"]: -> "+entry.getKey()+" -> "+t.getDebugString());
+ }
+ res.add(t);
+ }
+ }
+ }
+ }
+ return res;
+ }
+ public Type getEqualSemantics1(final Type s, final JavaConfiguration cfg, final boolean skipOpaque) {
+ final List<Type> tls = getEqualSemantics(s, cfg, skipOpaque);
+ if( tls.size() > 0 ) {
+ final Type res = tls.get(0);
+ if( GlueGen.debug() ) {
+ System.err.println(" tls.0: "+res.getDebugString());
+ }
+ return res;
+ } else {
+ return null;
+ }
+ }
+
//this method is broken
/**
* Get the names that correspond to the given type. There will be more than
diff --git a/src/java/com/jogamp/gluegen/cgram/types/UnionType.java b/src/java/com/jogamp/gluegen/cgram/types/UnionType.java
index 99d2fed..6ccc4a2 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/UnionType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/UnionType.java
@@ -38,14 +38,6 @@ public class UnionType extends CompoundType {
}
@Override
- public boolean equals(final Object arg) {
- if (arg == null || !(arg instanceof UnionType)) {
- return false;
- }
- return super.equals(arg);
- }
-
- @Override
public final boolean isStruct() { return false; }
@Override
public final boolean isUnion() { return true; }
@@ -54,6 +46,9 @@ public class UnionType extends CompoundType {
Type newCVVariant(final int cvAttributes) {
final UnionType t = new UnionType(getName(), getSize(), cvAttributes, getStructName());
t.setFields(getFields());
+ if( hasTypedefName() ) {
+ t.setTypedefName( getName() );
+ }
return t;
}
diff --git a/src/java/com/jogamp/gluegen/cgram/types/VoidType.java b/src/java/com/jogamp/gluegen/cgram/types/VoidType.java
index 2e1f069..f6adaac 100644
--- a/src/java/com/jogamp/gluegen/cgram/types/VoidType.java
+++ b/src/java/com/jogamp/gluegen/cgram/types/VoidType.java
@@ -58,4 +58,24 @@ public class VoidType extends Type implements Cloneable {
Type newCVVariant(final int cvAttributes) {
return new VoidType(getName(), cvAttributes);
}
+
+ @Override
+ protected int hashCodeImpl() {
+ return 0;
+ }
+
+ @Override
+ protected boolean equalsImpl(final Type t) {
+ return true;
+ }
+
+ @Override
+ protected int hashCodeSemanticsImpl() {
+ return 0;
+ }
+
+ @Override
+ protected boolean equalSemanticsImpl(final Type t) {
+ return true;
+ }
}
diff --git a/src/java/com/jogamp/gluegen/pcpp/PCPP.java b/src/java/com/jogamp/gluegen/pcpp/PCPP.java
index aca7b14..72b46a1 100644
--- a/src/java/com/jogamp/gluegen/pcpp/PCPP.java
+++ b/src/java/com/jogamp/gluegen/pcpp/PCPP.java
@@ -57,6 +57,9 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
+
+import com.jogamp.gluegen.Logging;
+
import static java.util.logging.Level.*;
/** A minimal pseudo-C-preprocessor designed in particular to preserve
@@ -65,7 +68,7 @@ import static java.util.logging.Level.*;
public class PCPP {
- private static final Logger LOG = Logger.getLogger(PCPP.class.getPackage().getName());
+ private final Logger LOG;
/** Map containing the results of #define statements. We must
evaluate certain very simple definitions (to properly handle
@@ -86,6 +89,7 @@ public class PCPP {
private final boolean enableCopyOutput2Stderr;
public PCPP(final List<String> includePaths, final boolean debug, final boolean copyOutput2Stderr) {
+ LOG = Logging.getLogger(PCPP.class.getPackage().getName());
this.includePaths = includePaths;
setOut(System.out);
enableDebugPrint = debug;
diff --git a/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java b/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java
index 5c059c9..abbe521 100644
--- a/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java
+++ b/src/java/com/jogamp/gluegen/procaddress/ProcAddressCMethodBindingEmitter.java
@@ -42,7 +42,9 @@ package com.jogamp.gluegen.procaddress;
import com.jogamp.gluegen.CMethodBindingEmitter;
import com.jogamp.gluegen.MethodBinding;
import com.jogamp.gluegen.JavaType;
+
import java.io.*;
+
import com.jogamp.gluegen.cgram.types.*;
public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter {
@@ -55,8 +57,11 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter {
private static final String procAddressJavaTypeName = JavaType.createForClass(Long.TYPE).jniTypeName();
private ProcAddressEmitter emitter;
- public ProcAddressCMethodBindingEmitter(final CMethodBindingEmitter methodToWrap, final boolean callThroughProcAddress,
- final boolean needsLocalTypedef, final String localTypedefCallingConvention, final ProcAddressEmitter emitter) {
+ public ProcAddressCMethodBindingEmitter(final CMethodBindingEmitter methodToWrap,
+ final boolean callThroughProcAddress,
+ final boolean needsLocalTypedef,
+ final String localTypedefCallingConvention,
+ final ProcAddressEmitter emitter) {
super(
new MethodBinding(methodToWrap.getBinding()) {
@@ -76,7 +81,8 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter {
methodToWrap.getIsJavaMethodStatic(),
true,
methodToWrap.forIndirectBufferAndArrayImplementation(),
- methodToWrap.getMachineDataInfo()
+ methodToWrap.getMachineDataInfo(),
+ emitter.getConfiguration()
);
if (methodToWrap.getReturnValueCapacityExpression() != null) {
@@ -124,7 +130,7 @@ public class ProcAddressCMethodBindingEmitter extends CMethodBindingEmitter {
// We (probably) didn't get a typedef for this function
// pointer type in the header file; the user requested that we
// forcibly generate one. Here we force the emission of one.
- final PointerType funcPtrType = new PointerType(null, cSym.getType(), 0);
+ final PointerType funcPtrType = new PointerType(null, cSym.getType(), 0, null);
// Just for safety, emit this name slightly differently than
// the mangling would otherwise produce
funcPointerTypedefName = "_local_" + funcPointerTypedefName;
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java
index 3b1857d..4564019 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/BaseClass.java
@@ -80,6 +80,7 @@ public class BaseClass extends SingletonJunitCase {
int i;
final long context = 0;
LongBuffer lb=null;
+ ByteBuffer bb=null;
final IntBuffer ib=null;
final long[] larray = null;
final int larray_offset = 0;
@@ -89,10 +90,38 @@ public class BaseClass extends SingletonJunitCase {
final int iarray_offset = 0;
long result = 0;
long l = result;
+ ShortBlob sb = null;
+ Int32Struct i32s = null;
+ AnonBlob ab = null;
+ PointerBuffer pb=null;
{
- final ByteBuffer bb = binding.createAPtrBlob();
- PointerBuffer pb = safeByteBuffer2PointerBuffer(bb, 1);
+ l = binding.testXID(l);
+ l = binding.testXID_2(l);
+
+ bb = binding.testAnonBuffer(bb);
+
+ sb = binding.testShortBlob0(sb);
+ sb = binding.testShortBlob1(sb);
+ sb = binding.testShortBlob2(sb);
+ sb = binding.testShortBlob3(sb);
+ sb = binding.testShortBlob4(sb);
+
+ i32s = binding.testInt32Struct(i32s);
+
+ ab = binding.testCreateAnonBlob();
+ binding.testDestroyAnonBlob(ab);
+
+ l = binding.testCreateAnonBlob2();
+ binding.testDestroyAnonBlob2(l);
+
+ lb = binding.testFooPtr(larray, 0);
+ lb = binding.testFooPtr(lb);
+ }
+
+ {
+ bb = binding.createAPtrBlob();
+ pb = safeByteBuffer2PointerBuffer(bb, 1);
long bb2A = binding.getAPtrAddress(bb);
bb2A = bb2A - 0; // avoid warning
@@ -119,9 +148,6 @@ public class BaseClass extends SingletonJunitCase {
binding.releaseAPtrBlob(bb);
}
- final ByteBuffer bb=null;
- PointerBuffer pb=null;
-
result = binding.arrayTestInt32(context, ib);
result = binding.arrayTestInt32(context, iarray, iarray_offset);
@@ -629,6 +655,57 @@ public class BaseClass extends SingletonJunitCase {
Assert.assertTrue("Wrong result: 0x"+Long.toHexString(pb.get(i))+"+1 != 0x"+Long.toHexString(pb2.get(i)), (pb.get(i)+1)==pb2.get(i));
}
}
+
+ {
+ final long l0 = 0xAAFFEE;
+ final long l1 = binding.testXID(l0);
+ final long l2 = binding.testXID_2(l0);
+ Assert.assertEquals(l0, l1);
+ Assert.assertEquals(l0, l2);
+
+ final ByteBuffer bb = Buffers.newDirectByteBuffer(PointerBuffer.ELEMENT_SIZE);
+ for(int j=0; j<bb.limit(); j++) {
+ bb.put(j, (byte)(0xAA+j));
+ }
+ final ByteBuffer bbOut = binding.testAnonBuffer(bb);
+ Assert.assertEquals(bb, bbOut);
+
+ final ShortBlob sb = ShortBlob.create();
+ sb.setB1((byte)0xAA);
+ sb.setB2((byte)0xEE);
+ final ShortBlob sb0 = binding.testShortBlob0(sb);
+ final ShortBlob sb1 = binding.testShortBlob1(sb);
+ final ShortBlob sb2 = binding.testShortBlob2(sb);
+ final ShortBlob sb3 = binding.testShortBlob3(sb);
+ final ShortBlob sb4 = binding.testShortBlob4(sb);
+ Assert.assertEquals(sb.getBuffer(), sb0.getBuffer());
+ Assert.assertEquals(sb.getBuffer(), sb1.getBuffer());
+ Assert.assertEquals(sb.getBuffer(), sb2.getBuffer());
+ Assert.assertEquals(sb.getBuffer(), sb3.getBuffer());
+ Assert.assertEquals(sb.getBuffer(), sb4.getBuffer());
+
+ final Int32Struct i32s = Int32Struct.create();
+ i32s.setB1((byte)0x02);
+ i32s.setB2((byte)0x12);
+ i32s.setB3((byte)0x22);
+ i32s.setB4((byte)0x32);
+ final Int32Struct i32s0 = binding.testInt32Struct(i32s);
+ Assert.assertEquals(i32s.getBuffer(), i32s0.getBuffer());
+
+ final AnonBlob ab = binding.testCreateAnonBlob();
+ binding.testDestroyAnonBlob(ab);
+
+ final long ab2 = binding.testCreateAnonBlob2();
+ binding.testDestroyAnonBlob2(ab2);
+
+ final long[] foo = new long[] { 0x1122334455667788L };
+ final LongBuffer fooLB = Buffers.newDirectLongBuffer(foo);
+ final LongBuffer foo1Out = binding.testFooPtr(fooLB);
+ Assert.assertEquals(fooLB, foo1Out);
+ final LongBuffer foo2Out = binding.testFooPtr(foo, 0);
+ Assert.assertEquals(fooLB, foo2Out);
+ }
+
}
public void chapter04TestPointerBuffer(final Bindingtest1 binding) throws Exception {
@@ -1123,14 +1200,14 @@ public class BaseClass extends SingletonJunitCase {
Assert.assertEquals(3, model.getIntxxPointerCustomLenVal());
Assert.assertEquals(3, model.getInt32PointerCustomLenVal());
- Assert.assertEquals(3, model.getInt32ArrayFixedLenArrayLength());
- Assert.assertEquals(3, model.getStructArrayFixedLenArrayLength());
+ Assert.assertEquals(3, TK_ModelConst.getInt32ArrayFixedLenArrayLength());
+ Assert.assertEquals(3, TK_ModelConst.getStructArrayFixedLenArrayLength());
Assert.assertEquals(3, model.getStructPointerCustomLenVal());
// field: int32ArrayFixedLen
// CType['int32_t *', size [fixed false, lnx64 12], [array*1]], with array length of 3
{
- final int size = model.getInt32ArrayFixedLenArrayLength();
+ final int size = TK_ModelConst.getInt32ArrayFixedLenArrayLength();
final int[] all = model.getInt32ArrayFixedLen(0, new int[size]);
final IntBuffer allB = model.getInt32ArrayFixedLen();
Assert.assertEquals(size, allB.limit());
@@ -1170,7 +1247,7 @@ public class BaseClass extends SingletonJunitCase {
// field: mat4x4
// CType['float * *', size [fixed false, lnx64 64], [array*2]], with array length of <code>4*4</code> */
{
- Assert.assertEquals(4*4, model.getMat4x4ArrayLength());
+ Assert.assertEquals(4*4, TK_ModelConst.getMat4x4ArrayLength());
final FloatBuffer mat4x4 = model.getMat4x4();
Assert.assertEquals(4*4, mat4x4.limit());
for(int i=0; i<4; i++) {
@@ -1185,7 +1262,7 @@ public class BaseClass extends SingletonJunitCase {
// field: structArrayFixedLen
// field: CType['TK_Dimension *', size [fixed false, lnx64 48], [array*1]], with array length of 3
{
- final int size = model.getStructArrayFixedLenArrayLength();
+ final int size = TK_ModelConst.getStructArrayFixedLenArrayLength();
final TK_Dimension[] all = model.getStructArrayFixedLen(0, new TK_Dimension[size]);
for(int i=0; i<size; i++) {
Assert.assertEquals(51 + i * 10, all[i].getX());
@@ -1236,7 +1313,7 @@ public class BaseClass extends SingletonJunitCase {
assertAPTR(surfaceContext, model.getCtx());
{
- Assert.assertEquals(12, model.getModelNameArrayFixedLenArrayLength());
+ Assert.assertEquals(12, TK_ModelConst.getModelNameArrayFixedLenArrayLength());
final ByteBuffer bb = model.getModelNameArrayFixedLen();
Assert.assertEquals(12, bb.limit());
@@ -1296,14 +1373,14 @@ public class BaseClass extends SingletonJunitCase {
Assert.assertEquals(3, model.getIntxxPointerCustomLenVal());
Assert.assertEquals(3, model.getInt32PointerCustomLenVal());
- Assert.assertEquals(3, model.getInt32ArrayFixedLenArrayLength());
- Assert.assertEquals(3, model.getStructArrayFixedLenArrayLength());
+ Assert.assertEquals(3, TK_ModelMutable.getInt32ArrayFixedLenArrayLength());
+ Assert.assertEquals(3, TK_ModelMutable.getStructArrayFixedLenArrayLength());
Assert.assertEquals(3, model.getStructPointerCustomLenVal());
// field: int32ArrayFixedLen
// CType['int32_t *', size [fixed false, lnx64 12], [array*1]], with array length of 3
{
- final int size = model.getInt32ArrayFixedLenArrayLength();
+ final int size = TK_ModelMutable.getInt32ArrayFixedLenArrayLength();
{
final int[] values = new int[] { 1, 2, 3 };
model.setInt32ArrayFixedLen(0, values);
@@ -1385,7 +1462,7 @@ public class BaseClass extends SingletonJunitCase {
model.setMat4x4(2*4, new float[] { 31, 32, 33, 34 } );
model.setMat4x4(3*4, new float[] { 41, 42, 43, 44 } );
- Assert.assertEquals(4*4, model.getMat4x4ArrayLength());
+ Assert.assertEquals(4*4, TK_ModelMutable.getMat4x4ArrayLength());
final FloatBuffer mat4x4 = model.getMat4x4();
Assert.assertEquals(4*4, mat4x4.limit());
for(int i=0; i<4; i++) {
@@ -1400,7 +1477,7 @@ public class BaseClass extends SingletonJunitCase {
// field: structArrayFixedLen
// field: CType['TK_Dimension *', size [fixed false, lnx64 48], [array*1]], with array length of 3
{
- final int size = model.getStructArrayFixedLenArrayLength();
+ final int size = TK_ModelMutable.getStructArrayFixedLenArrayLength();
{
for(int i=0; i<size; i++) {
final TK_Dimension d = TK_Dimension.create();
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg
index 8e41aae..7210940 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1-common.cfg
@@ -32,10 +32,17 @@ ReturnValueCapacity typeTestAnonPointer ARRAY_SIZE * sizeof(MYAPIConfig)
Opaque long MYAPIConfig
Opaque boolean Bool
+Opaque long XID
+# For 'struct _AnonBlob2*', we need to drop 'struct'
+Opaque long _AnonBlob2*
+
CustomCCode #include "test1.h"
Opaque long TK_Context
+RenameJavaSymbol DEFINE_01_EXT DEFINE_01
+RenameJavaSymbol testXID_EXT testXID
+
StructPackage TK_Dimension com.jogamp.gluegen.test.junit.generation
EmitStruct TK_Dimension
StructPackage TK_DimensionPair com.jogamp.gluegen.test.junit.generation
@@ -96,6 +103,9 @@ Import java.nio.*
Import java.util.*
Import com.jogamp.common.os.*
Import com.jogamp.common.nio.*
+Import com.jogamp.gluegen.test.junit.generation.ShortBlob
+Import com.jogamp.gluegen.test.junit.generation.Int32Struct
+Import com.jogamp.gluegen.test.junit.generation.AnonBlob
Import com.jogamp.gluegen.test.junit.generation.TK_Surface
Import com.jogamp.gluegen.test.junit.generation.TK_Dimension
Import com.jogamp.gluegen.test.junit.generation.TK_DimensionPair
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c
index 9999274..894dc10 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.c
@@ -8,6 +8,52 @@
#define DEBUG 1
+MYAPI XID MYAPIENTRY testXID(XID v) {
+ return v;
+}
+MYAPI XID_2 MYAPIENTRY testXID_2(XID_2 v) {
+ return v;
+}
+MYAPI AnonBuffer MYAPIENTRY testAnonBuffer(AnonBuffer v) {
+ return v;
+}
+MYAPI const ShortBlob * MYAPIENTRY testShortBlob0(const ShortBlob *v) {
+ return v;
+}
+MYAPI LPShortBlob1 MYAPIENTRY testShortBlob1(LPShortBlob1 v) {
+ return v;
+}
+MYAPI LPShortBlob2 MYAPIENTRY testShortBlob2(LPShortBlob2 v) {
+ return v;
+}
+MYAPI LPShortBlob3 MYAPIENTRY testShortBlob3(LPShortBlob3 v) {
+ return v;
+}
+MYAPI LPShortBlob4 MYAPIENTRY testShortBlob4(LPShortBlob4 v) {
+ return v;
+}
+MYAPI struct Int32Struct * MYAPIENTRY testInt32Struct(struct Int32Struct * v) {
+ return v;
+}
+
+MYAPI AnonBlob MYAPIENTRY testCreateAnonBlob() {
+ return (AnonBlob) calloc(1, sizeof(char));
+}
+MYAPI void MYAPIENTRY testDestroyAnonBlob(AnonBlob v) {
+ free(v);
+}
+
+MYAPI struct _AnonBlob2 * MYAPIENTRY testCreateAnonBlob2() {
+ return (struct _AnonBlob2 *) calloc(1, sizeof(char));
+}
+MYAPI void MYAPIENTRY testDestroyAnonBlob2(struct _AnonBlob2 * v) {
+ free(v);
+}
+
+MYAPI foo_ptr MYAPIENTRY testFooPtr(foo_ptr v) {
+ return v;
+}
+
MYAPI foo MYAPIENTRY nopTest() {
return 42;
}
diff --git a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
index 67a8050..50f43b7 100644
--- a/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
+++ b/src/junit/com/jogamp/gluegen/test/junit/generation/test1.h
@@ -28,9 +28,78 @@
typedef int Bool;
typedef uint64_t foo;
+typedef foo * foo_ptr;
typedef void * APtr1Type;
typedef intptr_t APtr2Type;
+typedef void * XID; // Opaque
+typedef XID XID_2; // Opaque, due to XID
+typedef void * AnonBuffer; // Non Opaque
+
+typedef XID XID_2; // Duplicate w/ compatible type (ignored)
+// typedef int XID_2; // Duplicate w/ incompatible type ERROR
+
+#define DEFINE_01 1234
+#define DEFINE_01 1234 // Duplicate w/ same value (ignored)
+// #define DEFINE_01 1235 // Duplicate w/ diff value ERROR
+#define DEFINE_01_EXT 1234 // Renamed Duplicate w/ same value (ignored)
+// #define DEFINE_01_EXT 1235 // Renamed Duplicate w/ diff value ERROR
+
+#define DEFINE_02 ( (int ) 3 )
+// #define DEFINE_02 ( (int ) 3 ) // Duplicate w/ same value ERROR (PCPP redefine)
+// #define DEFINE_02 ( (int) 3 ) // Duplicate w/ diff value ERROR (PCPP redefine, then GlueGen)
+
+enum Lala { LI=1, LU, LO };
+// enum Lala { LI=1, LU, LO }; // Duplicate w/ same value (ignored, ERROR in native compilation)
+// enum Lala { LI=1, LU=3, LO }; // Duplicate w/ diff value ERROR
+// enum Lala { LI=1, LU, LO, LERROR }; // Duplicate w/ diff value ERROR
+
+typedef enum { MI=1, MU, MO } Momo;
+// typedef enum { MI=1, MU, MO } Momo; // Duplicate w/ same value (ignored, ERROR in native compilation)
+// typedef enum { MI=1, MU=3, MO } Momo; // Duplicate w/ diff value ERROR
+// typedef enum { MI=1, MU, MO, MERR } Momo; // Duplicate w/ diff value ERROR
+
+typedef struct _ShortBlob {
+ uint8_t b1;
+ uint8_t b2;
+} ShortBlob, ShortBlob2, *LPShortBlob1; // Aliased to 'ShortBlob'
+typedef ShortBlob2 * LPShortBlob2; // Aliased to 'ShortBlob'
+typedef ShortBlob * LPShortBlob3; // Aliased to 'ShortBlob'
+typedef LPShortBlob1 LPShortBlob4; // Aliased to 'ShortBlob'
+
+struct Int32Struct {
+ uint8_t b1;
+ uint8_t b2;
+ uint8_t b3;
+ uint8_t b4;
+};
+
+typedef struct _AnonBlob * AnonBlob; // Anonymous-Struct, Non Opaque
+
+struct _AnonBlob2; // opaque: struct _AnonBlob2*
+
+MYAPI XID MYAPIENTRY testXID(XID v);
+MYAPI XID MYAPIENTRY testXID(XID_2 v); // duplicate: shall be dropped
+// MYAPI XID MYAPIENTRY testXID(int v); // duplicate w/ diff value ERROR
+MYAPI XID MYAPIENTRY testXID_EXT(XID v); // renamed duplicate w/ compat value: shall be dropped
+// MYAPI XID MYAPIENTRY testXID_EXT(int v); // renamed duplicate w/ diff value ERROR
+MYAPI XID_2 MYAPIENTRY testXID_2(XID_2 v);
+MYAPI AnonBuffer MYAPIENTRY testAnonBuffer(AnonBuffer v);
+MYAPI const ShortBlob * MYAPIENTRY testShortBlob0(const ShortBlob *v);
+MYAPI LPShortBlob1 MYAPIENTRY testShortBlob1(LPShortBlob1 v);
+MYAPI LPShortBlob2 MYAPIENTRY testShortBlob2(LPShortBlob2 v);
+MYAPI LPShortBlob3 MYAPIENTRY testShortBlob3(LPShortBlob3 v);
+MYAPI LPShortBlob4 MYAPIENTRY testShortBlob4(LPShortBlob4 v);
+MYAPI struct Int32Struct * MYAPIENTRY testInt32Struct(struct Int32Struct * v);
+
+MYAPI AnonBlob MYAPIENTRY testCreateAnonBlob();
+MYAPI void MYAPIENTRY testDestroyAnonBlob(AnonBlob v);
+
+MYAPI struct _AnonBlob2 * MYAPIENTRY testCreateAnonBlob2();
+MYAPI void MYAPIENTRY testDestroyAnonBlob2(struct _AnonBlob2 * v);
+
+MYAPI foo_ptr MYAPIENTRY testFooPtr(foo_ptr v);
+
/** Returns 42 */
MYAPI foo MYAPIENTRY nopTest();
@@ -131,7 +200,7 @@ MYAPI int MYAPIENTRY intArrayCopy(int * dest, const int * src, int num);
/** Increases the elements by 1, and returns the sum
MYAPI int MYAPIENTRY intArrayWrite(int * * ints, int num); */
-typedef struct __MYAPIConfig * MYAPIConfig;
+typedef struct __MYAPIConfig * MYAPIConfig; // anonymous-struct opaque
/** Returns the passed MYAPIConfig incremented by 1 */
MYAPI MYAPIConfig MYAPIENTRY typeTestAnonSingle(const MYAPIConfig a);
@@ -172,7 +241,7 @@ typedef struct {
int32_t height;
} TK_Dimension;
-typedef struct _TK_Context * TK_Context; // anonymous
+typedef struct _TK_Context * TK_Context; // anonymous-struct opaque
typedef struct {
TK_Context ctx;
diff --git a/src/junit/com/jogamp/gluegen/test/junit/internals/TestType.java b/src/junit/com/jogamp/gluegen/test/junit/internals/TestType.java
new file mode 100644
index 0000000..1b83d0c
--- /dev/null
+++ b/src/junit/com/jogamp/gluegen/test/junit/internals/TestType.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package com.jogamp.gluegen.test.junit.internals;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.jogamp.gluegen.cgram.types.FloatType;
+import com.jogamp.gluegen.cgram.types.IntType;
+import com.jogamp.junit.util.SingletonJunitCase;
+
+import org.junit.FixMethodOrder;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestType extends SingletonJunitCase {
+
+ @Test
+ public void test01Equals() {
+ final FloatType f1 = new FloatType("GLfloat", null, 0);
+ final FloatType f2 = new FloatType("float", null, 0);
+ final IntType i1 = new IntType("GLint", null, false, 0);
+ final IntType i2 = new IntType("int", null, false, 0);
+ final int f1H = f1.hashCode();
+ final int f2H = f2.hashCode();
+ final int i1H = i1.hashCode();
+ final int i2H = i2.hashCode();
+
+ final int f1HS = f1.hashCodeSemantics();
+ final int f2HS = f2.hashCodeSemantics();
+ final int i1HS = i1.hashCodeSemantics();
+ final int i2HS = i2.hashCodeSemantics();
+
+ Assert.assertFalse(f1.getClass().isInstance(null));
+ Assert.assertTrue(f1.getClass().isInstance(f2));
+ Assert.assertTrue(i1.getClass().isInstance(i2));
+ Assert.assertFalse(f1.getClass().isInstance(i2));
+
+ Assert.assertFalse(f1.equals(f2));
+ Assert.assertFalse(i1.equals(i2));
+ Assert.assertFalse(f1.equals(i2));
+ Assert.assertNotEquals(f1H, f2H);
+ Assert.assertNotEquals(i1H, i2H);
+ Assert.assertNotEquals(f1H, i2H);
+
+ Assert.assertTrue(f1.equalSemantics(f2));
+ Assert.assertTrue(i1.equalSemantics(i2));
+ Assert.assertFalse(f1.equalSemantics(i2));
+ Assert.assertEquals(f1HS, f2HS);
+ Assert.assertEquals(i1HS, i2HS);
+ Assert.assertNotEquals(f1HS, i2HS);
+ }
+
+ public static void main(final String args[]) {
+ final String tstname = TestType.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}