1 # Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
25 import string, sys, fpformat, re, os
29 from xml.sax.handler import *
30 from omniidl import idlast, idltype, idlvisitor, idlutil, output
32 # parameters not found in IDL file, user's specified in optional parameters
33 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
84 def addChild(self, tree):
86 self.childs.append(tree)
90 def addNamedChild(self, name, content = ''):
91 return self.addChild(Tree(name, content))
93 def replaceChild(self, tree):
97 if (i.name == tree.name) & ((i.key is None) | (i.key == tree.key)):
99 self.childs.insert(pos, tree)
103 return self.addChild(tree)
105 def insertFirstChild(self, tree):
107 self.childs.insert(0, tree)
110 def insertFirstNamedChild(self, name, content = ''):
111 return self.insertFirstChild(Tree(name, content))
113 def output_xml(self, f, depth=0):
116 s = string.ljust('', 4*depth)
117 s += '<' + self.name + '>'
118 if self.content != '':
121 if len(self.childs) > 0:
126 for i in self.childs:
130 s = '</' + self.name + '>\n'
131 if len(self.childs) > 0 :
132 s = string.ljust('', 4*depth) + s
135 def Dump(self, levels=-1, depth=0):
136 #Dumps the tree contents
138 if levels == 0: return
140 s = string.ljust('', 4*depth)
141 print s, self, self.content
142 for i in self.childs:
143 i.Dump(levels-1, depth+1)
146 #Returns list of the parents
155 def getChild(self, name, content=None):
156 # return child node with a given name
157 # if content == None, don't compare contents
158 for i in self.childs:
160 if (content is None) | (i.content == content):
164 def getNode(self, name, content='', depth=-1):
165 # recursive search of a node with a given name
166 # content == None, don't compare content
167 if (self.name == name):
168 if (content is None) | (self.content == content):
172 for i in self.childs:
173 n = i.getNode(name, content, depth-1)
190 def mergeChilds(self, t, list):
191 L_ext = t.getChild(list)
192 L_int = self.getChild(list)
196 for i_ext in L_ext.childs:
198 if k_ext is None: continue
201 for i_int in L_int.childs:
203 if k_int is None: continue
211 L_merge.addChild(i_int)
213 L_merge.addChild(i_ext)
215 self.replaceChild(L_merge)
219 #--------------------------------------------------
220 # implements parameter tree
221 #--------------------------------------------------
222 class parameter(Tree):
224 def __init__(self, name=None, mode = 'in', type='', comment='unknown'):
225 Tree.__init__(self, mode + 'Parameter', key=name)
227 if name is None: return
229 self.addNamedChild(mode + 'Parameter-name', name)
230 self.addNamedChild(mode + 'Parameter-type', type)
231 self.addNamedChild(mode + 'Parameter-comment', comment)
236 self.replaceChild(P.getChild(P.mode + 'Parameter-name'))
237 self.replaceChild(P.getChild(P.mode + 'Parameter-type'))
238 C = P.getChild(P.mode + 'Parameter-comment')
239 if C.content != 'unkonwn':
242 #--------------------------------------------------
243 # implements dataStreamParameter tree
244 #--------------------------------------------------
245 class dataStreamParameter(parameter):
247 def __init__(self, name=None, mode='in', type='', dependency='', comment='unknown'):
248 parameter.__init__(self, name, mode, type, comment)
249 if name is None: return
251 self.addNamedChild(mode + 'Parameter-dependency', dependency)
256 parameter.merge(self, P)
257 self.replaceChild(P.getChild(mode + 'Parameter-dependency'))
260 def parseComment(comment):
263 word = spaces + '([a-zA-Z][a-zA-Z0-9_]*)' + spaces
269 ## match : // followed by a 'DataStreamPorts' string,
270 ## the service name, and a list of ports
271 pattern = '// *DataStreamPorts{,1}' + word
272 m = re.match(pattern, comment)
274 ## if there is a match, parse remaining part of comment
277 type = 'DataStreamPorts'
280 sPorts = comment[m.end():]
281 pattern = word + '\('+word+','+word +','+word+'\)' \
282 + spaces + ',{,1}' + spaces
283 while len(sPorts) > 0:
284 ## process next DataStreamPort
285 ## match a definition like xx(a,b,c) with a possible trailing ,
286 ## returns a tuple (xx, a, b, c) and
287 ## the remaining part of input string
288 m = re.match(pattern, sPorts)
291 'format error in DataStreamPort definition : '+sPorts
292 sPorts = sPorts[m.end():]
293 result.append(m.groups())
295 return type, key, result;
297 #--------------------------------------------------
298 # implements service tree
299 #--------------------------------------------------
302 def __init__(self, name=None, comment = 'unknown'):
304 Tree.__init__(self, 'component-service', key=name)
305 if name is None: return
307 self.addNamedChild('service-name', name)
308 self.addNamedChild('service-author',common_data["AUTHOR"])
309 self.addNamedChild('service-version',common_data["VERSION"])
310 self.addNamedChild('service-comment', comment)
311 self.addNamedChild('service-by-default', "0")
312 self.addNamedChild('inParameter-list')
313 self.addNamedChild('outParameter-list')
314 self.addNamedChild('DataStream-list')
316 def createInParameter(self, name, type):
317 L = self.getChild('inParameter-list')
318 p = parameter(name, 'in', type)
322 def createOutParameter(self, name, type):
323 L = self.getChild('outParameter-list')
324 p = parameter(name, 'out', type)
328 def createDataStreamParameter(self, p):
329 L = self.getChild('DataStream-list')
330 p = dataStreamParameter(p[0], p[2], p[1], p[3])
336 self.replaceChild(S.getChild('service-author'))
337 self.replaceChild(S.getChild('service-version'))
338 self.replaceChild(S.getChild('service-by-default'))
339 C = S.getChild('service-comment')
340 if C.content != 'unkonwn':
343 for L in ['inParameter-list', 'outParameter-list', 'DataStream-list']:
344 self.mergeChilds(S, L)
348 #--------------------------------------------------
349 # implements interface tree
350 #--------------------------------------------------
351 class Interface(Tree):
353 def __init__(self, name=None, comment='unknown'):
355 Tree.__init__(self, key=name)
357 if name is None: return
359 self.addNamedChild('component-interface-name', name)
360 self.addNamedChild('component-interface-comment', comment);
361 self.addNamedChild('component-service-list')
363 def createService(self, name):
364 L = self.getChild('component-service-list')
367 error ("Interface.createService() : 'component-service-list' is not found")
374 def findService(self, key):
375 L = self.getChild('component-service-list')
383 C = S.getChild('component-interface-comment')
384 if C.content != 'unkonwn':
387 self.mergeChilds(I, 'component-service-list')
389 def processDataStreams(self):
390 for sComment in self.comments:
392 type, key, result = parseComment(sComment)
394 if type == 'DataStreamPorts':
395 Service = self.findService(key)
399 ' not found in interface : ' + self.key
401 ## process next DataStreamPort
402 Service.createDataStreamParameter(p)
405 #--------------------------------------------------
406 # implements Component tree
407 #--------------------------------------------------
408 class Component(Tree):
409 def __init__(self, name=None):
410 Tree.__init__(self, 'component', key=name)
411 if name is None: return
413 # ASV : fix for bug PAL8922 (Component name indicated by user in GUI is not taken into account
414 if common_data["COMP_NAME"] != '':
415 self.addNamedChild('component-name', common_data["COMP_NAME"])
417 self.addNamedChild('component-name', name)
419 # ASV : if user name is NOT set, then use component-name instead. Else - default.
420 if common_data["COMP_UNAME"] != '':
421 self.addNamedChild('component-username', common_data["COMP_UNAME"])
423 if common_data["COMP_NAME"] != '':
424 self.addNamedChild('component-username', common_data["COMP_NAME"] )
426 self.addNamedChild('component-username', name)
428 self.addNamedChild('component-type', common_data["COMP_TYPE"])
429 self.addNamedChild('component-author', common_data["AUTHOR"])
430 self.addNamedChild('component-version', common_data["VERSION"])
431 self.addNamedChild('component-comment', 'unknown')
432 self.addNamedChild('component-multistudy', common_data["COMP_MULT"])
433 self.addNamedChild('component-impltype', common_data["COMP_IMPL"])
434 self.addNamedChild('component-icone', common_data["ICON"])
435 self.addNamedChild('constraint')
436 self.addNamedChild('component-interface-list')
438 def createInterface(self, name):
439 L = self.getChild('component-interface-list')
441 error("createInterface: No component-interface-list is found")
449 for i in ['component-username', 'component-author',
450 'component-type', 'component-icone', 'component-version',
451 'component-multistudy', 'component-impltype', 'constraint']:
453 int = self.getChild(i)
456 elif ext is not None and len(ext.content):
457 int.content = ext.content
459 Cc = C.getChild('component-comment')
460 if Cc.content != 'unkonwn':
461 self.replaceChild(Cc)
463 self.mergeChilds(C, 'component-interface-list')
465 #--------------------------------------------------
466 # implements document tree
467 #--------------------------------------------------
468 class Catalog(ContentHandler, Tree):
469 def __init__(self, filename = None):
474 parser = xml.sax.make_parser()
475 parser.setContentHandler(self)
476 parser.parse(filename)
478 t = self.addNamedChild('begin-catalog')
479 t.addNamedChild('component-list')
481 n = self.getChild('begin-catalog')
483 error("Catalog.__init__ : No 'begin-catalog' is found!")
485 if n.getChild('path-prefix-list') is None:
486 n.insertFirstNamedChild('path-prefix-list')
487 if n.getChild('component-list') is None:
488 n.addNamedChild('component-list')
490 def removeComponent(self, name):
491 complist = self.getNode('component-list')
494 print "Catalog.removeComponent() : 'component-list' is not found"
496 for comp in complist.childs:
497 cname = comp.getChild('component-name')
498 if cname is not None:
499 if cname.content == name:
500 complist.childs.pop(idx)
501 print "Component " + name + " is removed"
504 def startDocument(self):
505 self.list.append(self)
507 def startElement(self, name, attrs):
508 p = self.list[len(self.list)-1]
509 if name == 'component':
510 e = p.addChild(Component())
511 elif name == 'component-interface-name':
512 e = p.addNamedChild(name)
513 elif name == 'component-service':
514 e = p.addChild(Service())
515 elif name == 'inParameter':
516 e = p.addChild(parameter(mode='in'))
517 elif name == 'outParameter':
518 e = p.addChild(parameter(mode='out'))
520 e = p.addNamedChild(name)
524 def endElement(self, name):
525 self.buffer = string.join(string.split(self.buffer), ' ')
526 p = self.list[len(self.list)-1]
527 p.content = self.buffer
528 if name == 'component':
529 p.key = p.getChild('component-name').content
533 def characters(self, ch):
536 def mergeComponent(self, comp):
538 L_int = self.getNode('component-list')
540 error("Catalog.mergeComponent : 'component-list' is not found")
546 for i_int in L_int.childs:
547 if (i_int.key == n_ext):
552 print ' add component', i_ext.getChild('component-name').content
553 L_int.addChild(i_ext)
555 print ' replace component', i_ext.getChild('component-name').content
564 idltype.tk_void: "void",
565 idltype.tk_short: "short",
566 idltype.tk_long: "long",
567 idltype.tk_ushort: "unsigned short",
568 idltype.tk_ulong: "unsigned long",
569 idltype.tk_float: "float",
570 idltype.tk_double: "double",
571 idltype.tk_boolean: "boolean",
572 idltype.tk_char: "char",
573 idltype.tk_octet: "octet",
574 idltype.tk_any: "any",
575 idltype.tk_TypeCode: "CORBA::TypeCode",
576 idltype.tk_Principal: "CORBA::Principal",
577 idltype.tk_longlong: "long long",
578 idltype.tk_ulonglong: "unsigned long long",
579 idltype.tk_longdouble: "long double",
580 idltype.tk_wchar: "wchar"
584 #--------------------------------------------------
585 # class ModuleCatalogVisitor
586 #--------------------------------------------------
587 class ModuleCatalogVisitor (idlvisitor.AstVisitor):
589 def __init__(self, catalog):
590 self.catalog = catalog
593 def visitAST(self, node):
594 for n in node.declarations():
597 def visitModule(self, node):
598 for n in node.definitions():
601 def visitInterface(self, node):
607 for i in node.inherits():
609 if ((s[0] == "Engines") & (s[1] == "Component")):
610 self.EngineType = 1; break
612 Comp = Component(node.identifier())
614 self.currentInterface = Comp.createInterface(node.identifier())
616 for c in node.callables():
617 if isinstance(c, idlast.Operation):
620 for c in node.declarations():
621 if isinstance(c, idlast.Struct):
624 for i in node.comments():
625 self.currentInterface.comments.append(str(i))
627 self.currentInterface.processDataStreams()
629 if (self.EngineType):
631 nb_components = nb_components + 1
632 self.catalog.mergeComponent(Comp)
637 def visitOperation(self, node):
639 self.currentService = self.currentInterface.createService \
642 node.returnType().accept(self)
643 if (self.currentType != "void"):
644 self.currentService.createOutParameter \
645 ("return", self.currentType)
647 for c in node.parameters():
650 for i in node.comments():
651 self.currentInterface.comments.append(str(i))
654 def visitDeclaredType(self, type):
655 self.currentType = type.name()
657 def visitBaseType(self, type):
658 self.currentType = ttsMap[type.kind()]
660 def visitStringType(self, type):
661 self.currentType = "string"
663 def visitParameter(self, node):
664 node.paramType().accept(self)
666 self.currentService.createInParameter \
667 (node.identifier(), self.currentType)
669 self.currentService.createOutParameter \
670 (node.identifier(), self.currentType)
672 #--------------------------------------------------
673 # parse idl and store xml file
674 #--------------------------------------------------
677 CatalogFileName=getParamValue("catalog", "CatalogModulePersonnel.xml", args)
678 if re.compile(".*?.xml$").match(CatalogFileName, 1) is None:
679 CatalogFileName = CatalogFileName + '.xml'
681 #========= Read parameters ======================
682 common_data["ICON"] = getParamValue("icon", "", args)
683 common_data["AUTHOR"] = getParamValue("author", os.getenv("USER"), args)
684 common_data["VERSION"] = getParamValue("version", "1", args)
685 common_data["COMP_NAME"] = getParamValue("name", "", args)
686 common_data["COMP_UNAME"] = getParamValue("username", "", args)
687 common_data["COMP_TYPE"] = getParamValue("type", "OTHER", args)
688 common_data["COMP_MULT"] = getParamValue("multistudy", "1", args)
689 common_data["COMP_IMPL"] = getParamValue("impltype", "1", args)
693 remove_comp = getParamValue("remove", "", args)
695 #==================================================
697 if (os.path.exists(CatalogFileName)):
698 print "Importing", CatalogFileName
699 C = Catalog(CatalogFileName)
701 print "Creating ",CatalogFileName
704 print "Reading idl file"
706 visitor = ModuleCatalogVisitor(C)
712 C.removeComponent(remove_comp)
714 if (os.path.exists(CatalogFileName)):
715 print "Updating", CatalogFileName
716 CatalogFileName_old = CatalogFileName + '_old'
717 os.rename(CatalogFileName, CatalogFileName_old)
719 CatalogFileName_old = ""
720 print "Writing", CatalogFileName
722 CatalogFileName_new = CatalogFileName + '_new'
723 f=open(CatalogFileName_new, 'w')
724 f.write("<?xml version='1.0' encoding='us-ascii' ?>\n\n")
728 os.rename(CatalogFileName_new, CatalogFileName)
729 if ((CatalogFileName_old != "") & os.path.exists(CatalogFileName_old)):
730 os.unlink(CatalogFileName_old)
735 if __name__ == "__main__":
737 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>"