1 # -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2019 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
29 from xml.sax.handler import *
30 from omniidl import idlast, idltype, idlvisitor, idlutil, output
31 from salome_utils import getUserName
33 # parameters not found in IDL file, user's specified in optional parameters
34 common_data={"AUTHOR" : "",
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+"="
54 res = default_value #initial value
56 s = re.compile(pattern).search(opt)
64 #--------------------------------------------------
66 #--------------------------------------------------
68 print("ERROR : ", message)
71 #--------------------------------------------------
72 # base class implementing tree
73 #--------------------------------------------------
76 def __init__(self, name = '', content = '', key = None):
78 self.content = content
85 def addChild(self, tree):
87 self.childs.append(tree)
91 def addNamedChild(self, name, content = ''):
92 return self.addChild(Tree(name, content))
94 def replaceChild(self, tree):
98 if (i.name == tree.name) & ((i.key is None) | (i.key == tree.key)):
100 self.childs.insert(pos, tree)
104 return self.addChild(tree)
106 def insertFirstChild(self, tree):
108 self.childs.insert(0, tree)
111 def insertFirstNamedChild(self, name, content = ''):
112 return self.insertFirstChild(Tree(name, content))
114 def output_xml(self, f, depth=0):
117 s = ''.ljust(4*depth)
119 for k,v in list(self.attrs.items()):
120 s += ' ' + k + '="' + v + '"'
122 if self.content != '':
125 if len(self.childs) > 0:
130 for i in self.childs:
134 s = '</' + self.name + '>\n'
135 if len(self.childs) > 0 :
136 s = ''.ljust(4*depth) + s
139 def Dump(self, levels=-1, depth=0):
140 #Dumps the tree contents
142 if levels == 0: return
144 s = ''.ljust(4*depth)
145 print(s, self, self.content)
146 for i in self.childs:
147 i.Dump(levels-1, depth+1)
150 #Returns list of the parents
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:
164 if (content is None) | (i.content == content):
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):
176 for i in self.childs:
177 n = i.getNode(name, content, depth-1)
194 def mergeChilds(self, t, list):
195 L_ext = t.getChild(list)
196 L_int = self.getChild(list)
200 for i_ext in L_ext.childs:
202 if k_ext is None: continue
205 for i_int in L_int.childs:
207 if k_int is None: continue
215 L_merge.addChild(i_int)
217 L_merge.addChild(i_ext)
219 self.replaceChild(L_merge)
221 def setAttrib(self, name,value):
222 self.attrs[name]=value
225 #--------------------------------------------------
226 # implements parameter tree
227 #--------------------------------------------------
228 class parameter(Tree):
230 def __init__(self, name=None, mode = 'in', type='', comment='unknown'):
231 Tree.__init__(self, mode + 'Parameter', key=name)
233 if name is None: return
235 self.addNamedChild(mode + 'Parameter-name', name)
236 self.addNamedChild(mode + 'Parameter-type', type)
237 self.addNamedChild(mode + 'Parameter-comment', comment)
242 self.replaceChild(P.getChild(P.mode + 'Parameter-name'))
243 self.replaceChild(P.getChild(P.mode + 'Parameter-type'))
244 C = P.getChild(P.mode + 'Parameter-comment')
245 if C.content != 'unkonwn':
248 #--------------------------------------------------
249 # implements dataStreamParameter tree
250 #--------------------------------------------------
251 class dataStreamParameter(parameter):
253 def __init__(self, name=None, mode='in', type='', dependency='', comment='unknown'):
254 parameter.__init__(self, name, mode, type, comment)
255 if name is None: return
257 self.addNamedChild(mode + 'Parameter-dependency', dependency)
262 parameter.merge(self, P)
263 self.replaceChild(P.getChild(mode + 'Parameter-dependency'))
266 def parseComment(comment):
269 word = spaces + '([a-zA-Z][a-zA-Z0-9_]*)' + spaces
275 ## match : // followed by a 'DataStreamPorts' string,
276 ## the service name, and a list of ports
277 pattern = '// *DataStreamPorts{,1}' + word
278 m = re.match(pattern, comment)
280 ## if there is a match, parse remaining part of comment
283 type = 'DataStreamPorts'
286 sPorts = comment[m.end():]
287 pattern = word + '\('+word+','+word +','+word+'\)' \
288 + spaces + ',{,1}' + spaces
289 while len(sPorts) > 0:
290 ## process next DataStreamPort
291 ## match a definition like xx(a,b,c) with a possible trailing ,
292 ## returns a tuple (xx, a, b, c) and
293 ## the remaining part of input string
294 m = re.match(pattern, sPorts)
296 raise LookupError('format error in DataStreamPort definition : '+sPorts)
297 sPorts = sPorts[m.end():]
298 result.append(m.groups())
300 return type, key, result;
302 #--------------------------------------------------
303 # implements service tree
304 #--------------------------------------------------
307 def __init__(self, name=None, comment = 'unknown'):
309 Tree.__init__(self, 'component-service', key=name)
310 if name is None: return
312 self.addNamedChild('service-name', name)
313 self.addNamedChild('service-author',common_data["AUTHOR"])
314 self.addNamedChild('service-version',common_data["VERSION"])
315 self.addNamedChild('service-comment', comment)
316 self.addNamedChild('service-by-default', "0")
317 self.addNamedChild('inParameter-list')
318 self.addNamedChild('outParameter-list')
319 self.addNamedChild('DataStream-list')
321 def createInParameter(self, name, type):
322 L = self.getChild('inParameter-list')
323 p = parameter(name, 'in', type)
327 def createOutParameter(self, name, type):
328 L = self.getChild('outParameter-list')
329 p = parameter(name, 'out', type)
333 def createDataStreamParameter(self, p):
334 L = self.getChild('DataStream-list')
335 p = dataStreamParameter(p[0], p[2], p[1], p[3])
341 self.replaceChild(S.getChild('service-author'))
342 self.replaceChild(S.getChild('service-version'))
343 self.replaceChild(S.getChild('service-by-default'))
344 C = S.getChild('service-comment')
345 if C.content != 'unkonwn':
348 for L in ['inParameter-list', 'outParameter-list', 'DataStream-list']:
349 self.mergeChilds(S, L)
352 #--------------------------------------------------
353 # implements interface tree
354 #--------------------------------------------------
355 class Interface(Tree):
357 def __init__(self, name=None, comment='unknown'):
359 Tree.__init__(self, key=name)
361 if name is None: return
363 self.addNamedChild('component-interface-name', name)
364 self.addNamedChild('component-interface-comment', comment);
365 self.addNamedChild('component-service-list')
367 def createService(self, name):
368 L = self.getChild('component-service-list')
371 error ("Interface.createService() : 'component-service-list' is not found")
378 def findService(self, key):
379 L = self.getChild('component-service-list')
387 C = S.getChild('component-interface-comment')
388 if C.content != 'unkonwn':
391 self.mergeChilds(I, 'component-service-list')
393 def processDataStreams(self):
394 for sComment in self.comments:
396 type, key, result = parseComment(sComment)
398 if type == 'DataStreamPorts':
399 Service = self.findService(key)
401 raise LookupError('service ' + key + \
402 ' not found in interface : ' + self.key)
404 ## process next DataStreamPort
405 Service.createDataStreamParameter(p)
408 #--------------------------------------------------
409 # implements Component tree
410 #--------------------------------------------------
411 class Component(Tree):
412 def __init__(self, name=None):
413 Tree.__init__(self, 'component', key=name)
414 if name is None: return
416 # ASV : fix for bug PAL8922 (Component name indicated by user in GUI is not taken into account
417 if common_data["COMP_NAME"] != '':
418 self.addNamedChild('component-name', common_data["COMP_NAME"])
420 self.addNamedChild('component-name', name)
422 # ASV : if user name is NOT set, then use component-name instead. Else - default.
423 if common_data["COMP_UNAME"] != '':
424 self.addNamedChild('component-username', common_data["COMP_UNAME"])
426 if common_data["COMP_NAME"] != '':
427 self.addNamedChild('component-username', common_data["COMP_NAME"] )
429 self.addNamedChild('component-username', name)
431 self.addNamedChild('component-type', common_data["COMP_TYPE"])
432 self.addNamedChild('component-author', common_data["AUTHOR"])
433 self.addNamedChild('component-version', common_data["VERSION"])
434 self.addNamedChild('component-comment', 'unknown')
435 self.addNamedChild('component-impltype', common_data["COMP_IMPL"])
436 self.addNamedChild('component-icone', common_data["ICON"])
437 self.addNamedChild('constraint')
438 self.addNamedChild('component-interface-list')
440 def createInterface(self, name):
441 L = self.getChild('component-interface-list')
443 error("createInterface: No component-interface-list is found")
451 for i in ['component-username', 'component-author',
452 'component-type', 'component-icone', 'component-version',
453 'component-impltype', 'constraint']:
455 int = self.getChild(i)
458 elif ext is not None and len(ext.content):
459 int.content = ext.content
461 Cc = C.getChild('component-comment')
462 if Cc.content != 'unkonwn':
463 self.replaceChild(Cc)
465 self.mergeChilds(C, 'component-interface-list')
467 #--------------------------------------------------
468 # implements document tree
469 #--------------------------------------------------
470 class Catalog(ContentHandler, Tree):
471 def __init__(self, filename = None):
476 parser = xml.sax.make_parser()
477 parser.setContentHandler(self)
478 parser.parse(filename)
480 t = self.addNamedChild('begin-catalog')
481 t.addNamedChild('type-list')
482 t.addNamedChild('component-list')
484 n = self.getChild('begin-catalog')
486 error("Catalog.__init__ : No 'begin-catalog' is found!")
488 if n.getChild('path-prefix-list') is None:
489 n.insertFirstNamedChild('path-prefix-list')
490 if n.getChild('type-list') is None:
491 p=n.childs.index(n.getChild('path-prefix-list'))
492 n.childs.insert(p+1,Tree('type-list'))
493 if n.getChild('component-list') is None:
494 n.addNamedChild('component-list')
496 def removeComponent(self, name):
497 complist = self.getNode('component-list')
500 print("Catalog.removeComponent() : 'component-list' is not found")
502 for comp in complist.childs:
503 cname = comp.getChild('component-name')
504 if cname is not None:
505 if cname.content == name:
506 complist.childs.pop(idx)
507 print("Component " + name + " is removed")
510 def startDocument(self):
511 self.list.append(self)
513 def startElement(self, name, attrs):
514 p = self.list[len(self.list)-1]
515 if name == 'component':
516 e = p.addChild(Component())
517 elif name == 'component-interface-name':
518 e = p.addNamedChild(name)
519 elif name == 'component-service':
520 e = p.addChild(Service())
521 elif name == 'inParameter':
522 e = p.addChild(parameter(mode='in'))
523 elif name == 'outParameter':
524 e = p.addChild(parameter(mode='out'))
525 elif name == 'sequence':
526 e = p.addChild(SeqType(attrs["name"],attrs["content"]))
527 elif name == 'objref':
528 e = p.addChild(ObjType(attrs["name"]))
529 elif name == 'struct':
530 e = p.addChild(StructType(attrs["name"]))
532 e = p.addChild(Type(attrs["name"],attrs["kind"]))
533 elif name == 'member':
534 e = p.addChild(Member(attrs["name"],attrs["type"]))
536 e = p.addNamedChild(name)
540 def endElement(self, name):
541 self.buffer = ' '.join(self.buffer.split())
542 p = self.list[len(self.list)-1]
543 p.content = self.buffer
544 if name == 'component':
545 p.key = p.getChild('component-name').content
549 def characters(self, ch):
552 def mergeComponent(self, comp):
554 L_int = self.getNode('component-list')
556 error("Catalog.mergeComponent : 'component-list' is not found")
562 for i_int in L_int.childs:
563 if (i_int.key == n_ext):
568 print(' add component', i_ext.getChild('component-name').content)
569 L_int.addChild(i_ext)
571 print(' replace component', i_ext.getChild('component-name').content)
574 def mergeType(self, type):
575 L_int = self.getNode('type-list')
577 error("Catalog.mergeType : 'type-list' is not found")
579 for t in L_int.childs:
580 if t.attrs["name"] == type.attrs["name"]:
587 def __init__(self, name,type):
588 Tree.__init__(self, 'member')
589 self.setAttrib("name",name)
590 self.setAttrib("type",type)
593 def __init__(self, name,kind):
594 Tree.__init__(self, 'type')
595 self.setAttrib("name",name)
596 self.setAttrib("kind",kind)
599 self.setAttrib("kind",t.attrs["kind"])
602 def __init__(self, name,content):
603 Tree.__init__(self, 'sequence')
604 self.setAttrib("name",name)
605 self.setAttrib("content",content)
608 self.setAttrib("content",t.attrs["content"])
610 class StructType(Tree):
611 def __init__(self, name):
612 Tree.__init__(self, 'struct')
613 self.setAttrib("name",name)
616 #remove childs and replace by t childs
619 self.childs.append(c)
622 def __init__(self, name):
623 Tree.__init__(self, 'objref')
624 self.setAttrib("name",name)
627 RepoId=t.attrs.get("id")
629 self.setAttrib("id",RepoId)
630 #remove childs and replace by t childs
633 self.childs.append(c)
638 idltype.tk_void: "void",
639 idltype.tk_short: "short",
640 idltype.tk_long: "long",
641 idltype.tk_ushort: "unsigned short",
642 idltype.tk_ulong: "unsigned long",
643 idltype.tk_float: "float",
644 idltype.tk_double: "double",
645 idltype.tk_boolean: "boolean",
646 idltype.tk_char: "char",
647 idltype.tk_octet: "octet",
648 idltype.tk_any: "any",
649 idltype.tk_TypeCode: "CORBA::TypeCode",
650 idltype.tk_Principal: "CORBA::Principal",
651 idltype.tk_longlong: "long long",
652 idltype.tk_ulonglong: "unsigned long long",
653 idltype.tk_longdouble: "long double",
654 idltype.tk_wchar: "wchar"
658 #--------------------------------------------------
659 # class ModuleCatalogVisitor
660 #--------------------------------------------------
661 class ModuleCatalogVisitor (idlvisitor.AstVisitor):
663 def __init__(self, catalog):
664 self.catalog = catalog
666 self.currentScope=None
668 def visitAST(self, node):
669 for n in node.declarations():
673 def visitModule(self, node):
674 self.currentScope=node
675 for n in node.definitions():
678 def visitInterface(self, node):
683 for i in node.inherits():
685 if s[0] == "Engines":
686 if s[1] == "EngineComponent":
687 self.EngineType = 1; break
688 if s[1] == "Superv_Component":
689 self.EngineType = 2; break
692 #This interface is a SALOME component
693 Comp = Component(node.identifier())
695 self.currentInterface = Comp.createInterface(node.identifier())
697 for c in node.callables():
698 if isinstance(c, idlast.Operation):
701 for c in node.declarations():
702 if isinstance(c, idlast.Struct):
705 for i in node.comments():
706 self.currentInterface.comments.append(str(i))
708 if self.EngineType == 2:
709 self.currentInterface.processDataStreams()
712 nb_components = nb_components + 1
713 self.catalog.mergeComponent(Comp)
716 #This interface is not a component : use it as a DataType
717 t=ObjType("/".join(node.scopedName()))
718 for i in node.inherits():
719 t.addNamedChild("base","/".join(i.scopedName()))
720 self.catalog.mergeType(t)
725 def visitOperation(self, node):
727 self.currentService = self.currentInterface.createService \
730 node.returnType().accept(self)
731 if (self.currentType != "void"):
732 self.currentService.createOutParameter \
733 ("return", self.currentType)
735 for c in node.parameters():
738 for i in node.comments():
739 self.currentInterface.comments.append(str(i))
742 def visitDeclaredType(self, type):
744 scoped_name="/".join(type.scopedName())
745 self.currentType = scoped_name
747 def visitBaseType(self, type):
748 self.currentType = ttsMap[type.kind()]
750 def visitStringType(self, type):
751 self.currentType = "string"
753 def visitWStringType(self, type):
754 self.currentType = "wstring"
756 def visitParameter(self, node):
757 node.paramType().accept(self)
759 self.currentService.createInParameter \
760 (node.identifier(), self.currentType)
762 self.currentService.createOutParameter \
763 (node.identifier(), self.currentType)
765 def visitSequenceType(self,type):
766 type.seqType().accept(self)
767 if type.bound() == 0:
768 self.contentType=self.currentType
769 self.currentType = "sequence"
771 self.currentType = None
773 def visitTypedef(self, node):
774 if node.constrType():
775 node.aliasType().decl().accept(self)
777 node.aliasType().accept(self)
778 type = self.currentType
782 for d in node.declarators():
784 if self.__result_declarator:
785 decll.append(self.__result_declarator)
786 if type == "sequence":
787 #it's a sequence type
789 scoped_name="/".join(self.currentScope.scopedName()+[name])
790 self.catalog.mergeType(SeqType(scoped_name,self.contentType))
794 # scoped_name="/".join(self.currentScope.scopedName()+[name])
795 # self.catalog.mergeType(Type(scoped_name,type))
797 def visitStruct(self, node):
798 t=StructType("/".join(node.scopedName()))
799 for m in node.members():
801 m.memberType().decl().accept(self)
803 m.memberType().accept(self)
804 type = self.currentType
805 for d in m.declarators():
807 t.addChild(Member(self.__result_declarator,type))
809 self.catalog.mergeType(t)
811 def visitDeclarator(self, node):
813 self.__result_declarator =None
815 self.__result_declarator =node.identifier()
817 #--------------------------------------------------
818 # parse idl and store xml file
819 #--------------------------------------------------
822 CatalogFileName=getParamValue("catalog", "CatalogModulePersonnel.xml", args)
823 if re.compile(".*?.xml$").match(CatalogFileName, 1) is None:
824 CatalogFileName = CatalogFileName + '.xml'
826 #========= Read parameters ======================
827 common_data["ICON"] = getParamValue("icon", "", args)
828 common_data["AUTHOR"] = getParamValue("author", getUserName(), args)
829 common_data["VERSION"] = getParamValue("version", "1", args)
830 common_data["COMP_NAME"] = getParamValue("name", "", args)
831 common_data["COMP_UNAME"] = getParamValue("username", "", args)
832 common_data["COMP_TYPE"] = getParamValue("type", "OTHER", args)
833 common_data["COMP_IMPL"] = getParamValue("impltype", "1", args)
837 remove_comp = getParamValue("remove", "", args)
839 #==================================================
841 if (osp.exists(CatalogFileName)):
842 print("Importing", CatalogFileName)
843 C = Catalog(CatalogFileName)
845 print("Creating ",CatalogFileName)
848 print("Reading idl file")
850 visitor = ModuleCatalogVisitor(C)
856 C.removeComponent(remove_comp)
858 if (osp.exists(CatalogFileName)):
859 print("Updating", CatalogFileName)
860 CatalogFileName_old = CatalogFileName + '_old'
861 os.rename(CatalogFileName, CatalogFileName_old)
863 CatalogFileName_old = ""
864 print("Writing", CatalogFileName)
866 CatalogFileName_new = CatalogFileName + '_new'
867 f=open(CatalogFileName_new, 'w')
868 f.write("<?xml version='1.0' encoding='us-ascii' ?>\n\n")
872 os.rename(CatalogFileName_new, CatalogFileName)
873 if ((CatalogFileName_old != "") & osp.exists(CatalogFileName_old)):
874 os.unlink(CatalogFileName_old)
879 if __name__ == "__main__":
881 print("Usage : omniidl -bIDLparser [-I<catalog files directory>]* -Wbcatalog=<my_catalog.xml>[,icon=<pngfile>][,version=<num>][,author=<name>][,name=<component_name>][,username=<component_username>][,impltype=<implementation type : 0 (python), 1 (C++)>] <file.idl>")