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