Ethereal-dev: [Ethereal-dev] idl2eth - preparation for recursive/embedd structs

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Frank Singleton <frank.singleton@xxxxxxxxxxxx>
Date: Mon, 19 Nov 2001 13:34:18 -0600
Hi, 

I have started on handling of recursive/embedded structs and unions
that can be found in CORBA IDL .

patch1.diff - find all union/struct references and store in lists.
              This includes embedded unions and structs.
            - pass the struct and union lists onto ethereal_gen.py
            - print all found nodes at DEBUG

patch2.diff - accept struct and union lists passed in via ethereal_be.py
            - these lists are unused until I add the templates for struct
              and union helper functions. So code generation is unchanged
              for the moment.

Twas diffed against 2001-11-05 CVS nightly tarball :-)

/Frank

-- 
EUS/SV/Z Frank Singleton      ASO Americas BSS
Office : +1 972 583 3251      ECN 800 33251  
Mobile : +1 214 228 0874      Amateur Radio: VK3FCS/KM5WS   
Email : frank.singleton@xxxxxxxxxxxx

Hardware: HP Omnibook 4150 running Redhat Linux 7.1 (2.4.3-12 kernel).
--- ../ethereal-2001-11-05/ethereal_be.py	Fri Oct 12 12:14:41 2001
+++ ../ethereal-2001-11-05.updated/ethereal_be.py	Mon Nov 19 13:05:36 2001
@@ -1,6 +1,6 @@
 # -*- python -*-
 #
-# $Id: ethereal_be.py,v 1.5 2001/10/12 17:14:41 guy Exp $
+# $Id: ethereal_be.py,v 1.28 2001/11/19 19:05:36 frank Exp $
 #
 #    File      : ethereal_be.py
 #
@@ -45,14 +45,17 @@
 #
 # Strategy. 
 #
-# Crawl all the way down all branches until I hit  "Operation" nodes
-# and "Attribute" nodes. Then store the "operation" nodes in oplist[]
-# and "attribute" nodes in atlist[].
+# Crawl all the way down all branches until I hit  "Operation", "Enum", "Attribute",
+# "Struct" and "Union" nodes.  Then store these nodes in lists.
 #
-# Pass the obj.oplist[] and obj.atlist[](via an object ref) to the src code
+# Pass these lists (via an object ref) to the src code
 # generator (ethereal_gen) class and let it do the hard work ! 
 #
 #
+# Dont forget structs can contain embedded structs etc .. so dont forget
+# to peek inside and check :-)
+#
+#
 
 
 """Ethereal IDL compiler back-end."""
@@ -63,20 +66,28 @@
 from ethereal_gen import ethereal_gen_C
 
 #
-# This class finds the "Operation" nodes and "Attribute" nodes, and hands them off
-# to an instance of the source code generator class "ethereal_gen" 
+# This class finds the "Operation" nodes ,Enum Nodes, "Attribute" nodes, Struct Nodes
+# and Union Nodes. Then it hands them off to an instance of the source code generator
+# class "ethereal_gen" 
 #
 
 class EtherealVisitor:
+
+    DEBUG = 0                           # debug flag
     
     def __init__(self, st):
         self.st = st
         self.oplist = []                # list of operation nodes
         self.enlist = []                # list of enum nodes
         self.atlist = []                # list of attribute nodes
+        self.stlist = []                # list of struct nodes
+        self.unlist = []                # list of union nodes
 
         
     def visitAST(self, node):
+        if self.DEBUG:
+            print "XXX visitAST() node = ", node
+            
         for n in node.declarations():
             if isinstance(n, idlast.Module):
                 self.visitModule(n)
@@ -88,9 +99,21 @@
                 self.visitAttribute(n)
             if isinstance(n, idlast.Enum):
                 self.visitEnum(n)
-                                
-
+            if isinstance(n, idlast.Struct):
+                self.visitStruct(n)
+            if isinstance(n, idlast.Union):
+                self.visitUnion(n)
+
+            # Check for Typedef structs and unions
+            
+            if isinstance(n, idlast.Typedef):
+                self.visitTypedef(n)    # who are you ?
+                
+                
     def visitModule(self, node):
+        if self.DEBUG:
+            print "XXX visitModule() node = ", node
+            
         for n in node.definitions():
             if isinstance(n, idlast.Module):
                 self.visitModule(n)    
@@ -102,9 +125,21 @@
                 self.visitAttribute(n)
             if isinstance(n, idlast.Enum):
                 self.visitEnum(n)
-                
+            if isinstance(n, idlast.Struct):
+                self.visitStruct(n)
+            if isinstance(n, idlast.Union):
+                self.visitUnion(n)
+
+            # Check for Typedef structs and unions
+            
+            if isinstance(n, idlast.Typedef):
+                self.visitTypedef(n)    # who are you ?
+
+                                    
     def visitInterface(self, node):
-        #if node.mainFile():
+        if self.DEBUG:
+            print "XXX visitInterface() node = ", node
+        
         for c in node.callables():
             if isinstance(c, idlast.Operation):
                 self.visitOperation(c)
@@ -113,7 +148,22 @@
                 
         for d in node.contents():
             if isinstance(d, idlast.Enum):
-                self.visitEnum(d)                
+                self.visitEnum(d)
+                
+            if isinstance(d, idlast.Struct):
+                self.visitStruct(d)
+
+            if isinstance(d, idlast.Union):
+                self.visitUnion(d)
+                
+            # Check for Typedef structs and unions
+
+            if isinstance(d, idlast.Typedef):
+                self.visitTypedef(d)    # who are you ?
+                
+
+                                
+
     #
     # visitOperation
     #
@@ -122,7 +172,8 @@
     #
     
     def visitOperation(self,opnode):
-        self.oplist.append(opnode)      # store operation node
+        if not opnode in self.oplist:
+            self.oplist.append(opnode)      # store operation node
 
     #
     # visitAttribute
@@ -132,21 +183,100 @@
     #
     
     def visitAttribute(self,atnode):
-        self.atlist.append(atnode)      # store attribute node
+        if not atnode in self.atlist:
+            self.atlist.append(atnode)      # store attribute node
+
 
     #
     # visitEnum
     #
-    # populates the enum node list "enumlist"
+    # populates the Enum node list "enlist"
     #
     #
     
     def visitEnum(self,enode):
-        #print "XXX - enum found" , enode
-        self.enlist.append(enode)      # store enum node
+        if not enode in self.enlist:
+            self.enlist.append(enode)      # store enum node if unique
+
+    #
+    # visitTypedef
+    #
+    # Search to see if its a typedef'd struct, union, or enum
+    #
+    # eg: typdef enum colors {red, green, blue } mycolors;
+    #
+    
+    def visitTypedef(self,td):
+        d = td.aliasType()              # get Type, possibly Declared
+        if isinstance(d,idltype.Declared):
+            self.visitDeclared(d)
+        
+
+    #
+    # visitDeclared
+    #
+    # Search to see if its a struct, union, or enum
+    #
+    #
+    
+    def visitDeclared(self,d):
+        if isinstance(d,idltype.Declared):
+            sue = d.decl()             # grab the struct or union or enum 
+            
+            if isinstance(sue, idlast.Struct):
+                self.visitStruct(sue)                
+            if isinstance(sue, idlast.Union):
+                self.visitUnion(sue)
+            if isinstance(sue, idlast.Enum):
+                self.visitEnum(sue)
+
+
+
+
+    #
+    # visitStruct
+    #
+    # populates the struct node list "stlist"
+    # and checks its members also
+    #
+    #
+    
+    def visitStruct(self,stnode):
+        if not stnode in self.stlist:        
+            self.stlist.append(stnode)      # store struct node if unique and avoid recursive loops
+                                            # if we come across recursive structs
+
+            for m in stnode.members():      # find embedded struct definitions within this
+                mt = m.memberType()
+                if isinstance(mt,idltype.Declared):
+                    self.visitDeclared(mt)      # if declared, then check it out 
 
 
+                                                
+    #
+    # visitUnion
+    #
+    # populates the struct node list "unlist"
+    # and checks its members also
+    #
+    #
+    
+    def visitUnion(self,unnode):
+        if not unnode in self.unlist:
+            self.unlist.append(unnode)      # store union node if unique
+
+            if unnode.constrType():         # enum defined within switch type
+                if isinstance(unnode.switchType(),idltype.Declared):
+                    self.visitDeclared(unnode.switchType())
+
+            for c in unnode.cases():
+                ct =  c.caseType()
+                if isinstance(ct,idltype.Declared):
+                    self.visitDeclared(ct)      # if declared, then check it out 
+                
         
+
+
 def run(tree, args):
 
     st = output.Stream(sys.stdout, 4)   # set indent for stream
@@ -159,16 +289,32 @@
     # 
     # Assumption: Name is of the form   abcdefg.xyz  (eg: CosNaming.idl)
     #
-
+    
     fname = path.basename(tree.file())    # grab basename only, dont care about path
     nl = string.split(fname,".")[0]       # split name of main IDL file using "." as separator
                                           # and grab first field (eg: CosNaming)
 
+    if ev.DEBUG:
+        for i in ev.oplist:
+            print "XXX - Operation node ", i, " repoId() = ", i.repoId()
+        for i in ev.atlist:
+            print "XXX - Attribute node ", i, " identifiers() = ", i.identifiers()
+        for i in ev.enlist:
+            print "XXX - Enum node ", i, " repoId() = ", i.repoId()                
+        for i in ev.stlist:
+            print "XXX - Struct node ", i, " repoId() = ", i.repoId()                                             
+        for i in ev.unlist:
+            print "XXX - Union node ", i, " repoId() = ", i.repoId()
+
+            
     # create a C generator object
     # and generate some C code
+
+
+
     
     eg = ethereal_gen_C(ev.st, string.upper(nl), string.lower(nl), string.capitalize(nl) + " Dissector Using GIOP API") 
-    eg.genCode(ev.oplist, ev.atlist, ev.enlist)    # pass them onto the C generator
+    eg.genCode(ev.oplist, ev.atlist, ev.enlist, ev.stlist, ev.unlist)    # pass them onto the C generator
     
 
 
--- ../ethereal-2001-11-05/ethereal_gen.py	Wed Oct 31 04:40:53 2001
+++ ../ethereal-2001-11-05.updated/ethereal_gen.py	Mon Nov 19 13:02:24 2001
@@ -1,6 +1,6 @@
 # -*- python -*-
 #
-# $Id: ethereal_gen.py,v 1.15 2001/10/31 10:40:53 guy Exp $
+# $Id: ethereal_gen.py,v 1.2 2001/11/19 19:02:23 frank Exp $
 #                           
 # ethereal_gen.py (part of idl2eth)           
 #
@@ -94,8 +94,9 @@
 # 12. Implement IDL "union" code [done]
 # 13. Implement support for plugins [done]
 # 14. Dont generate code for empty operations (cf: exceptions without members)
-# 15. Generate code to display Enums numerically ans symbolically [done]
+# 15. Generate code to display Enums numerically and symbolically [done]
 # 16. Place structs in subtrees
+# 17. Recursive struct and union handling [started - pass struct and union list to ethereal_gen.py ]
 #
 # Also test, Test, TEST
 #
@@ -169,7 +170,7 @@
     #
     #
         
-    def genCode(self,oplist, atlist, enlist):   # operation and attribute lists
+    def genCode(self,oplist, atlist, enlist, stlist, unlist):   # operation,attribute,enums,struct and union lists
 
         self.genHelpers(oplist)         # sneaky .. call it now, to populate the fn_hash
                                         # so when I come to that operation later, I have the variables to