1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
4 # Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
5 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
27 import string, sys, fpformat, re, os
31 from xml.sax.handler import *
32 from omniidl import idlast, idltype, idlvisitor, idlutil, output
33 from salome_utils import getUserName
35 # parameters not found in IDL file, user's specified in optional parameters
36 common_data={"AUTHOR" : "",
48 #--------------------------------------------------
49 # extract value of <param_name> from <args> list
50 # it's proposed that the matching <args> item
51 # looks like <param_name>=<value>, for example,
52 # catalog=/tmp/myxml.xml
53 #--------------------------------------------------
54 def getParamValue( param_name, default_value, args ):
55 pattern="^"+param_name+"="
57 res = default_value #initial value
59 s = re.compile(pattern).search(opt)
67 #--------------------------------------------------
69 #--------------------------------------------------
71 print "ERROR : ", message
74 #--------------------------------------------------
75 # base class implementing tree
76 #--------------------------------------------------
79 def __init__(self, name = '', content = '', key = None):
81 self.content = content
88 def addChild(self, tree):
90 self.childs.append(tree)
94 def addNamedChild(self, name, content = ''):
95 return self.addChild(Tree(name, content))
97 def replaceChild(self, tree):
100 for i in self.childs:
101 if (i.name == tree.name) & ((i.key is None) | (i.key == tree.key)):
103 self.childs.insert(pos, tree)
107 return self.addChild(tree)
109 def insertFirstChild(self, tree):
111 self.childs.insert(0, tree)
114 def insertFirstNamedChild(self, name, content = ''):
115 return self.insertFirstChild(Tree(name, content))
117 def output_xml(self, f, depth=0):
120 s = string.ljust('', 4*depth)
122 for k,v in self.attrs.items():
123 s += ' ' + k + '="' + v + '"'
125 if self.content != '':
128 if len(self.childs) > 0:
133 for i in self.childs:
137 s = '</' + self.name + '>\n'
138 if len(self.childs) > 0 :
139 s = string.ljust('', 4*depth) + s
142 def Dump(self, levels=-1, depth=0):
143 #Dumps the tree contents
145 if levels == 0: return
147 s = string.ljust('', 4*depth)
148 print s, self, self.content
149 for i in self.childs:
150 i.Dump(levels-1, depth+1)
153 #Returns list of the parents
162 def getChild(self, name, content=None):
163 # return child node with a given name
164 # if content == None, don't compare contents
165 for i in self.childs:
167 if (content is None) | (i.content == content):
171 def getNode(self, name, content='', depth=-1):
172 # recursive search of a node with a given name
173 # content == None, don't compare content
174 if (self.name == name):
175 if (content is None) | (self.content == content):
179 for i in self.childs:
180 n = i.getNode(name, content, depth-1)
197 def mergeChilds(self, t, list):
198 L_ext = t.getChild(list)
199 L_int = self.getChild(list)
203 for i_ext in L_ext.childs:
205 if k_ext is None: continue
208 for i_int in L_int.childs:
210 if k_int is None: continue
218 L_merge.addChild(i_int)
220 L_merge.addChild(i_ext)
222 self.replaceChild(L_merge)
224 def setAttrib(self, name,value):
225 self.attrs[name]=value
228 #--------------------------------------------------
229 # implements parameter tree
230 #--------------------------------------------------
231 class parameter(Tree):
233 def __init__(self, name=None, mode = 'in', type='', comment='unknown'):
234 Tree.__init__(self, mode + 'Parameter', key=name)
236 if name is None: return
238 self.addNamedChild(mode + 'Parameter-name', name)
239 self.addNamedChild(mode + 'Parameter-type', type)
240 self.addNamedChild(mode + 'Parameter-comment', comment)
245 self.replaceChild(P.getChild(P.mode + 'Parameter-name'))
246 self.replaceChild(P.getChild(P.mode + 'Parameter-type'))
247 C = P.getChild(P.mode + 'Parameter-comment')
248 if C.content != 'unkonwn':
251 #--------------------------------------------------
252 # implements dataStreamParameter tree
253 #--------------------------------------------------
254 class dataStreamParameter(parameter):
256 def __init__(self, name=None, mode='in', type='', dependency='', comment='unknown'):
257 parameter.__init__(self, name, mode, type, comment)
258 if name is None: return
260 self.addNamedChild(mode + 'Parameter-dependency', dependency)
265 parameter.merge(self, P)
266 self.replaceChild(P.getChild(mode + 'Parameter-dependency'))
269 def parseComment(comment):
272 word = spaces + '([a-zA-Z][a-zA-Z0-9_]*)' + spaces
278 ## match : // followed by a 'DataStreamPorts' string,
279 ## the service name, and a list of ports
280 pattern = '// *DataStreamPorts{,1}' + word
281 m = re.match(pattern, comment)
283 ## if there is a match, parse remaining part of comment
286 type = 'DataStreamPorts'
289 sPorts = comment[m.end():]
290 pattern = word + '\('+word+','+word +','+word+'\)' \
291 + spaces + ',{,1}' + spaces
292 while len(sPorts) > 0:
293 ## process next DataStreamPort
294 ## match a definition like xx(a,b,c) with a possible trailing ,
295 ## returns a tuple (xx, a, b, c) and
296 ## the remaining part of input string
297 m = re.match(pattern, sPorts)
300 'format error in DataStreamPort definition : '+sPorts
301 sPorts = sPorts[m.end():]
302 result.append(m.groups())
304 return type, key, result;
306 #--------------------------------------------------
307 # implements service tree
308 #--------------------------------------------------
311 def __init__(self, name=None, comment = 'unknown'):
313 Tree.__init__(self, 'component-service', key=name)
314 if name is None: return
316 self.addNamedChild('service-name', name)
317 self.addNamedChild('service-author',common_data["AUTHOR"])
318 self.addNamedChild('service-version',common_data["VERSION"])
319 self.addNamedChild('service-comment', comment)
320 self.addNamedChild('service-by-default', "0")
321 self.addNamedChild('inParameter-list')
322 self.addNamedChild('outParameter-list')
323 self.addNamedChild('DataStream-list')
325 def createInParameter(self, name, type):
326 L = self.getChild('inParameter-list')
327 p = parameter(name, 'in', type)
331 def createOutParameter(self, name, type):
332 L = self.getChild('outParameter-list')
333 p = parameter(name, 'out', type)
337 def createDataStreamParameter(self, p):
338 L = self.getChild('DataStream-list')
339 p = dataStreamParameter(p[0], p[2], p[1], p[3])
345 self.replaceChild(S.getChild('service-author'))
346 self.replaceChild(S.getChild('service-version'))
347 self.replaceChild(S.getChild('service-by-default'))
348 C = S.getChild('service-comment')
349 if C.content != 'unkonwn':
352 for L in ['inParameter-list', 'outParameter-list', 'DataStream-list']:
353 self.mergeChilds(S, L)
356 #--------------------------------------------------
357 # implements interface tree
358 #--------------------------------------------------
359 class Interface(Tree):
361 def __init__(self, name=None, comment='unknown'):
363 Tree.__init__(self, key=name)
365 if name is None: return
367 self.addNamedChild('component-interface-name', name)
368 self.addNamedChild('component-interface-comment', comment);
369 self.addNamedChild('component-service-list')
371 def createService(self, name):
372 L = self.getChild('component-service-list')
375 error ("Interface.createService() : 'component-service-list' is not found")
382 def findService(self, key):
383 L = self.getChild('component-service-list')
391 C = S.getChild('component-interface-comment')
392 if C.content != 'unkonwn':
395 self.mergeChilds(I, 'component-service-list')
397 def processDataStreams(self):
398 for sComment in self.comments:
400 type, key, result = parseComment(sComment)
402 if type == 'DataStreamPorts':
403 Service = self.findService(key)
407 ' not found in interface : ' + self.key
409 ## process next DataStreamPort
410 Service.createDataStreamParameter(p)
413 #--------------------------------------------------
414 # implements Component tree
415 #--------------------------------------------------
416 class Component(Tree):
417 def __init__(self, name=None):
418 Tree.__init__(self, 'component', key=name)
419 if name is None: return
421 # ASV : fix for bug PAL8922 (Component name indicated by user in GUI is not taken into account
422 if common_data["COMP_NAME"] != '':
423 self.addNamedChild('component-name', common_data["COMP_NAME"])
425 self.addNamedChild('component-name', name)
427 # ASV : if user name is NOT set, then use component-name instead. Else - default.
428 if common_data["COMP_UNAME"] != '':
429 self.addNamedChild('component-username', common_data["COMP_UNAME"])
431 if common_data["COMP_NAME"] != '':
432 self.addNamedChild('component-username', common_data["COMP_NAME"] )
434 self.addNamedChild('component-username', name)
436 self.addNamedChild('component-type', common_data["COMP_TYPE"])
437 self.addNamedChild('component-author', common_data["AUTHOR"])
438 self.addNamedChild('component-version', common_data["VERSION"])
439 self.addNamedChild('component-comment', 'unknown')
440 self.addNamedChild('component-multistudy', common_data["COMP_MULT"])
441 self.addNamedChild('component-impltype', common_data["COMP_IMPL"])
442 self.addNamedChild('component-icone', common_data["ICON"])
443 self.addNamedChild('constraint')
444 self.addNamedChild('component-interface-list')
446 def createInterface(self, name):
447 L = self.getChild('component-interface-list')
449 error("createInterface: No component-interface-list is found")
457 for i in ['component-username', 'component-author',
458 'component-type', 'component-icone', 'component-version',
459 'component-multistudy', 'component-impltype', 'constraint']:
461 int = self.getChild(i)
464 elif ext is not None and len(ext.content):
465 int.content = ext.content
467 Cc = C.getChild('component-comment')
468 if Cc.content != 'unkonwn':
469 self.replaceChild(Cc)
471 self.mergeChilds(C, 'component-interface-list')
473 #--------------------------------------------------
474 # implements document tree
475 #--------------------------------------------------
476 class Catalog(ContentHandler, Tree):
477 def __init__(self, filename = None):
482 parser = xml.sax.make_parser()
483 parser.setContentHandler(self)
484 parser.parse(filename)
486 t = self.addNamedChild('begin-catalog')
487 t.addNamedChild('type-list')
488 t.addNamedChild('component-list')
490 n = self.getChild('begin-catalog')
492 error("Catalog.__init__ : No 'begin-catalog' is found!")
494 if n.getChild('path-prefix-list') is None:
495 n.insertFirstNamedChild('path-prefix-list')
496 if n.getChild('type-list') is None:
497 p=n.childs.index(n.getChild('path-prefix-list'))
498 n.childs.insert(p+1,Tree('type-list'))
499 if n.getChild('component-list') is None:
500 n.addNamedChild('component-list')
502 def removeComponent(self, name):
503 complist = self.getNode('component-list')
506 print "Catalog.removeComponent() : 'component-list' is not found"
508 for comp in complist.childs:
509 cname = comp.getChild('component-name')
510 if cname is not None:
511 if cname.content == name:
512 complist.childs.pop(idx)
513 print "Component " + name + " is removed"
516 def startDocument(self):
517 self.list.append(self)
519 def startElement(self, name, attrs):
520 p = self.list[len(self.list)-1]
521 if name == 'component':
522 e = p.addChild(Component())
523 elif name == 'component-interface-name':
524 e = p.addNamedChild(name)
525 elif name == 'component-service':
526 e = p.addChild(Service())
527 elif name == 'inParameter':
528 e = p.addChild(parameter(mode='in'))
529 elif name == 'outParameter':
530 e = p.addChild(parameter(mode='out'))
531 elif name == 'sequence':
532 e = p.addChild(SeqType(attrs["name"],attrs["content"]))
533 elif name == 'objref':
534 e = p.addChild(ObjType(attrs["name"]))
535 elif name == 'struct':
536 e = p.addChild(StructType(attrs["name"]))
538 e = p.addChild(Type(attrs["name"],attrs["kind"]))
539 elif name == 'member':
540 e = p.addChild(Member(attrs["name"],attrs["type"]))
542 e = p.addNamedChild(name)
546 def endElement(self, name):
547 self.buffer = string.join(string.split(self.buffer), ' ')
548 p = self.list[len(self.list)-1]
549 p.content = self.buffer
550 if name == 'component':
551 p.key = p.getChild('component-name').content
555 def characters(self, ch):
558 def mergeComponent(self, comp):
560 L_int = self.getNode('component-list')
562 error("Catalog.mergeComponent : 'component-list' is not found")
568 for i_int in L_int.childs:
569 if (i_int.key == n_ext):
574 print ' add component', i_ext.getChild('component-name').content
575 L_int.addChild(i_ext)
577 print ' replace component', i_ext.getChild('component-name').content
580 def mergeType(self, type):
581 L_int = self.getNode('type-list')
583 error("Catalog.mergeType : 'type-list' is not found")
585 for t in L_int.childs:
586 if t.attrs["name"] == type.attrs["name"]:
593 def __init__(self, name,type):
594 Tree.__init__(self, 'member')
595 self.setAttrib("name",name)
596 self.setAttrib("type",type)
599 def __init__(self, name,kind):
600 Tree.__init__(self, 'type')
601 self.setAttrib("name",name)
602 self.setAttrib("kind",kind)
605 self.setAttrib("kind",t.attrs["kind"])
608 def __init__(self, name,content):
609 Tree.__init__(self, 'sequence')
610 self.setAttrib("name",name)
611 self.setAttrib("content",content)
614 self.setAttrib("content",t.attrs["content"])
616 class StructType(Tree):
617 def __init__(self, name):
618 Tree.__init__(self, 'struct')
619 self.setAttrib("name",name)
622 #remove childs and replace by t childs
625 self.childs.append(c)
628 def __init__(self, name):
629 Tree.__init__(self, 'objref')
630 self.setAttrib("name",name)
633 RepoId=t.attrs.get("id")
635 self.setAttrib("id",RepoId)
636 #remove childs and replace by t childs
639 self.childs.append(c)
644 idltype.tk_void: "void",
645 idltype.tk_short: "short",
646 idltype.tk_long: "long",
647 idltype.tk_ushort: "unsigned short",
648 idltype.tk_ulong: "unsigned long",
649 idltype.tk_float: "float",
650 idltype.tk_double: "double",
651 idltype.tk_boolean: "boolean",
652 idltype.tk_char: "char",
653 idltype.tk_octet: "octet",
654 idltype.tk_any: "any",
655 idltype.tk_TypeCode: "CORBA::TypeCode",
656 idltype.tk_Principal: "CORBA::Principal",
657 idltype.tk_longlong: "long long",
658 idltype.tk_ulonglong: "unsigned long long",
659 idltype.tk_longdouble: "long double",
660 idltype.tk_wchar: "wchar"
664 #--------------------------------------------------
665 # class ModuleCatalogVisitor
666 #--------------------------------------------------
667 class ModuleCatalogVisitor (idlvisitor.AstVisitor):
669 def __init__(self, catalog):
670 self.catalog = catalog
672 self.currentScope=None
674 def visitAST(self, node):
675 for n in node.declarations():
679 def visitModule(self, node):
680 self.currentScope=node
681 for n in node.definitions():
684 def visitInterface(self, node):
689 for i in node.inherits():
691 if s[0] == "Engines":
692 if s[1] == "EngineComponent":
693 self.EngineType = 1; break
694 if s[1] == "Superv_Component":
695 self.EngineType = 2; break
698 #This interface is a SALOME component
699 Comp = Component(node.identifier())
701 self.currentInterface = Comp.createInterface(node.identifier())
703 for c in node.callables():
704 if isinstance(c, idlast.Operation):
707 for c in node.declarations():
708 if isinstance(c, idlast.Struct):
711 for i in node.comments():
712 self.currentInterface.comments.append(str(i))
714 if self.EngineType == 2:
715 self.currentInterface.processDataStreams()
718 nb_components = nb_components + 1
719 self.catalog.mergeComponent(Comp)
722 #This interface is not a component : use it as a DataType
723 t=ObjType("/".join(node.scopedName()))
724 for i in node.inherits():
725 t.addNamedChild("base","/".join(i.scopedName()))
726 self.catalog.mergeType(t)
731 def visitOperation(self, node):
733 self.currentService = self.currentInterface.createService \
736 node.returnType().accept(self)
737 if (self.currentType != "void"):
738 self.currentService.createOutParameter \
739 ("return", self.currentType)
741 for c in node.parameters():
744 for i in node.comments():
745 self.currentInterface.comments.append(str(i))
748 def visitDeclaredType(self, type):
750 scoped_name="/".join(type.scopedName())
751 self.currentType = scoped_name
753 def visitBaseType(self, type):
754 self.currentType = ttsMap[type.kind()]
756 def visitStringType(self, type):
757 self.currentType = "string"
759 def visitParameter(self, node):
760 node.paramType().accept(self)
762 self.currentService.createInParameter \
763 (node.identifier(), self.currentType)
765 self.currentService.createOutParameter \
766 (node.identifier(), self.currentType)
768 def visitSequenceType(self,type):
769 type.seqType().accept(self)
770 if type.bound() == 0:
771 self.contentType=self.currentType
772 self.currentType = "sequence"
774 self.currentType = None
776 def visitTypedef(self, node):
777 if node.constrType():
778 node.aliasType().decl().accept(self)
780 node.aliasType().accept(self)
781 type = self.currentType
785 for d in node.declarators():
787 if self.__result_declarator:
788 decll.append(self.__result_declarator)
789 if type == "sequence":
790 #it's a sequence type
792 scoped_name="/".join(self.currentScope.scopedName()+[name])
793 self.catalog.mergeType(SeqType(scoped_name,self.contentType))
797 # scoped_name="/".join(self.currentScope.scopedName()+[name])
798 # self.catalog.mergeType(Type(scoped_name,type))
800 def visitStruct(self, node):
801 t=StructType("/".join(node.scopedName()))
802 for m in node.members():
804 m.memberType().decl().accept(self)
806 m.memberType().accept(self)
807 type = self.currentType
808 for d in m.declarators():
810 t.addChild(Member(self.__result_declarator,type))
812 self.catalog.mergeType(t)
814 def visitDeclarator(self, node):
816 self.__result_declarator =None
818 self.__result_declarator =node.identifier()
820 #--------------------------------------------------
821 # parse idl and store xml file
822 #--------------------------------------------------
825 CatalogFileName=getParamValue("catalog", "CatalogModulePersonnel.xml", args)
826 if re.compile(".*?.xml$").match(CatalogFileName, 1) is None:
827 CatalogFileName = CatalogFileName + '.xml'
829 #========= Read parameters ======================
830 common_data["ICON"] = getParamValue("icon", "", args)
831 common_data["AUTHOR"] = getParamValue("author", getUserName(), args)
832 common_data["VERSION"] = getParamValue("version", "1", args)
833 common_data["COMP_NAME"] = getParamValue("name", "", args)
834 common_data["COMP_UNAME"] = getParamValue("username", "", args)
835 common_data["COMP_TYPE"] = getParamValue("type", "OTHER", args)
836 common_data["COMP_MULT"] = getParamValue("multistudy", "1", args)
837 common_data["COMP_IMPL"] = getParamValue("impltype", "1", args)
841 remove_comp = getParamValue("remove", "", args)
843 #==================================================
845 if (os.path.exists(CatalogFileName)):
846 print "Importing", CatalogFileName
847 C = Catalog(CatalogFileName)
849 print "Creating ",CatalogFileName
852 print "Reading idl file"
854 visitor = ModuleCatalogVisitor(C)
860 C.removeComponent(remove_comp)
862 if (os.path.exists(CatalogFileName)):
863 print "Updating", CatalogFileName
864 CatalogFileName_old = CatalogFileName + '_old'
865 os.rename(CatalogFileName, CatalogFileName_old)
867 CatalogFileName_old = ""
868 print "Writing", CatalogFileName
870 CatalogFileName_new = CatalogFileName + '_new'
871 f=open(CatalogFileName_new, 'w')
872 f.write("<?xml version='1.0' encoding='us-ascii' ?>\n\n")
876 os.rename(CatalogFileName_new, CatalogFileName)
877 if ((CatalogFileName_old != "") & os.path.exists(CatalogFileName_old)):
878 os.unlink(CatalogFileName_old)
883 if __name__ == "__main__":
885 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>"