Salome HOME
merge from branch BR_V5_DEV
[modules/kernel.git] / src / ModuleGenerator / IDLparser.py
1 #  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 #
3 #  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 #  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 #
6 #  This library is free software; you can redistribute it and/or
7 #  modify it under the terms of the GNU Lesser General Public
8 #  License as published by the Free Software Foundation; either
9 #  version 2.1 of the License.
10 #
11 #  This library is distributed in the hope that it will be useful,
12 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 #  Lesser General Public License for more details.
15 #
16 #  You should have received a copy of the GNU Lesser General Public
17 #  License along with this library; if not, write to the Free Software
18 #  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 #
20 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 #
22 #  File   : IDLparser.py
23 #  Module : SALOME
24 #
25 import string, sys, fpformat, re, os
26 import xml.sax
27 import pdb
28
29 from xml.sax.handler import *
30 from omniidl import idlast, idltype, idlvisitor, idlutil, output
31
32 # parameters not found in IDL file, user's specified in optional parameters
33 common_data={"AUTHOR"     : "",
34              "ICON"       : "",
35              "VERSION"    : "",
36              "COMP_TYPE"  : "",
37              "COMP_NAME"  : "",
38              "COMP_UNAME" : "",
39              "COMP_MULT"  : "",
40              "COMP_IMPL"  : ""
41              }
42
43 nb_components = 0
44
45 #--------------------------------------------------
46 # extract value of <param_name> from <args> list
47 # it's proposed that the matching <args> item
48 # looks like <param_name>=<value>, for example,
49 # catalog=/tmp/myxml.xml
50 #--------------------------------------------------
51 def getParamValue( param_name, default_value, args ):
52     pattern="^"+param_name+"="
53
54     res = default_value        #initial value
55     for opt in args:
56         s = re.compile(pattern).search(opt)
57         if s:
58             res = opt[s.end():]
59             break     #found
60
61     return res    
62
63
64 #--------------------------------------------------
65 # print error message
66 #--------------------------------------------------
67 def error (message):
68     print "ERROR : ", message
69
70
71 #--------------------------------------------------
72 # base class implementing tree
73 #--------------------------------------------------
74 class Tree:
75     
76     def __init__(self, name = '', content = '', key = None):
77         self.name = name
78         self.content = content
79         self.key = key
80         self.parent = None
81         self.childs = []
82         self.comments = []
83         self.attrs={}
84         
85     def addChild(self, tree):
86         if tree is not None: 
87             self.childs.append(tree)
88             tree.parent = self
89         return tree
90
91     def addNamedChild(self, name, content = ''):
92         return self.addChild(Tree(name, content))
93
94     def replaceChild(self, tree):
95          if tree is not None:
96             pos = 0
97             for i in self.childs:
98                 if (i.name == tree.name) & ((i.key is None) | (i.key == tree.key)):
99                     self.childs.pop(pos)
100                     self.childs.insert(pos, tree)
101                     return tree
102                 pos += 1
103
104          return self.addChild(tree)
105        
106     def insertFirstChild(self, tree):
107         if tree is not None:
108             self.childs.insert(0, tree)
109         return tree
110     
111     def insertFirstNamedChild(self, name, content = ''):
112         return self.insertFirstChild(Tree(name, content))
113
114     def output_xml(self, f, depth=0):
115         d = depth
116         if self.name != '':
117             s = string.ljust('', 4*depth)
118             s += '<' + self.name 
119             for k,v in self.attrs.items():
120               s += ' ' + k + '="' + v + '"'
121             s += '>'
122             if self.content != '':
123                 s +=  self.content
124             else:
125                 if len(self.childs) > 0:
126                     s += '\n'
127             f.write(s)
128             d +=  1
129             
130         for i in self.childs:
131             i.output_xml(f, d)
132             
133         if self.name != '':
134             s = '</' + self.name + '>\n'
135             if len(self.childs) > 0 :
136                 s = string.ljust('', 4*depth) + s
137             f.write(s)
138
139     def Dump(self, levels=-1, depth=0):
140         #Dumps the tree contents
141         
142         if levels == 0: return
143         
144         s = string.ljust('', 4*depth)
145         print s, self, self.content
146         for i in self.childs:
147             i.Dump(levels-1, depth+1)
148
149     def parents(self):
150         #Returns list of the parents
151         l = []
152         p = self.parent
153         while p:
154             l.append(p)
155             l.append(p.name)
156             p = p.parent
157         return l
158         
159     def getChild(self, name, content=None):
160         # return child node with a given name
161         # if content == None, don't compare contents
162         for i in self.childs:
163             if (i.name == name):
164                 if (content is None) | (i.content == content):
165                     return i
166         return None
167
168     def getNode(self, name, content='', depth=-1):
169         # recursive search of a node with a given name
170         # content == None, don't compare content
171         if (self.name == name):
172             if (content is None) | (self.content == content):
173                 return self
174             
175         if (depth != 0):
176             for i in self.childs:
177                 n = i.getNode(name, content, depth-1)
178                 if n:  return n 
179             
180         return None
181
182     def __repr__(self):
183         s = '<'
184         if self.name != '':
185             s += self.name
186         else:
187             s +=  'None'
188         s += '>'
189         return s
190
191     def merge(self, t):
192         pass
193
194     def mergeChilds(self, t, list):
195         L_ext = t.getChild(list)
196         L_int = self.getChild(list)
197
198         L_merge = Tree(list)
199         
200         for i_ext in L_ext.childs:
201             k_ext = i_ext.key
202             if k_ext is None:  continue
203             present = 0
204             
205             for i_int in L_int.childs:
206                 k_int = i_int.key
207                 if k_int is None:  continue
208                 
209                 if (k_int == k_ext):
210                     present = 1
211                     break;
212                 
213             if present :
214                 i_int.merge(i_ext)
215                 L_merge.addChild(i_int)
216             else:
217                 L_merge.addChild(i_ext)
218                 
219         self.replaceChild(L_merge)
220
221     def setAttrib(self, name,value):
222       self.attrs[name]=value
223             
224
225     
226 #--------------------------------------------------
227 # implements parameter tree
228 #--------------------------------------------------
229 class parameter(Tree):
230     
231     def __init__(self, name=None, mode = 'in', type='', comment='unknown'):
232         Tree.__init__(self, mode + 'Parameter', key=name)
233         self.mode = mode
234         if name is None:  return
235         
236         self.addNamedChild(mode + 'Parameter-name', name)
237         self.addNamedChild(mode + 'Parameter-type', type)
238         self.addNamedChild(mode + 'Parameter-comment', comment)
239         
240     def merge(self, P):
241
242         self.mode = P.mode
243         self.replaceChild(P.getChild(P.mode + 'Parameter-name'))
244         self.replaceChild(P.getChild(P.mode + 'Parameter-type'))
245         C = P.getChild(P.mode + 'Parameter-comment')
246         if C.content != 'unkonwn':
247             self.replaceChild(C)
248     
249 #--------------------------------------------------
250 # implements dataStreamParameter tree
251 #--------------------------------------------------
252 class dataStreamParameter(parameter):
253     
254     def __init__(self, name=None, mode='in', type='', dependency='', comment='unknown'):
255         parameter.__init__(self, name, mode, type, comment)
256         if name is None:  return
257         
258         self.addNamedChild(mode + 'Parameter-dependency', dependency)
259         self.mode = mode
260             
261     def merge(self, P):
262
263         parameter.merge(self, P)
264         self.replaceChild(P.getChild(mode + 'Parameter-dependency'))
265
266
267 def parseComment(comment):
268
269     spaces = '[\t\n ]*'
270     word = spaces + '([a-zA-Z][a-zA-Z0-9_]*)' + spaces
271     
272     result = []
273     type = None
274     key = None
275     
276     ## match :  // followed by a 'DataStreamPorts' string,
277     ## the service name, and a list of ports
278     pattern = '// *DataStreamPorts{,1}' + word
279     m = re.match(pattern, comment)
280
281     ## if there is a match, parse remaining part of comment
282     if m:
283         ## service
284         type = 'DataStreamPorts'
285         key = m.group(1)
286         
287         sPorts = comment[m.end():]
288         pattern = word + '\('+word+','+word +','+word+'\)' \
289                   + spaces + ',{,1}' + spaces
290         while len(sPorts) > 0:
291             ## process next DataStreamPort
292             ## match a definition like xx(a,b,c) with a possible trailing ,
293             ## returns a tuple (xx, a, b, c) and
294             ## the remaining part of input string
295             m = re.match(pattern, sPorts)
296             if m is None:
297                 raise LookupError, \
298                       'format error in DataStreamPort definition : '+sPorts
299             sPorts = sPorts[m.end():]
300             result.append(m.groups())
301             
302     return type, key, result;
303
304 #--------------------------------------------------
305 # implements service tree
306 #--------------------------------------------------
307 class Service(Tree):
308     
309     def __init__(self, name=None, comment = 'unknown'):
310         
311         Tree.__init__(self, 'component-service', key=name)
312         if name is None:  return
313         
314         self.addNamedChild('service-name', name)
315         self.addNamedChild('service-author',common_data["AUTHOR"])
316         self.addNamedChild('service-version',common_data["VERSION"])
317         self.addNamedChild('service-comment', comment)
318         self.addNamedChild('service-by-default', "0")
319         self.addNamedChild('inParameter-list')
320         self.addNamedChild('outParameter-list')
321         self.addNamedChild('DataStream-list')
322             
323     def createInParameter(self, name, type):
324         L = self.getChild('inParameter-list')
325         p = parameter(name, 'in', type)
326         L.replaceChild(p)
327         return p
328     
329     def createOutParameter(self, name, type):
330         L = self.getChild('outParameter-list')
331         p = parameter(name, 'out', type)
332         L.replaceChild(p)
333         return p
334
335     def createDataStreamParameter(self, p):
336         L = self.getChild('DataStream-list')
337         p = dataStreamParameter(p[0], p[2], p[1], p[3])
338         L.replaceChild(p)
339         return p
340             
341     def merge(self, S):
342
343         self.replaceChild(S.getChild('service-author'))
344         self.replaceChild(S.getChild('service-version'))
345         self.replaceChild(S.getChild('service-by-default'))
346         C = S.getChild('service-comment')
347         if C.content != 'unkonwn':
348             self.replaceChild(C)
349             
350         for L in ['inParameter-list', 'outParameter-list', 'DataStream-list']:
351            self.mergeChilds(S, L)
352             
353
354
355 #--------------------------------------------------
356 # implements interface tree
357 #--------------------------------------------------
358 class Interface(Tree):
359     
360     def __init__(self, name=None, comment='unknown'):
361                
362         Tree.__init__(self, key=name)
363
364         if name is None:  return
365         
366         self.addNamedChild('component-interface-name', name)
367         self.addNamedChild('component-interface-comment', comment);
368         self.addNamedChild('component-service-list')
369             
370     def createService(self, name):
371         L = self.getChild('component-service-list')
372
373         if L is None:
374             error ("Interface.createService() : 'component-service-list' is not found")
375             return None
376
377         s = Service(name)
378         L.addChild(s)
379         return s
380
381     def findService(self, key):
382         L = self.getChild('component-service-list')
383         for S in L.childs:
384             if S.key == key:
385                 return S
386         return None
387     
388     def merge(self, I):
389
390         C = S.getChild('component-interface-comment')
391         if C.content != 'unkonwn':
392             self.replaceChild(C)
393
394         self.mergeChilds(I, 'component-service-list')
395     
396     def processDataStreams(self):
397         for sComment in self.comments:
398
399             type, key, result = parseComment(sComment)
400
401             if type == 'DataStreamPorts':
402                 Service = self.findService(key)
403                 if Service is None:
404                     raise LookupError, \
405                           'service ' + key + \
406                           ' not found in interface : ' + self.key
407                 for p in result:
408                 ## process next DataStreamPort
409                     Service.createDataStreamParameter(p)
410
411
412 #--------------------------------------------------
413 # implements Component tree
414 #--------------------------------------------------
415 class Component(Tree):
416     def __init__(self, name=None):
417         Tree.__init__(self, 'component', key=name)
418         if name is None:  return
419                  
420 # ASV : fix for bug PAL8922 (Component name indicated by user in GUI is not taken into account
421         if common_data["COMP_NAME"] != '':
422             self.addNamedChild('component-name', common_data["COMP_NAME"])
423         else:
424             self.addNamedChild('component-name', name)
425
426 # ASV : if user name is NOT set, then use component-name instead.  Else - default.
427         if common_data["COMP_UNAME"] != '':
428             self.addNamedChild('component-username',   common_data["COMP_UNAME"])
429         else:
430             if common_data["COMP_NAME"] != '':
431                 self.addNamedChild('component-username', common_data["COMP_NAME"] )
432             else:
433                 self.addNamedChild('component-username',   name)
434             
435         self.addNamedChild('component-type',       common_data["COMP_TYPE"])
436         self.addNamedChild('component-author',     common_data["AUTHOR"])
437         self.addNamedChild('component-version',    common_data["VERSION"])
438         self.addNamedChild('component-comment',    'unknown')
439         self.addNamedChild('component-multistudy', common_data["COMP_MULT"])
440         self.addNamedChild('component-impltype',   common_data["COMP_IMPL"])
441         self.addNamedChild('component-icone',      common_data["ICON"])
442         self.addNamedChild('constraint')
443         self.addNamedChild('component-interface-list')
444             
445     def createInterface(self, name):
446         L = self.getChild('component-interface-list')
447         if L is None:
448             error("createInterface: No component-interface-list is found")
449             return None
450         i = Interface(name)
451         L.addChild(i)
452         return i
453
454     def merge(self, C):
455
456         for i in ['component-username', 'component-author',
457                   'component-type', 'component-icone', 'component-version',
458                   'component-multistudy', 'component-impltype', 'constraint']:
459             ext = C.getChild(i)
460             int = self.getChild(i)
461             if int is None:
462                 int = ext
463             elif ext is not None and len(ext.content):
464                 int.content = ext.content
465                 
466         Cc = C.getChild('component-comment')
467         if Cc.content != 'unkonwn':
468             self.replaceChild(Cc)
469                 
470         self.mergeChilds(C, 'component-interface-list')
471     
472 #--------------------------------------------------
473 # implements document tree
474 #--------------------------------------------------
475 class Catalog(ContentHandler, Tree):
476     def __init__(self, filename = None):
477         Tree.__init__(self)
478         self.buffer = ''
479         self.list = []
480         if (filename):
481             parser = xml.sax.make_parser()
482             parser.setContentHandler(self)
483             parser.parse(filename)
484         else:
485             t = self.addNamedChild('begin-catalog')
486             t.addNamedChild('type-list')
487             t.addNamedChild('component-list')
488
489         n = self.getChild('begin-catalog')
490         if n is None:
491             error("Catalog.__init__ : No 'begin-catalog' is found!")
492             return
493         if n.getChild('path-prefix-list') is None:
494             n.insertFirstNamedChild('path-prefix-list')
495         if n.getChild('type-list') is None:
496             p=n.childs.index(n.getChild('path-prefix-list'))
497             n.childs.insert(p+1,Tree('type-list'))
498         if n.getChild('component-list') is None:
499             n.addNamedChild('component-list')
500             
501     def removeComponent(self, name):
502         complist = self.getNode('component-list')
503         idx = 0
504         if complist is None:
505             print "Catalog.removeComponent() : 'component-list' is not found"
506             return
507         for comp in complist.childs:
508             cname = comp.getChild('component-name')
509             if cname is not None:
510                 if cname.content == name:
511                     complist.childs.pop(idx)
512                     print "Component " + name + " is removed"
513             idx += 1       
514  
515     def startDocument(self):
516         self.list.append(self)
517     
518     def startElement(self, name, attrs):
519         p = self.list[len(self.list)-1]
520         if name == 'component':
521             e = p.addChild(Component())
522         elif name == 'component-interface-name':
523             e = p.addNamedChild(name)
524         elif name == 'component-service':
525             e = p.addChild(Service())
526         elif name == 'inParameter':
527             e = p.addChild(parameter(mode='in'))
528         elif name == 'outParameter':
529             e = p.addChild(parameter(mode='out'))
530         elif name == 'sequence':
531             e = p.addChild(SeqType(attrs["name"],attrs["content"]))
532         elif name == 'objref':
533             e = p.addChild(ObjType(attrs["name"]))
534         elif name == 'struct':
535             e = p.addChild(StructType(attrs["name"]))
536         elif name == 'type':
537             e = p.addChild(Type(attrs["name"],attrs["kind"]))
538         elif name == 'member':
539             e = p.addChild(Member(attrs["name"],attrs["type"]))
540         else:
541             e = p.addNamedChild(name)
542         self.list.append(e)
543         self.buffer = ''
544         
545     def endElement(self, name):
546         self.buffer = string.join(string.split(self.buffer), ' ')
547         p = self.list[len(self.list)-1]
548         p.content = self.buffer
549         if name == 'component':
550             p.key = p.getChild('component-name').content
551         self.buffer = ''
552         e = self.list.pop()
553         
554     def characters(self, ch):
555         self.buffer += ch
556
557     def mergeComponent(self, comp):
558         
559         L_int = self.getNode('component-list')
560         if   L_int is None:
561             error("Catalog.mergeComponent : 'component-list' is not found")
562             return
563         
564         i_ext = comp
565         present = 0
566         n_ext = i_ext.key
567         for i_int in L_int.childs:
568             if (i_int.key == n_ext):
569                 present = 1
570                 break;
571                 
572         if present == 0:
573             print '   add component', i_ext.getChild('component-name').content
574             L_int.addChild(i_ext)
575         else:
576             print '   replace component', i_ext.getChild('component-name').content
577             i_int.merge(i_ext)
578             
579     def mergeType(self, type):
580       L_int = self.getNode('type-list')
581       if L_int is None:
582         error("Catalog.mergeType : 'type-list' is not found")
583         return
584       for t in L_int.childs:
585         if t.attrs["name"] == type.attrs["name"]:
586           t.merge(type)
587           return
588
589       L_int.addChild(type)
590
591 class Member(Tree):
592   def __init__(self, name,type):
593     Tree.__init__(self, 'member')
594     self.setAttrib("name",name)
595     self.setAttrib("type",type)
596
597 class Type(Tree):
598   def __init__(self, name,kind):
599     Tree.__init__(self, 'type')
600     self.setAttrib("name",name)
601     self.setAttrib("kind",kind)
602
603   def merge(self,t):
604     self.setAttrib("kind",t.attrs["kind"])
605
606 class SeqType(Tree):
607   def __init__(self, name,content):
608     Tree.__init__(self, 'sequence')
609     self.setAttrib("name",name)
610     self.setAttrib("content",content)
611
612   def merge(self,t):
613     self.setAttrib("content",t.attrs["content"])
614
615 class StructType(Tree):
616   def __init__(self, name):
617     Tree.__init__(self, 'struct')
618     self.setAttrib("name",name)
619
620   def merge(self,t):
621     #remove childs and replace by t childs
622     self.childs=[]
623     for c in t.childs:
624       self.childs.append(c)
625
626 class ObjType(Tree):
627   def __init__(self, name):
628     Tree.__init__(self, 'objref')
629     self.setAttrib("name",name)
630
631   def merge(self,t):
632     RepoId=t.attrs.get("id")
633     if RepoId:
634       self.setAttrib("id",RepoId)
635     #remove childs and replace by t childs
636     self.childs=[]
637     for c in t.childs:
638       self.childs.append(c)
639
640 # IDL file reader
641
642 ttsMap = {
643     idltype.tk_void:       "void",
644     idltype.tk_short:      "short",
645     idltype.tk_long:       "long",
646     idltype.tk_ushort:     "unsigned short",
647     idltype.tk_ulong:      "unsigned long",
648     idltype.tk_float:      "float",
649     idltype.tk_double:     "double",
650     idltype.tk_boolean:    "boolean",
651     idltype.tk_char:       "char",
652     idltype.tk_octet:      "octet",
653     idltype.tk_any:        "any",
654     idltype.tk_TypeCode:   "CORBA::TypeCode",
655     idltype.tk_Principal:  "CORBA::Principal",
656     idltype.tk_longlong:   "long long",
657     idltype.tk_ulonglong:  "unsigned long long",
658     idltype.tk_longdouble: "long double",
659     idltype.tk_wchar:      "wchar"
660     }
661
662
663 #--------------------------------------------------
664 # class ModuleCatalogVisitor
665 #--------------------------------------------------
666 class ModuleCatalogVisitor (idlvisitor.AstVisitor):
667     
668     def __init__(self, catalog):
669         self.catalog = catalog
670         self.EngineType = 0
671         self.currentScope=None
672         
673     def visitAST(self, node):
674         for n in node.declarations():
675             if n.mainFile():
676               n.accept(self)
677             
678     def visitModule(self, node):
679         self.currentScope=node
680         for n in node.definitions():
681             n.accept(self)
682                 
683     def visitInterface(self, node):
684         if node.mainFile():
685
686             self.EngineType = 0
687             
688             for i in node.inherits():
689                 s = i.scopedName();
690                 if s[0] == "Engines":
691                   if s[1] == "Component":
692                     self.EngineType = 1; break
693                   if s[1] == "Superv_Component":
694                     self.EngineType = 2; break
695                 
696             if self.EngineType:
697               #This interface is a SALOME component
698               Comp = Component(node.identifier())
699             
700               self.currentInterface = Comp.createInterface(node.identifier())
701         
702               for c in node.callables():
703                 if isinstance(c, idlast.Operation):
704                     c.accept(self)
705
706               for c in node.declarations():
707                 if isinstance(c, idlast.Struct):
708                     c.accept(self)
709                 
710               for i in node.comments():
711                 self.currentInterface.comments.append(str(i))
712
713               if self.EngineType == 2:
714                 self.currentInterface.processDataStreams()
715             
716               global nb_components
717               nb_components = nb_components + 1
718               self.catalog.mergeComponent(Comp)
719
720             else:
721               #This interface is not a component : use it as a DataType
722               t=ObjType("/".join(node.scopedName()))
723               for i in node.inherits():
724                 t.addNamedChild("base","/".join(i.scopedName()))
725               self.catalog.mergeType(t)
726
727             self.EngineType = 0
728             
729
730     def visitOperation(self, node):
731
732         self.currentService = self.currentInterface.createService \
733                                        (node.identifier())
734             
735         node.returnType().accept(self)
736         if (self.currentType != "void"):
737             self.currentService.createOutParameter \
738                 ("return", self.currentType)
739             
740         for c in node.parameters():
741             c.accept(self)
742
743         for i in node.comments():
744             self.currentInterface.comments.append(str(i))
745         
746
747     def visitDeclaredType(self, type):
748         name=type.name()
749         scoped_name="/".join(type.scopedName())
750         self.currentType = scoped_name
751             
752     def visitBaseType(self, type):
753         self.currentType = ttsMap[type.kind()]
754     
755     def visitStringType(self, type):
756         self.currentType = "string"
757         
758     def visitParameter(self, node):
759         node.paramType().accept(self)
760         if node.is_in():
761             self.currentService.createInParameter \
762                      (node.identifier(), self.currentType)
763         if node.is_out():
764             self.currentService.createOutParameter \
765                      (node.identifier(), self.currentType)
766         
767     def visitSequenceType(self,type):
768       type.seqType().accept(self)
769       if type.bound() == 0:
770           self.contentType=self.currentType
771           self.currentType = "sequence"
772       else:
773           self.currentType = None
774
775     def visitTypedef(self, node):
776       if node.constrType():
777             node.aliasType().decl().accept(self)
778
779       node.aliasType().accept(self)
780       type  = self.currentType
781       if not type:
782         return
783       decll = []
784       for d in node.declarators():
785             d.accept(self)
786             if self.__result_declarator:
787               decll.append(self.__result_declarator)
788       if type == "sequence":
789         #it's a sequence type
790         for name in decll:
791           scoped_name="/".join(self.currentScope.scopedName()+[name])
792           self.catalog.mergeType(SeqType(scoped_name,self.contentType))
793       #else:
794         #it's an alias
795       #  for name in decll:
796       #    scoped_name="/".join(self.currentScope.scopedName()+[name])
797       #    self.catalog.mergeType(Type(scoped_name,type))
798
799     def visitStruct(self, node):
800       t=StructType("/".join(node.scopedName()))
801       for m in node.members():
802             if m.constrType():
803                 m.memberType().decl().accept(self)
804
805             m.memberType().accept(self)
806             type = self.currentType
807             for d in m.declarators():
808                 d.accept(self)
809                 t.addChild(Member(self.__result_declarator,type))
810
811       self.catalog.mergeType(t)
812
813     def visitDeclarator(self, node):
814         if node.sizes():
815           self.__result_declarator =None
816         else:
817           self.__result_declarator =node.identifier()
818
819 #--------------------------------------------------
820 # parse idl and store xml file
821 #--------------------------------------------------
822 def run(tree, args):
823     
824     CatalogFileName=getParamValue("catalog", "CatalogModulePersonnel.xml", args)
825     if re.compile(".*?.xml$").match(CatalogFileName, 1) is None:
826         CatalogFileName = CatalogFileName + '.xml'
827
828     #=========  Read parameters  ======================    
829     common_data["ICON"]       = getParamValue("icon",       "",                args)
830     common_data["AUTHOR"]     = getParamValue("author",     os.getenv("USER"), args)
831     common_data["VERSION"]    = getParamValue("version",    "1",               args)
832     common_data["COMP_NAME"]  = getParamValue("name",       "",                args) 
833     common_data["COMP_UNAME"] = getParamValue("username",   "",                args)
834     common_data["COMP_TYPE"]  = getParamValue("type",       "OTHER",           args)
835     common_data["COMP_MULT"]  = getParamValue("multistudy", "1",               args)
836     common_data["COMP_IMPL"]  = getParamValue("impltype",   "1",               args)
837
838     print common_data
839     
840     remove_comp = getParamValue("remove", "", args)
841     
842     #==================================================    
843     
844     if (os.path.exists(CatalogFileName)):
845         print "Importing", CatalogFileName
846         C = Catalog(CatalogFileName)
847     else:
848         print "Creating ",CatalogFileName
849         C = Catalog()
850
851     print "Reading idl file"
852     
853     visitor = ModuleCatalogVisitor(C)
854     tree.accept(visitor)
855
856 ##    C.Dump()
857     
858     if remove_comp :
859         C.removeComponent(remove_comp)
860     
861     if (os.path.exists(CatalogFileName)):
862         print "Updating", CatalogFileName
863         CatalogFileName_old = CatalogFileName + '_old'
864         os.rename(CatalogFileName, CatalogFileName_old)
865     else:
866         CatalogFileName_old = ""
867         print "Writing", CatalogFileName
868         
869     CatalogFileName_new = CatalogFileName + '_new'
870     f=open(CatalogFileName_new, 'w')
871     f.write("<?xml version='1.0' encoding='us-ascii' ?>\n\n")
872     C.output_xml(f)
873     f.close()
874
875     os.rename(CatalogFileName_new, CatalogFileName)
876     if ((CatalogFileName_old != "") & os.path.exists(CatalogFileName_old)):
877         os.unlink(CatalogFileName_old)
878         
879     print
880
881
882 if __name__ == "__main__":
883     print
884     print "Usage : omniidl -bIDLparser [-I<catalog files directory>]* -Wbcatalog=<my_catalog.xml>[,icon=<pngfile>][,version=<num>][,author=<name>][,name=<component_name>][,username=<component_username>][,multistudy=<component_multistudy>][,impltype=<implementation type : 0 (python), 1 (C++)>] <file.idl>"
885     print
886
887