From 9eb9403d774db0c55ea3cb2fc5bd04114b8b5feb Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Mon, 9 Mar 2015 03:09:18 +0100
Subject: Bug 1134 - Fix aliased typedef struct emission

- Code regarding 'aliased typedef struct' is tagged in JavaEmitter and HeaderParser:
  'NOTE: Struct Name Resolution (JavaEmitter, HeaderParser)'

  Prefers containing cstruct typedef pointer
  if available _and_ if cstruct is _not_ a typedef!

- Removed: 'HeaderParser.resolveAnonCompound(..)' no more required,
  since CompoundType always sets its name!
  Commit cf9f28cf249393f42d7d2835775521dfadee6b92

- JavaEmitter.emitStruct:
  - Regard above 'aliased typedef struct' NOTE

- JavaEmitter.typeToJavaType:
  - Regard above 'aliased typedef struct' NOTE

- ReferencedStructs
  - Drop duplicate CompoundType instances of same name.
    This can happen due to const/volatile and ASTLocusTag variants.
---
 src/java/com/jogamp/gluegen/GlueGen.java           | 13 +---
 src/java/com/jogamp/gluegen/JavaEmitter.java       | 91 ++++++++++++----------
 src/java/com/jogamp/gluegen/ReferencedStructs.java | 56 +++++++------
 3 files changed, 89 insertions(+), 71 deletions(-)

(limited to 'src/java')

diff --git a/src/java/com/jogamp/gluegen/GlueGen.java b/src/java/com/jogamp/gluegen/GlueGen.java
index 4ef5648..c4eb1c5 100644
--- a/src/java/com/jogamp/gluegen/GlueGen.java
+++ b/src/java/com/jogamp/gluegen/GlueGen.java
@@ -294,8 +294,7 @@ public class GlueGen implements GlueEmitterControls {
             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
-                // to be skipped).
+                // emitted (e.g., if an Ignore directive in the JavaEmitter causes it to be skipped).
                 sym.getType().visit(referencedStructs);
             }
 
@@ -315,13 +314,9 @@ public class GlueGen implements GlueEmitterControls {
 
             // Lay out structs
             emit.beginStructLayout();
-            for (final Iterator<Type> iter = referencedStructs.results(); iter.hasNext();) {
-                final Type t = iter.next();
-                if (t.isCompound()) {
-                    emit.layoutStruct(t.asCompound());
-                } else if (t.isPointer()) {
-                    final PointerType p = t.asPointer();
-                    final CompoundType c = p.getTargetType().asCompound();
+            for (final Iterator<CompoundType> iter = referencedStructs.layouts(); iter.hasNext();) {
+                final CompoundType c = iter.next();
+                if( !c.isLayouted() ) {
                     emit.layoutStruct(c);
                 }
             }
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index ca89b0e..52e8834 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -877,53 +877,64 @@ public class JavaEmitter implements GlueEmitter {
   }
 
   @Override
-  public void emitStruct(final CompoundType structCType, final Type typedefed) throws Exception {
+  public void emitStruct(final CompoundType structCType, final Type structCTypedefPtr) throws Exception {
     final String structCTypeName, typedefedName;
     {
         final String _name = structCType.getName();
-        if ( null == _name && null != typedefed && null != typedefed.getName() ) {
-            // use typedef'ed name
-            typedefedName = typedefed.getName();
+        if ( null != structCTypedefPtr && null != structCTypedefPtr.getName() ) {
+            // always use typedef'ed name if available
+            typedefedName = structCTypedefPtr.getName();
             structCTypeName = typedefedName;
         } else {
-            // use actual struct type name
+            // fall back to actual struct type name
             typedefedName = null;
             structCTypeName = _name;
         }
-    }
-    LOG.log(INFO, structCType.getASTLocusTag(),
-            "Struct emission of structCType \"{0}\" -> {1}", structCTypeName, structCType);
-    LOG.log(INFO, structCType.getASTLocusTag(),
-            "           which has a typedef \"{0}\" -> {1}", typedefedName, typedefed);
-
-    if ( null == structCTypeName ) {
-        final String structName = structCType.getStructName();
-        if ( null != structName && cfg.shouldIgnoreInInterface(structName) ) {
+        LOG.log(INFO, structCType.getASTLocusTag(), "Struct emission of structCType {0}", structCType);
+        LOG.log(INFO, structCType.getASTLocusTag(),"              structCTypedefPtr {0}", structCTypedefPtr);
+        LOG.log(INFO, structCType.getASTLocusTag(),"   : structCTypeName \"{0}\" -> typedefedName \"{1}\" -> \"{2}\"",
+                                                                   _name, typedefedName, structCTypeName);
+        if ( null == structCTypeName ) {
             LOG.log(INFO, structCType.getASTLocusTag(),
-                    "skipping emission of unnamed ignored struct \"{0}\": {1}", structName, structCType);
+                    "skipping emission of unnamed struct {0} w/o typedef",  structCType);
             return;
-        } else {
+        }
+        final AliasedSymbol.AliasedSymbolImpl aliases = new AliasedSymbol.AliasedSymbolImpl(structCTypeName);
+        aliases.addAliasedName(_name);
+        aliases.addAliasedName(typedefedName);
+        if ( cfg.shouldIgnoreInInterface(aliases) ) {
             LOG.log(INFO, structCType.getASTLocusTag(),
-                    "skipping emission of unnamed struct {0}, typedef {1} ",  structCType, typedefed);
+                    "skipping emission of ignored \"{0}\": {1}", aliases, structCType);
             return;
         }
     }
-    if ( cfg.shouldIgnoreInInterface(structCTypeName) ) {
+
+    if( null != structCTypedefPtr && isOpaque(structCTypedefPtr) ) {
         LOG.log(INFO, structCType.getASTLocusTag(),
-                "skipping emission of ignored \"{0}\": {1}", structCTypeName, structCType);
+                "skipping emission of opaque typedef {0}", structCTypedefPtr);
         return;
     }
-    if( null != typedefed && isOpaque(typedefed) ) {
+    if( isOpaque(structCType) ) {
         LOG.log(INFO, structCType.getASTLocusTag(),
-                "skipping emission of opaque typedef {0}, c-struct {1}", typedefed, structCType);
+                "skipping emission of opaque c-struct {0}", structCType);
         return;
     }
 
     final Type containingCType;
     {
-        final Type aptr = new PointerType(SizeThunk.POINTER, structCType, 0);
-        aptr.setTypedefName(typedefedName);
+        // NOTE: Struct Name Resolution (JavaEmitter, HeaderParser)
+        final Type aptr;
+        int mode;
+        if( null != typedefedName ) {
+            aptr = structCTypedefPtr;
+            mode = 1;
+        } else {
+            aptr = new PointerType(SizeThunk.POINTER, structCType, 0);
+            aptr.setTypedefName(typedefedName);
+            mode = 2;
+        }
         containingCType = canonicalize(aptr);
+        LOG.log(INFO, structCType.getASTLocusTag(), "containingCType[{0}]: {1} -canon-> {2}", mode, aptr, containingCType);
     }
     final JavaType containingJType = typeToJavaType(containingCType, null);
     if( containingJType.isOpaqued() ) {
@@ -939,15 +950,7 @@ public class JavaEmitter implements GlueEmitter {
     final String containingJTypeName = containingJType.getName();
     LOG.log(INFO, structCType.getASTLocusTag(),
             "perform emission of \"{0}\" -> \"{1}\": {2}", structCTypeName, containingJTypeName, structCType);
-    if( GlueGen.debug() ) {
-        if( null != typedefed ) {
-            LOG.log(INFO, structCType.getASTLocusTag(), "    typedefed {0}", typedefed);
-        } else {
-            LOG.log(INFO, structCType.getASTLocusTag(), "    typedefed {0}", (Object)null);
-        }
-        LOG.log(INFO, structCType.getASTLocusTag(), "    containingCType {0}", containingCType);
-        LOG.log(INFO, structCType.getASTLocusTag(), "    containingJType {0}", containingJType);
-    }
+
     if( 0 == structCType.getNumFields() ) {
         LOG.log(INFO, structCType.getASTLocusTag(),
                 "emission of \"{0}\" with zero fields {1}", containingJTypeName, structCType);
@@ -2168,14 +2171,22 @@ public class JavaEmitter implements GlueEmitter {
                 cType.getName().equals("jobject")) {
               return javaType(java.lang.Object.class);
             }
-            String name = targetType.getName();
-            if (name == null) {
-              // Try containing pointer type for any typedefs
-              name = cType.getName();
-              if (name == null) {
-                throw new GlueGenException("Couldn't find a proper type name for pointer type " + cType.getDebugString(),
-                                            cType.getASTLocusTag());
-              }
+            // NOTE: Struct Name Resolution (JavaEmitter, HeaderParser)
+            String name;
+            if( !targetType.isTypedef() && cType.isTypedef() ) {
+                // If compound is not a typedef _and_ containing pointer is typedef, use the latter.
+                name = cType.getName();
+            } else {
+                // .. otherwise try compound name
+                name = targetType.getName();
+                if( null == name ) {
+                  // .. fall back to pointer type name
+                  name = cType.getName();
+                  if (name == null) {
+                    throw new GlueGenException("Couldn't find a proper type name for pointer type " + cType.getDebugString(),
+                                                cType.getASTLocusTag());
+                  }
+                }
             }
             return JavaType.createForCStruct(cfg.renameJavaType(name));
           } else {
diff --git a/src/java/com/jogamp/gluegen/ReferencedStructs.java b/src/java/com/jogamp/gluegen/ReferencedStructs.java
index 46a2a7e..26deb3a 100644
--- a/src/java/com/jogamp/gluegen/ReferencedStructs.java
+++ b/src/java/com/jogamp/gluegen/ReferencedStructs.java
@@ -44,31 +44,43 @@ import com.jogamp.gluegen.cgram.types.*;
 
 public class ReferencedStructs implements TypeVisitor {
 
-  private final Set<Type> results = new HashSet<Type>();
+    private final Map<String, Type> resultMap = new HashMap<String, Type>();
+    private final Set<CompoundType> layoutSet = new HashSet<CompoundType>();
+    private final Set<Type> skip = new HashSet<Type>();
 
-  public void clear() {
-    results.clear();
-  }
+    public void clear() {
+        resultMap.clear();
+    }
 
-  public Iterator<Type> results() {
-    return results.iterator();
-  }
+    public Iterator<Type> results() {
+        return resultMap.values().iterator();
+    }
+    public Iterator<CompoundType> layouts() {
+        return layoutSet.iterator();
+    }
 
-  @Override
-  public void visitType(final Type t) {
-    if (t.isPointer()) {
-      final PointerType p = t.asPointer();
-      if (p.isTypedef()) {
-        final CompoundType c = p.getTargetType().asCompound();
-        if (c != null && c.getName() == null) {
-          // This otherwise-unnamed CompoundType is referred to by a
-          // PointerType that has a typedef name. Assume that it is
-          // referred to in the glue code and emit it.
-          results.add(p);
+    @Override
+    public void visitType(final Type t) {
+        if( skip.contains(t) ) {
+            return;
+        }
+        if ( t.isPointer() ) {
+            final PointerType p = t.asPointer();
+            final CompoundType c = p.getTargetType().asCompound();
+            if( p.isTypedef() && null != c ) {
+                // If containing pointer is typedef, use it (preferred)
+                skip.add(c); // earmark to skip the compound!
+                resultMap.put(c.getName(), p);
+                layoutSet.add(c);
+            } else {
+                // .. otherwise skip pointer and use followup compound
+            }
+        } else if( t.isCompound() ) {
+            // Use compound if not yet mapped, e.g. by typedef'ed (preferred)
+            if( !resultMap.containsKey(t.getName()) ) {
+                resultMap.put(t.getName(), t);
+            }
+            layoutSet.add(t.asCompound()); // always: could be const/volatile variants ..
         }
-      }
-    } else if (t.isCompound()) {
-      results.add(t);
     }
-  }
 }
-- 
cgit v1.2.3