From Frank Singleton:
[obnox/wireshark/wip.git] / ethereal_be.py
1 # -*- python -*-
2 #
3 # $Id: ethereal_be.py,v 1.6 2001/11/19 22:58:49 guy Exp $
4 #
5 #    File      : ethereal_be.py
6 #
7 #    Author    : Frank Singleton (frank.singleton@ericsson.com)
8 #
9 #    Copyright (C) 2001 Frank Singleton, Ericsson Inc.
10 #
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.
14 #  
15 #
16 #  Please see packet-giop.h in Ethereal distro for API description.
17 #  Ethereal is available at http://www.ethereal.com/
18 #
19 #  Omniidl is part of the OmniOrb distribution, and is available at
20 #  http://www.uk.research.att.com/omniORB/omniORB.html
21 #
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.
26 #
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.
31 #
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
35 #  02111-1307, USA.
36 #
37 # Description:
38 #   
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.
42 #
43 #  
44 #
45 #
46 # Strategy. 
47 #
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.
50 #
51 # Pass these lists (via an object ref) to the src code
52 # generator (ethereal_gen) class and let it do the hard work ! 
53 #
54 #
55 # Dont forget structs can contain embedded structs etc .. so dont forget
56 # to peek inside and check :-)
57 #
58 #
59
60
61 """Ethereal IDL compiler back-end."""
62
63 from omniidl import idlast, idltype, idlvisitor, idlutil, output
64 import sys, string
65 from os import path
66 from ethereal_gen import ethereal_gen_C
67
68 #
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" 
72 #
73
74 class EtherealVisitor:
75
76     DEBUG = 0                           # debug flag
77     
78     def __init__(self, st):
79         self.st = 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
85
86         
87     def visitAST(self, node):
88         if self.DEBUG:
89             print "XXX visitAST() node = ", node
90             
91         for n in node.declarations():
92             if isinstance(n, idlast.Module):
93                 self.visitModule(n)
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):
101                 self.visitEnum(n)
102             if isinstance(n, idlast.Struct):
103                 self.visitStruct(n)
104             if isinstance(n, idlast.Union):
105                 self.visitUnion(n)
106
107             # Check for Typedef structs and unions
108             
109             if isinstance(n, idlast.Typedef):
110                 self.visitTypedef(n)    # who are you ?
111                 
112                 
113     def visitModule(self, node):
114         if self.DEBUG:
115             print "XXX visitModule() node = ", node
116             
117         for n in node.definitions():
118             if isinstance(n, idlast.Module):
119                 self.visitModule(n)    
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):
127                 self.visitEnum(n)
128             if isinstance(n, idlast.Struct):
129                 self.visitStruct(n)
130             if isinstance(n, idlast.Union):
131                 self.visitUnion(n)
132
133             # Check for Typedef structs and unions
134             
135             if isinstance(n, idlast.Typedef):
136                 self.visitTypedef(n)    # who are you ?
137
138                                     
139     def visitInterface(self, node):
140         if self.DEBUG:
141             print "XXX visitInterface() node = ", node
142         
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)
148                 
149         for d in node.contents():
150             if isinstance(d, idlast.Enum):
151                 self.visitEnum(d)
152                 
153             if isinstance(d, idlast.Struct):
154                 self.visitStruct(d)
155
156             if isinstance(d, idlast.Union):
157                 self.visitUnion(d)
158                 
159             # Check for Typedef structs and unions
160
161             if isinstance(d, idlast.Typedef):
162                 self.visitTypedef(d)    # who are you ?
163                 
164
165                                 
166
167     #
168     # visitOperation
169     #
170     # populates the operations node list "oplist"
171     #
172     #
173     
174     def visitOperation(self,opnode):
175         if not opnode in self.oplist:
176             self.oplist.append(opnode)      # store operation node
177
178     #
179     # visitAttribute
180     #
181     # populates the attribute node list "atlist"
182     #
183     #
184     
185     def visitAttribute(self,atnode):
186         if not atnode in self.atlist:
187             self.atlist.append(atnode)      # store attribute node
188
189
190     #
191     # visitEnum
192     #
193     # populates the Enum node list "enlist"
194     #
195     #
196     
197     def visitEnum(self,enode):
198         if not enode in self.enlist:
199             self.enlist.append(enode)      # store enum node if unique
200
201     #
202     # visitTypedef
203     #
204     # Search to see if its a typedef'd struct, union, or enum
205     #
206     # eg: typdef enum colors {red, green, blue } mycolors;
207     #
208     
209     def visitTypedef(self,td):
210         d = td.aliasType()              # get Type, possibly Declared
211         if isinstance(d,idltype.Declared):
212             self.visitDeclared(d)
213         
214
215     #
216     # visitDeclared
217     #
218     # Search to see if its a struct, union, or enum
219     #
220     #
221     
222     def visitDeclared(self,d):
223         if isinstance(d,idltype.Declared):
224             sue = d.decl()             # grab the struct or union or enum 
225             
226             if isinstance(sue, idlast.Struct):
227                 self.visitStruct(sue)                
228             if isinstance(sue, idlast.Union):
229                 self.visitUnion(sue)
230             if isinstance(sue, idlast.Enum):
231                 self.visitEnum(sue)
232
233
234
235
236     #
237     # visitStruct
238     #
239     # populates the struct node list "stlist"
240     # and checks its members also
241     #
242     #
243     
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
248
249             for m in stnode.members():      # find embedded struct definitions within this
250                 mt = m.memberType()
251                 if isinstance(mt,idltype.Declared):
252                     self.visitDeclared(mt)      # if declared, then check it out 
253
254
255                                                 
256     #
257     # visitUnion
258     #
259     # populates the struct node list "unlist"
260     # and checks its members also
261     #
262     #
263     
264     def visitUnion(self,unnode):
265         if not unnode in self.unlist:
266             self.unlist.append(unnode)      # store union node if unique
267
268             if unnode.constrType():         # enum defined within switch type
269                 if isinstance(unnode.switchType(),idltype.Declared):
270                     self.visitDeclared(unnode.switchType())
271
272             for c in unnode.cases():
273                 ct =  c.caseType()
274                 if isinstance(ct,idltype.Declared):
275                     self.visitDeclared(ct)      # if declared, then check it out 
276                 
277         
278
279
280 def run(tree, args):
281
282     st = output.Stream(sys.stdout, 4)   # set indent for stream
283     ev = EtherealVisitor(st)            # create visitor object
284     
285     ev.visitAST(tree)                   # go find some operations
286     
287     #
288     # Grab name of main IDL file being compiled.
289     # 
290     # Assumption: Name is of the form   abcdefg.xyz  (eg: CosNaming.idl)
291     #
292     
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)
296
297     if ev.DEBUG:
298         for i in ev.oplist:
299             print "XXX - Operation node ", i, " repoId() = ", i.repoId()
300         for i in ev.atlist:
301             print "XXX - Attribute node ", i, " identifiers() = ", i.identifiers()
302         for i in ev.enlist:
303             print "XXX - Enum node ", i, " repoId() = ", i.repoId()                
304         for i in ev.stlist:
305             print "XXX - Struct node ", i, " repoId() = ", i.repoId()                                             
306         for i in ev.unlist:
307             print "XXX - Union node ", i, " repoId() = ", i.repoId()
308
309             
310     # create a C generator object
311     # and generate some C code
312
313
314
315     
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
318     
319
320