5 # File : ethereal_be.py
7 # Author : Frank Singleton (frank.singleton@ericsson.com)
9 # Copyright (C) 2001 Frank Singleton, Ericsson Inc.
11 # This file is a backend to "omniidl", used to generate "Ethereal"
12 # dissectors from IDL descriptions. The output language generated
13 # is "C". It will generate code to use the GIOP/IIOP get_CDR_XXX API.
16 # Please see packet-giop.h in Ethereal distro for API description.
17 # Ethereal is available at http://www.ethereal.com/
19 # Omniidl is part of the OmniOrb distribution, and is available at
20 # http://www.uk.research.att.com/omniORB/omniORB.html
22 # This program is free software; you can redistribute it and/or modify it
23 # under the terms of the GNU General Public License as published by
24 # the Free Software Foundation; either version 2 of the License, or
25 # (at your option) any later version.
27 # This program is distributed in the hope that it will be useful,
28 # but WITHOUT ANY WARRANTY; without even the implied warranty of
29 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30 # General Public License for more details.
32 # You should have received a copy of the GNU General Public License
33 # along with this program; if not, write to the Free Software
34 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
39 # Omniidl Back-end which parses an IDL data structure provided by the frontend
40 # and generates packet-idl-xxx.[ch] for compiling as a dissector in
41 # Ethereal IP protocol anlayser.
48 # Crawl all the way down all branches until I hit "Operation", "Enum", "Attribute",
49 # "Struct" and "Union" nodes. Then store these nodes in lists.
51 # Pass these lists (via an object ref) to the src code
52 # generator (ethereal_gen) class and let it do the hard work !
55 # Dont forget structs can contain embedded structs etc .. so dont forget
56 # to peek inside and check :-)
61 """Ethereal IDL compiler back-end."""
63 from omniidl import idlast, idltype, idlvisitor, idlutil, output
66 from ethereal_gen import ethereal_gen_C
69 # This class finds the "Operation" nodes ,Enum Nodes, "Attribute" nodes, Struct Nodes
70 # and Union Nodes. Then it hands them off to an instance of the source code generator
71 # class "ethereal_gen"
74 class EtherealVisitor:
76 DEBUG = 0 # debug flag
78 def __init__(self, st):
80 self.oplist = [] # list of operation nodes
81 self.enlist = [] # list of enum nodes
82 self.atlist = [] # list of attribute nodes
83 self.stlist = [] # list of struct nodes
84 self.unlist = [] # list of union nodes
87 def visitAST(self, node):
89 print "XXX visitAST() node = ", node
91 for n in node.declarations():
92 if isinstance(n, idlast.Module):
94 if isinstance(n, idlast.Interface):
95 self.visitInterface(n)
96 if isinstance(n, idlast.Operation):
97 self.visitOperation(n)
98 if isinstance(n, idlast.Attribute):
99 self.visitAttribute(n)
100 if isinstance(n, idlast.Enum):
102 if isinstance(n, idlast.Struct):
104 if isinstance(n, idlast.Union):
107 # Check for Typedef structs and unions
109 if isinstance(n, idlast.Typedef):
110 self.visitTypedef(n) # who are you ?
113 def visitModule(self, node):
115 print "XXX visitModule() node = ", node
117 for n in node.definitions():
118 if isinstance(n, idlast.Module):
120 if isinstance(n, idlast.Interface):
121 self.visitInterface(n)
122 if isinstance(n, idlast.Operation):
123 self.visitOperation(n)
124 if isinstance(n, idlast.Attribute):
125 self.visitAttribute(n)
126 if isinstance(n, idlast.Enum):
128 if isinstance(n, idlast.Struct):
130 if isinstance(n, idlast.Union):
133 # Check for Typedef structs and unions
135 if isinstance(n, idlast.Typedef):
136 self.visitTypedef(n) # who are you ?
139 def visitInterface(self, node):
141 print "XXX visitInterface() node = ", node
143 for c in node.callables():
144 if isinstance(c, idlast.Operation):
145 self.visitOperation(c)
146 if isinstance(c, idlast.Attribute):
147 self.visitAttribute(c)
149 for d in node.contents():
150 if isinstance(d, idlast.Enum):
153 if isinstance(d, idlast.Struct):
156 if isinstance(d, idlast.Union):
159 # Check for Typedef structs and unions
161 if isinstance(d, idlast.Typedef):
162 self.visitTypedef(d) # who are you ?
170 # populates the operations node list "oplist"
174 def visitOperation(self,opnode):
175 if not opnode in self.oplist:
176 self.oplist.append(opnode) # store operation node
181 # populates the attribute node list "atlist"
185 def visitAttribute(self,atnode):
186 if not atnode in self.atlist:
187 self.atlist.append(atnode) # store attribute node
193 # populates the Enum node list "enlist"
197 def visitEnum(self,enode):
198 if not enode in self.enlist:
199 self.enlist.append(enode) # store enum node if unique
204 # Search to see if its a typedef'd struct, union, or enum
206 # eg: typdef enum colors {red, green, blue } mycolors;
209 def visitTypedef(self,td):
210 d = td.aliasType() # get Type, possibly Declared
211 if isinstance(d,idltype.Declared):
212 self.visitDeclared(d)
218 # Search to see if its a struct, union, or enum
222 def visitDeclared(self,d):
223 if isinstance(d,idltype.Declared):
224 sue = d.decl() # grab the struct or union or enum
226 if isinstance(sue, idlast.Struct):
227 self.visitStruct(sue)
228 if isinstance(sue, idlast.Union):
230 if isinstance(sue, idlast.Enum):
239 # populates the struct node list "stlist"
240 # and checks its members also
244 def visitStruct(self,stnode):
245 if not stnode in self.stlist:
246 self.stlist.append(stnode) # store struct node if unique and avoid recursive loops
247 # if we come across recursive structs
249 for m in stnode.members(): # find embedded struct definitions within this
251 if isinstance(mt,idltype.Declared):
252 self.visitDeclared(mt) # if declared, then check it out
259 # populates the struct node list "unlist"
260 # and checks its members also
264 def visitUnion(self,unnode):
265 if not unnode in self.unlist:
266 self.unlist.append(unnode) # store union node if unique
268 if unnode.constrType(): # enum defined within switch type
269 if isinstance(unnode.switchType(),idltype.Declared):
270 self.visitDeclared(unnode.switchType())
272 for c in unnode.cases():
274 if isinstance(ct,idltype.Declared):
275 self.visitDeclared(ct) # if declared, then check it out
282 st = output.Stream(sys.stdout, 4) # set indent for stream
283 ev = EtherealVisitor(st) # create visitor object
285 ev.visitAST(tree) # go find some operations
288 # Grab name of main IDL file being compiled.
290 # Assumption: Name is of the form abcdefg.xyz (eg: CosNaming.idl)
293 fname = path.basename(tree.file()) # grab basename only, dont care about path
294 nl = string.split(fname,".")[0] # split name of main IDL file using "." as separator
295 # and grab first field (eg: CosNaming)
299 print "XXX - Operation node ", i, " repoId() = ", i.repoId()
301 print "XXX - Attribute node ", i, " identifiers() = ", i.identifiers()
303 print "XXX - Enum node ", i, " repoId() = ", i.repoId()
305 print "XXX - Struct node ", i, " repoId() = ", i.repoId()
307 print "XXX - Union node ", i, " repoId() = ", i.repoId()
310 # create a C generator object
311 # and generate some C code
316 eg = ethereal_gen_C(ev.st, string.upper(nl), string.lower(nl), string.capitalize(nl) + " Dissector Using GIOP API")
317 eg.genCode(ev.oplist, ev.atlist, ev.enlist, ev.stlist, ev.unlist) # pass them onto the C generator