Salome HOME
This commit was generated by cvs2git to track changes on a CVS vendor
[modules/kernel.git] / src / ModuleGenerator / IDLparser.py
1 import string, sys, fpformat, re, os
2 import xml.sax
3 import pdb
4
5 from xml.sax.handler import *
6 from omniidl import idlast, idltype, idlvisitor, idlutil, output
7
8 #values of this map are used in some nodes defenition
9 common_data={"AUTHOR"   : "",
10              "ICON"     : "",
11              "VERSION"  : "",
12              "COMP_TYPE": "",
13              "COMP_NAME": "",
14              "COMP_MULT": "1"
15              }
16
17 #--------------------------------------------------
18 # print error message
19 #--------------------------------------------------
20 def error (message):
21     print "ERROR : ", message
22
23
24 #--------------------------------------------------
25 # base class implementing tree
26 #--------------------------------------------------
27 class Tree:
28     
29     def __init__(self, name = '', content = ''):
30         self.name = name
31         self.content = content
32         self.parent = None
33         self.childs = []
34         
35     def addChild(self, tree):
36         if tree is not None: 
37             self.childs.append(tree)
38             tree.parent = self
39         return tree
40
41     def addNamedChild(self, name, content = ''):
42         return self.addChild(Tree(name, content))
43
44     def replaceChild(self, tree):
45          if tree is not None:
46             pos = 0
47             for i in self.childs:
48                 if i.name == tree.name:
49                     self.childs.pop(pos)
50                     self.childs.insert(pos, tree)
51                     return tree
52                 pos += 1
53
54          return self.addChild(tree)
55        
56     def insertFirstChild(self, tree):
57         if tree is not None:
58             self.childs.insert(0, tree)
59         return tree
60     
61     def insertFirstNamedChild(self, name, content = ''):
62         return self.insertFirstChild(Tree(name, content))
63
64     def output_xml(self, f, depth=0):
65         d = depth
66         if self.name != '':
67             s = string.ljust('', 4*depth)
68             s += '<' + self.name + '>'
69             if self.content != '':
70                 s +=  self.content
71             else:
72                 if len(self.childs) > 0:
73                     s += '\n'
74             f.write(s)
75             d +=  1
76             
77         for i in self.childs:
78             i.output_xml(f, d)
79             
80         if self.name != '':
81             s = '</' + self.name + '>\n'
82             if len(self.childs) > 0 :
83                 s = string.ljust('', 4*depth) + s
84             f.write(s)
85
86     def Dump(self, levels=-1, depth=0):
87         #Dumps the tree contents
88         
89         if levels == 0: return
90         
91         s = string.ljust('', 4*depth)
92         print s, self, self.content
93         for i in self.childs:
94             i.Dump(levels-1, depth+1)
95
96     def parents(self):
97         #Returns list of the parents
98         l = []
99         p = self.parent
100         while p:
101             l.append(p)
102             l.append(p.name)
103             p = p.parent
104         return l
105         
106     def getChild(self, name, content=None):
107
108         # content == None, don't compare content
109         for i in self.childs:
110             if (i.name == name):
111                 if (content is None) | (i.content == content):
112                     return i
113         return None
114
115     def getNode(self, name, content='', depth=-1):
116
117         # recursive search
118         # content == None, don't compare content
119         if (self.name == name):
120             if (content is None) | (self.content == content):
121                 return self
122             
123         if (depth != 0):
124             for i in self.childs:
125                 n = i.getNode(name, content, depth-1)
126                 if n:  return n #return a value 
127             
128         return None
129
130     def __repr__(self):
131         s = '<'
132         if self.name != '':
133             s += self.name
134         else:
135             s +=  'None'
136         s += '>'
137         return s
138
139     def merge(self, t):
140         pass
141     
142 #--------------------------------------------------
143 # implements inParameter tree
144 #--------------------------------------------------
145 class inParameter(Tree):
146     
147     def __init__(self, name=None, type='', comment=''):
148         Tree.__init__(self, 'inParameter')
149         if name is None:  return
150         
151         self.addNamedChild('inParameter-type', type)
152         self.addNamedChild('inParameter-name', name)
153         self.addNamedChild('inParameter-comment', comment)
154             
155     def merge(self, P):
156
157         T = P.getChild('inParameter-type')
158         self.replaceChild(T)
159     
160 #--------------------------------------------------
161 # implements outParameter tree
162 #--------------------------------------------------
163 class outParameter(Tree):
164     
165     def __init__(self, name=None, type='', comment = ''):
166         
167         Tree.__init__(self, 'outParameter')
168         if name is None:  return
169         
170         self.addNamedChild('outParameter-type', type)
171         self.addNamedChild('outParameter-name', name)
172         self.addNamedChild('outParameter-comment', comment)
173             
174     def merge(self, P):
175
176         T = P.getChild('outParameter-type')
177         self.replaceChild(T)
178     
179 #--------------------------------------------------
180 # implements service tree
181 #--------------------------------------------------
182 class Service(Tree):
183     
184     def __init__(self, name=None):
185         
186         Tree.__init__(self, 'component-service')
187         if name is None:  return
188         
189         self.addNamedChild('service-name', name)
190         self.addNamedChild('service-author',common_data["AUTHOR"])
191         self.addNamedChild('service-version',common_data["VERSION"])
192         self.addNamedChild('service-comment')
193         self.addNamedChild('service-by-default', "0")
194         self.addNamedChild('inParameter-list')
195         self.addNamedChild('outParameter-list')
196             
197     def createInParameter(self, name, type):
198         L = self.getChild('inParameter-list')
199         if L is None:
200             error ("Service.createInParameter() : 'inParameter-list' is not found"); return None;
201         p = inParameter(name, type)
202         L.addChild(p)
203         return p
204     
205     def createOutParameter(self, name, type):
206         L = self.getChild('outParameter-list')
207         if L is None:
208             error ("Service.createOutParameter() : 'outParameter-list' is not found"); return None;
209         p = outParameter(name, type)
210         L.addChild(p)
211         return p
212
213
214     def merge(self, S):
215         
216         L_ext = S.getChild('inParameter-list')
217         L_int = self.getChild('inParameter-list')
218
219         if L_ext is not None and L_int is not None:
220
221             L_merge = Tree('inParameter-list')
222         
223             for i_ext in L_ext.childs:
224                 # i_ext = <inParameter>
225                 n_ext = i_ext.getChild('inParameter-name')
226                 if n_ext is None:  continue
227                 present = 0
228             
229                 for i_int in L_int.childs:
230                     # i_int = <inParameter>
231                     n_int = i_int.getChild('inParameter-name')
232                     
233                     if n_int is None:  continue
234                     
235                     if (n_int.content == n_ext.content):
236                         present = 1
237                         break;
238                 
239                 if present :
240                         i_int.merge(i_ext)
241                         L_merge.addChild(i_int)
242                 else:
243                         L_merge.addChild(i_ext)
244                         
245             self.replaceChild(L_merge)
246             
247         else : error("Service.merge(): 'inParameter-list' is not found") #either L_ext or  L_int is None
248             
249         L_ext = S.getChild('outParameter-list')
250         L_int = self.getChild('outParameter-list')
251
252         if L_ext is None or L_int is None:
253             error ("Service.merge() : 'outParameter-list' is not found")
254             
255         L_merge = Tree('outParameter-list')
256         
257         for i_ext in L_ext.childs:
258             #i_ext = <outParameter>
259             present = 0
260             n_ext = i_ext.getChild('outParameter-name')
261             if n_ext is None:   continue
262             for i_int in L_int.childs:
263                 n_int = i_int.getChild('outParameter-name')
264                 if n_int is None:  continue
265                 if (n_int.content == n_ext.content):
266                     present = 1
267                     break;
268                 
269             if present :
270                 i_int.merge(i_ext)
271                 L_merge.addChild(i_int)
272             else:
273                 L_merge.addChild(i_ext)
274                 
275         self.replaceChild(L_merge)
276
277
278 #--------------------------------------------------
279 # implements interface tree
280 #--------------------------------------------------
281 class Interface(Tree):
282     
283     def __init__(self, name=None):
284                
285         Tree.__init__(self)
286
287         if name is None:  return
288         
289         self.addNamedChild('component-interface-name', name)
290         self.addNamedChild('component-interface-comment');
291         self.addNamedChild('component-service-list')
292             
293     def createService(self, name):
294         L = self.getChild('component-service-list')
295
296         if L is None:
297             error ("Interface.createService() : 'component-service-list' is not found")
298             return None
299
300         s = Service(name)
301         L.addChild(s)
302         return s
303
304     def merge(self, I):
305
306         L_ext = I.getChild('component-service-list')
307         L_int = self.getChild('component-service-list')
308       
309         if L_ext is None or L_int is None:
310            error("Interface.merge() : 'component-service-list' is not found!")
311            return
312        
313         L_merge = Tree('component-service-list')
314         
315         for i_ext in L_ext.childs:
316             
317             present = 0
318             n_ext = i_ext.getChild('service-name')
319             if n_ext is None: continue
320             
321             for i_int in L_int.childs:
322                 n_int = i_int.getChild('service-name')
323                 if n_int is None:  continue
324                 if (n_int.content == n_ext.content):
325                     present = 1
326                     break;
327                 
328             if present == 0:
329                 i_int.merge(i_ext)
330                 L_merge.addChild(i_int)
331             else:
332                 L_merge.addChild(i_ext)
333                 
334         self.replaceChild(L_merge)
335
336
337 #--------------------------------------------------
338 # implements Component tree
339 #--------------------------------------------------
340 class Component(Tree):
341     def __init__(self, name=None):
342         Tree.__init__(self, 'component')
343
344         if name is None: return
345         
346         self.addNamedChild('component-name', name)
347         self.addNamedChild('component-type',common_data["COMP_TYPE"])
348         self.addNamedChild('component-author',common_data["AUTHOR"])
349         self.addNamedChild('component-version',common_data["VERSION"])
350         self.addNamedChild('component-comment')
351         self.addNamedChild('component-multistudy', common_data["COMP_MULT"])
352         self.addNamedChild('component-icone',common_data["ICON"])
353         self.addNamedChild('constraint')
354         self.addNamedChild('component-interface-list')
355             
356     def createInterface(self, name):
357         L = self.getChild('component-interface-list')
358         if L is None:
359             error("createInterface: No component-interface-list is found")
360             return None
361         i = Interface(name)
362         L.addChild(i)
363         return i
364
365     def merge(self, C):
366         ext=C.getChild('component-author')
367         int=self.getChild('component-author')
368         if int is not None  and  ext is not None  and  len(ext.content):
369             int.content = ext.content
370             
371         ext=C.getChild('component-type')
372         int=self.getChild('component-type')
373         if int is not None  and  ext is not None  and  len(ext.content):
374             int.content = ext.content
375
376         ext=C.getChild('component-icone')
377         int=self.getChild('component-icone')
378         if int is not None  and  ext is not None  and  len(ext.content):
379             int.content = ext.content
380
381         ext=C.getChild('component-version')
382         int=self.getChild('component-version')
383         if int is not None  and  ext is not None  and  len(ext.content):
384             int.content = ext.content
385
386         ext=C.getChild('component-comment')
387         int=self.getChild('component-comment')
388         if int is not None  and  ext is not None  and  len(ext.content):
389             int.content = ext.content
390
391         ext=C.getChild('component-multistudy')
392         int=self.getChild('component-multistudy')
393         if int is not None  and  ext is not None  and  len(ext.content):
394             int.content = ext.content
395             
396         ext=C.getChild('constraint')
397         int=self.getChild('constraint')
398         if int is not None  and  ext is not None  and  len(ext.content):
399             int.content = ext.content
400              
401         L_ext = C.getChild('component-interface-list')
402         L_int = self.getChild('component-interface-list')
403         if L_ext is None or L_int is None:
404             error("Component.merge : No component-interface-list is found")
405             return
406         L_merge = Tree('component-interface-list')
407         
408         for i_ext in L_ext.childs:
409             present = 0
410             n_ext = i_ext.getChild('component-interface-name')
411
412             if n_ext is None:  continue
413             
414             for i_int in L_int.childs:
415                 n_int = i_int.getChild('component-interface-name')
416                 if n_int is None:  continue
417                 if (n_int.content == n_ext.content):
418                     present = 1
419                     break;
420                 
421             if present :
422                 i_int.merge(i_ext)
423                 L_merge.addChild(i_int)
424             else:
425                 L_merge.addChild(i_ext)
426                 
427         self.replaceChild(L_merge)
428     
429 #--------------------------------------------------
430 # implements document tree
431 #--------------------------------------------------
432 class Catalog(ContentHandler, Tree):
433     def __init__(self, filename = None):
434         Tree.__init__(self)
435         self.buffer = ''
436         self.list = []
437         if (filename):
438             parser = xml.sax.make_parser()
439             parser.setContentHandler(self)
440             parser.parse(filename)
441         else:
442             t = self.addNamedChild('begin-catalog')
443             t.addNamedChild('component-list')
444
445         n = self.getChild('begin-catalog')
446         if n is None:
447             error("Catalog.__init__ : No 'begin-catalog' is found!")
448             return
449         if n.getChild('path-prefix-list') is None:
450             n.insertFirstNamedChild('path-prefix-list')
451         if n.getChild('component-list') is None:
452             n.addNamedChild('component-list')
453             
454     def removeComponent(self, name):
455         complist = self.getNode('component-list')
456         idx = 0
457         if complist is None:
458             print "Catalog.removeComponent() : 'component-list' is not found"
459             return
460         for comp in complist.childs:
461             cname = comp.getChild('component-name')
462             if cname is not None:
463                 if cname.content == name:
464                     complist.childs.pop(idx)
465                     print "Component " + name + " is removed"
466             idx += 1       
467  
468     def startDocument(self):
469         self.list.append(self)
470     
471     def startElement(self, name, attrs):
472         p = self.list[len(self.list)-1]
473
474         if name == 'component':
475             e = p.addChild(Component())
476         elif name == 'component-interface-name':
477             e = p.addNamedChild(name)
478         elif name == 'component-service':
479             e = p.addChild(Service())
480         elif name == 'inParameter':
481             e = p.addChild(inParameter())
482         elif name == 'outParameter':
483             e = p.addChild(outParameter())
484         else:
485             e = p.addNamedChild(name)
486         self.list.append(e)
487         self.buffer = ''
488         
489     def endElement(self, name):
490         self.buffer = string.join(string.split(self.buffer), ' ')
491         p = self.list[len(self.list)-1]
492         p.content = self.buffer
493         self.buffer = ''
494         e = self.list.pop()
495
496         
497     def characters(self, ch):
498         self.buffer += ch
499
500     def mergeComponent(self, comp):
501         
502         L_int = self.getNode('component-list')
503         if   L_int is None:
504             error("Catalog.mergeComponent : 'component-list' is not found")
505             return
506         
507         i_ext = comp
508         present = 0
509         n_ext = i_ext.getChild('component-name')
510         if n_ext is None:
511             error("Catalog.mergeComponent : 'component-name' is not found")
512             return
513         for i_int in L_int.childs:
514             n_int = i_int.getChild('component-name')
515             if n_int is None:  continue
516             
517             if (n_int.content == n_ext.content):
518                 present = 1
519                 break;
520                 
521         if present == 0:
522             print '   add component', n_ext.content
523             L_int.addChild(i_ext)
524         else:
525             print '   replace component', n_ext.content
526             i_int.merge(i_ext)
527             
528
529             
530
531 # IDL file reader
532
533 ttsMap = {
534     idltype.tk_void:       "void",
535     idltype.tk_short:      "short",
536     idltype.tk_long:       "long",
537     idltype.tk_ushort:     "unsigned short",
538     idltype.tk_ulong:      "unsigned long",
539     idltype.tk_float:      "float",
540     idltype.tk_double:     "double",
541     idltype.tk_boolean:    "boolean",
542     idltype.tk_char:       "char",
543     idltype.tk_octet:      "octet",
544     idltype.tk_any:        "any",
545     idltype.tk_TypeCode:   "CORBA::TypeCode",
546     idltype.tk_Principal:  "CORBA::Principal",
547     idltype.tk_longlong:   "long long",
548     idltype.tk_ulonglong:  "unsigned long long",
549     idltype.tk_longdouble: "long double",
550     idltype.tk_wchar:      "wchar"
551     }
552
553
554 #--------------------------------------------------
555 # class ModuleCatalogVisitor
556 #--------------------------------------------------
557 class ModuleCatalogVisitor (idlvisitor.AstVisitor):
558     
559     def __init__(self, catalog):
560         self.catalog = catalog
561         self.EngineType = 0
562         
563     def visitAST(self, node):
564         for n in node.declarations():
565             n.accept(self)
566             
567     def visitModule(self, node):
568         for n in node.definitions():
569             n.accept(self)
570                 
571     def visitInterface(self, node):
572         if node.mainFile():
573
574             self.EngineType = 0
575             
576             for i in node.inherits():
577                 s = i.scopedName();
578                 if ((s[0] == "Engines") & (s[1] == "Component")):
579                     self.EngineType = 1; break
580                 
581             if common_data["COMP_NAME"] :  Comp = Component(common_data["COMP_NAME"])
582             else :  Comp = Component(node.identifier())
583             
584             self.currentInterface = Comp.createInterface(node.identifier())
585         
586             for c in node.callables():
587                 if isinstance(c, idlast.Operation):
588                     c.accept(self)
589
590             if (self.EngineType):
591                 self.catalog.mergeComponent(Comp)
592
593             self.EngineType = 0
594             
595     def visitOperation(self, node):
596
597         self.currentService = self.currentInterface.createService \
598                                        (node.identifier())
599         
600         for c in node.parameters():
601             c.accept(self)
602             
603         node.returnType().accept(self)
604         if (self.currentType != "void"):
605             self.currentService.createOutParameter \
606                 ("return", self.currentType)
607         
608
609     def visitDeclaredType(self, type):
610         self.currentType = type.name()
611             
612     def visitBaseType(self, type):
613         self.currentType = ttsMap[type.kind()]
614     
615     def visitStringType(self, type):
616         self.currentType = "string"
617         
618     def visitParameter(self, node):
619         node.paramType().accept(self)
620         if node.is_in():
621             self.currentService.createInParameter \
622                      (node.identifier(), self.currentType)
623         if node.is_out():
624             self.currentService.createOutParameter \
625                      (node.identifier(), self.currentType)
626         
627 #--------------------------------------------------
628 # extract value of <param_name> from <args> list
629 # it's proposed that the matching <args> item
630 # looks like <param_name>=<value>, for example,
631 # catalog=/tmp/myxml.xml
632 #--------------------------------------------------
633 def getParamValue( param_name, args ):
634     pattern="^"+param_name+"="
635
636     res = ""        #initial value
637     for opt in args:
638         s = re.compile(pattern).search(opt)
639         if s:
640             res = opt[s.end():]
641             break     #found
642
643     return res    
644
645 #--------------------------------------------------
646 # parse idl and store xml file
647 #--------------------------------------------------
648 def run(tree, args):
649     CatalogFileName=getParamValue("catalog",args)
650     if CatalogFileName is None:
651         CatalogFileName = 'CatalogModulePersonnel.xml'
652     
653     if (re.compile(".*?.xml$").match(CatalogFileName, 1) is None):
654         CatalogFileName = CatalogFileName + '.xml'
655
656     #=========  Read parameters  ======================    
657     common_data["ICON"] = getParamValue("icon",args)              # get icon file
658
659     common_data["AUTHOR"] = getParamValue("author",args)          # get author name
660     if common_data["AUTHOR"] is None:   common_data["AUTHOR"] = os.getenv("USER");
661     
662     common_data["VERSION"] = getParamValue("version",args)        # get version
663
664     common_data["COMP_NAME"] = getParamValue("name",args)         # get icon file
665
666     val = getParamValue("type",args)                              # get icon file
667     if val:   common_data["COMP_TYPE"] = val
668
669     val = getParamValue("multistudy",args)                        # get icon file
670     if val :    common_data["COMP_MULT"]  = val
671
672     remove_comp = getParamValue("remove", args)
673     
674     #==================================================    
675     
676     if (os.path.exists(CatalogFileName)):
677         print "Importing", CatalogFileName
678         C = Catalog(CatalogFileName)
679     else:
680         print "Warning : ",CatalogFileName, " was not found."
681         C = Catalog()
682         
683     print "Reading idl file"
684     
685     visitor = ModuleCatalogVisitor(C)
686     tree.accept(visitor)
687
688     if remove_comp :
689         C.removeComponent(remove_comp)
690     
691     if (os.path.exists(CatalogFileName)):
692         print "Updating", CatalogFileName
693         CatalogFileName_old = CatalogFileName + '_old'
694         os.rename(CatalogFileName, CatalogFileName_old)
695     else:
696         CatalogFileName_old = ""
697         print "Writing", CatalogFileName
698         
699     CatalogFileName_new = CatalogFileName + '_new'
700     f=open(CatalogFileName_new, 'w')
701     f.write("<?xml version='1.0' encoding='us-ascii' ?>\n\n")
702     C.output_xml(f)
703     f.close()
704
705     os.rename(CatalogFileName_new, CatalogFileName)
706     if ((CatalogFileName_old != "") & os.path.exists(CatalogFileName_old)):
707         os.unlink(CatalogFileName_old)
708         
709     print
710
711
712 if __name__ == "__main__":
713     print
714     print "Usage : omniidl -bIDLparser -Wbcatalog=<my_catalog.xml>[,icon=<pngfile>][,version=<num>][,author=<name>][,name=<component_name>][,multistudy=<component_multistudy>][,remove=component_name] <file.idl>"
715     print