Salome HOME
Use getPortNumber from salome_utils to
[modules/kernel.git] / bin / launchConfigureParser.py
1 #  -*- coding: iso-8859-1 -*-
2 #  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
3 #
4 #  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
5 #  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 #
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.
11 #
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.
16 #
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
20 #
21 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 #
23
24 import os, glob, string, sys, re
25 import xml.sax
26 import optparse
27 import types
28
29 # names of tags in XML configuration file
30 doc_tag = "document"
31 sec_tag = "section"
32 par_tag = "parameter"
33 import_tag = "import"
34
35 # names of attributes in XML configuration file
36 nam_att = "name"
37 val_att = "value"
38
39 # certain values in XML configuration file ("launch" section)
40 lanch_nam      = "launch"
41 help_nam       = "help"
42 gui_nam        = "gui"
43 splash_nam     = "splash"
44 logger_nam     = "logger"
45 xterm_nam      = "xterm"
46 file_nam       = "file"
47 portkill_nam   = "portkill"
48 killall_nam    = "killall"
49 modules_nam    = "modules"
50 embedded_nam   = "embedded"
51 standalone_nam = "standalone"
52 key_nam        = "key"
53 terminal_nam   = "terminal"
54 interp_nam     = "interp"
55 except_nam     = "noexcepthandler"
56 terminal_nam   = "terminal"
57 pinter_nam     = "pinter"
58 batch_nam      = "batch"
59 test_nam       = "test"
60 play_nam       = "play"
61 gdb_session_nam = "gdb_session"
62 ddd_session_nam = "ddd_session"
63 valgrind_session_nam = "valgrind_session"
64 shutdown_servers_nam = "shutdown_servers"
65
66 # values in XML configuration file giving specific module parameters (<module_name> section)
67 # which are stored in opts with key <module_name>_<parameter> (eg SMESH_plugins)
68 plugins_nam    = "plugins"
69
70 # values passed as arguments, NOT read from XML config file, but set from within this script
71 appname_nam    = "appname"
72 port_nam       = "port"
73 salomeappname  = "SalomeApp"
74 script_nam     = "pyscript"
75
76 # possible choices for the "embedded" and "standalone" parameters
77 embedded_choices   = [ "registry", "study", "moduleCatalog", "cppContainer", "SalomeAppEngine" ]
78 standalone_choices = [ "registry", "study", "moduleCatalog", "cppContainer", "pyContainer"]
79
80 # values of boolean type (must be '0' or '1').
81 # xml_parser.boolValue() is used for correct setting
82 boolKeys = ( gui_nam, splash_nam, logger_nam, file_nam, xterm_nam, portkill_nam, killall_nam, except_nam, pinter_nam, shutdown_servers_nam )
83 intKeys = ( interp_nam, )
84
85 # values of list type
86 listKeys = ( embedded_nam, key_nam, modules_nam, standalone_nam, plugins_nam )
87
88 ###
89 # Get the application version
90 # Uses GUI_ROOT_DIR (or KERNEL_ROOT_DIR in batch mode) +/bin/salome/VERSION file
91 ###
92 def version():
93     try:
94         filename = None
95         root_dir = os.environ.get( 'KERNEL_ROOT_DIR', '' ) # KERNEL_ROOT_DIR or "" if not found
96         if root_dir and os.path.exists( root_dir + "/bin/salome/VERSION" ):
97             filename = root_dir + "/bin/salome/VERSION"
98         root_dir = os.environ.get( 'GUI_ROOT_DIR', '' )    # GUI_ROOT_DIR "" if not found
99         if root_dir and os.path.exists( root_dir + "/bin/salome/VERSION" ):
100             filename = root_dir + "/bin/salome/VERSION"
101         if filename:
102             str = open( filename, "r" ).readline() # str = "THIS IS SALOME - SALOMEGUI VERSION: 3.0.0"
103             match = re.search( r':\s+([a-zA-Z0-9.]+)\s*$', str )
104             if match :
105                 return match.group( 1 )
106     except:
107         pass
108     return ''
109
110 ###
111 # Calculate and return configuration file unique ID
112 # For example: for SALOME version 3.1.0a1 the id is 300999701
113 ###
114 def version_id( fname ):
115     vers = fname.split(".")
116     major   = int(vers[0])
117     minor   = int(vers[1])
118     mr = re.search(r'^([0-9]+)([A-Za-z]?)([0-9]*)',vers[2])
119     release = dev = 0
120     if mr:
121         release = int(mr.group(1))
122         dev1 = dev2 = 0
123         if len(mr.group(2)): dev1 = ord(mr.group(2))
124         if len(mr.group(3)): dev2 = int(mr.group(3))
125         dev = dev1 * 100 + dev2
126     else:
127         return None
128     ver = major
129     ver = ver * 100 + minor
130     ver = ver * 100 + release
131     ver = ver * 10000
132     if dev > 0: ver = ver - 10000 + dev
133     return ver
134
135 ###
136 # Get user configuration file name
137 ###
138 def userFile(appname):
139     v = version()
140     if not v:
141         return ""        # not unknown version
142     if sys.platform == "win32":
143       filename = "%s\%s.xml.%s" % (os.environ['HOME'], appname, v)
144     else:
145       filename = "%s/.%src.%s" % (os.environ['HOME'], appname, v)
146     if os.path.exists(filename):
147         return filename  # user preferences file for the current version exists
148     # initial id
149     id0 = version_id( v )
150     # get all existing user preferences files
151     if sys.platform == "win32":
152       files = glob.glob( os.environ['HOME'] + "\." + appname + ".xml.*" )
153     else:
154       files = glob.glob( os.environ['HOME'] + "/." + appname + "rc.*" )
155     f2v = {}
156     for file in files:
157         match = re.search( r'\.%src\.([a-zA-Z0-9.]+)$'%appname, file )
158         if match: f2v[file] = match.group(1)
159     last_file = ""
160     last_version = 0
161     for file in f2v:
162         ver = version_id( f2v[file] )
163         if ver and abs(last_version-id0) > abs(ver-id0):
164             last_version = ver
165             last_file = file
166     return last_file
167
168 # --
169
170 _verbose = None
171
172 def verbose():
173     global _verbose
174     # verbose has already been called
175     if _verbose is not None:
176         return _verbose
177     # first time
178     try:
179         from os import getenv
180         _verbose = int(getenv('SALOME_VERBOSE'))
181     except:
182         _verbose = 0
183         pass
184     #
185     return _verbose
186
187 def setVerbose(level):
188     global _verbose
189     _verbose = level
190     return
191
192 # --
193
194 def process_containers_params( standalone, embedded ):
195     # 1. filter inappropriate containers names
196     if standalone is not None:
197         standalone = filter( lambda x: x in standalone_choices, standalone )
198     if embedded is not None:
199         embedded   = filter( lambda x: x in embedded_choices,   embedded )
200
201     # 2. remove containers appearing in 'standalone' parameter from the 'embedded'
202     # parameter --> i.e. 'standalone' parameter has higher priority
203     if standalone is not None and embedded is not None:
204         embedded = filter( lambda x: x not in standalone, embedded )
205
206     # 3. return corrected parameters values
207     return standalone, embedded
208
209 # -----------------------------------------------------------------------------
210
211 ###
212 # XML reader for launch configuration file usage
213 ###
214
215 section_to_skip = ""
216
217 class xml_parser:
218     def __init__(self, fileName, _opts, _importHistory=[] ):
219         if verbose(): print "Configure parser: processing %s ..." % fileName
220         self.fileName = os.path.abspath(fileName)
221         self.importHistory = _importHistory
222         self.importHistory.append(self.fileName)
223         self.space = []
224         self.opts = _opts
225         self.section = section_to_skip
226         parser = xml.sax.make_parser()
227         parser.setContentHandler(self)
228         parser.parse(fileName)
229         standalone, embedded = process_containers_params( self.opts.get( standalone_nam ),
230                                                           self.opts.get( embedded_nam ) )
231         if standalone is not None:
232             self.opts[ standalone_nam ] = standalone
233         if embedded is not None:
234             self.opts[ embedded_nam ] = embedded
235         pass
236
237     def boolValue( self, str ):
238         strloc = str
239         if isinstance(strloc, types.UnicodeType):
240             strloc = strloc.encode().strip()
241         if isinstance(strloc, types.StringType):
242             strlow = strloc.lower()
243             if strlow in   ("1", "yes", "y", "on", "true", "ok"):
244                 return True
245             elif strlow in ("0", "no", "n", "off", "false", "cancel"):
246                 return False
247         return strloc
248         pass
249
250     def intValue( self, str ):
251         strloc = str
252         if isinstance(strloc, types.UnicodeType):
253             strloc = strloc.encode().strip()
254         if isinstance(strloc, types.StringType):
255             strlow = strloc.lower()
256             if strlow in   ("1", "yes", "y", "on", "true", "ok"):
257                 return 1
258             elif strlow in ("0", "no", "n", "off", "false", "cancel"):
259                 return 0
260             else:
261                 return string.atoi(strloc)
262         return strloc
263         pass
264
265     def startElement(self, name, attrs):
266         self.space.append(name)
267         self.current = None
268         
269         # if we are importing file
270         if self.space == [doc_tag, import_tag] and nam_att in attrs.getNames():
271             self.importFile( attrs.getValue(nam_att) )
272         
273         # if we are analyzing "section" element and its "name" attribute is
274         # either "launch" or module name -- set section_name
275         if self.space == [doc_tag, sec_tag] and nam_att in attrs.getNames():
276             section_name = attrs.getValue( nam_att )
277             if section_name == lanch_nam:
278                 self.section = section_name # launch section
279             elif self.opts.has_key( modules_nam ) and \
280                  section_name in self.opts[ modules_nam ]:
281                 self.section = section_name # <module> section
282             else:
283                 self.section = section_to_skip # any other section
284             pass
285
286         # if we are analyzing "parameter" elements - children of either
287         # "section launch" or "section "<module>"" element, then store them
288         # in self.opts assiciative array (key = [<module>_ + ] value of "name" attribute)
289         elif self.section != section_to_skip           and \
290              self.space == [doc_tag, sec_tag, par_tag] and \
291              nam_att in attrs.getNames()               and \
292              val_att in attrs.getNames():
293             nam = attrs.getValue( nam_att )
294             val = attrs.getValue( val_att )
295             if self.section == lanch_nam: # key for launch section
296                 key = nam
297             else:                         # key for <module> section
298                 key = self.section + "_" + nam
299             if nam in boolKeys:
300                 self.opts[key] = self.boolValue( val )  # assign boolean value: 0 or 1
301             elif nam in intKeys:
302                 self.opts[key] = self.intValue( val )   # assign integer value
303             elif nam in listKeys:
304                 self.opts[key] = filter( lambda a: a.strip(), re.split( "[:;,]", val ) ) # assign list value: []
305             else:
306                 self.opts[key] = val
307             pass
308         pass
309
310     def endElement(self, name):
311         p = self.space.pop()
312         self.current = None
313         if self.section != section_to_skip and name == sec_tag:
314             self.section = section_to_skip
315         pass
316
317     def characters(self, content):
318         pass
319
320     def processingInstruction(self, target, data):
321         pass
322
323     def setDocumentLocator(self, locator):
324         pass
325
326     def startDocument(self):
327         self.read = None
328         pass
329
330     def endDocument(self):
331         self.read = None
332         pass
333     
334     def importFile(self, fname):
335         # get absolute name
336         if os.path.isabs (fname) :
337             absfname = fname
338         else:
339             absfname = os.path.join(os.path.dirname(self.fileName), fname)
340         
341         # check existing and registry file
342         for ext in ["", ".xml", ".XML"] :
343             if os.path.exists(absfname + ext) :
344                 absfname += ext
345                 if absfname in self.importHistory :
346                     if verbose(): print "Configure parser: file %s is already imported" % absfname
347                     return # already imported
348                 break
349             pass
350         else:
351             if verbose(): print "Configure parser: Error : file %s does NOT exists" % absfname
352             return
353          
354         # importing file
355         try:
356             # copy current options
357             import copy
358             opts = copy.deepcopy(self.opts)
359             # import file
360             imp = xml_parser(absfname, opts, self.importHistory)
361             # merge results
362             for key in imp.opts.keys():
363                 if not self.opts.has_key(key):
364                     self.opts[key] = imp.opts[key]
365                     pass
366                 pass
367             pass
368         except:
369             if verbose(): print "Configure parser: Error : can not read configuration file %s" % absfname
370         pass
371       
372
373 # -----------------------------------------------------------------------------
374
375 booleans = { '1': True , 'yes': True , 'y': True , 'on' : True , 'true' : True , 'ok'     : True,
376              '0': False, 'no' : False, 'n': False, 'off': False, 'false': False, 'cancel' : False }
377
378 boolean_choices = booleans.keys()
379
380 def check_embedded(option, opt, value, parser):
381     from optparse import OptionValueError
382     assert value is not None
383     if parser.values.embedded:
384         embedded = filter( lambda a: a.strip(), re.split( "[:;,]", parser.values.embedded ) )
385     else:
386         embedded = []
387     if parser.values.standalone:
388         standalone = filter( lambda a: a.strip(), re.split( "[:;,]", parser.values.standalone ) )
389     else:
390         standalone = []
391     vals = filter( lambda a: a.strip(), re.split( "[:;,]", value ) )
392     for v in vals:
393         if v not in embedded_choices:
394             raise OptionValueError( "option %s: invalid choice: %r (choose from %s)" % ( opt, v, ", ".join( map( repr, embedded_choices ) ) ) )
395         if v not in embedded:
396             embedded.append( v )
397             if v in standalone:
398                 del standalone[ standalone.index( v ) ]
399                 pass
400     parser.values.embedded = ",".join( embedded )
401     parser.values.standalone = ",".join( standalone )
402     pass
403
404 def check_standalone(option, opt, value, parser):
405     from optparse import OptionValueError
406     assert value is not None
407     if parser.values.embedded:
408         embedded = filter( lambda a: a.strip(), re.split( "[:;,]", parser.values.embedded ) )
409     else:
410         embedded = []
411     if parser.values.standalone:
412         standalone = filter( lambda a: a.strip(), re.split( "[:;,]", parser.values.standalone ) )
413     else:
414         standalone = []
415     vals = filter( lambda a: a.strip(), re.split( "[:;,]", value ) )
416     for v in vals:
417         if v not in standalone_choices:
418             raise OptionValueError( "option %s: invalid choice: %r (choose from %s)" % ( opt, v, ", ".join( map( repr, standalone_choices ) ) ) )
419         if v not in standalone:
420             standalone.append( v )
421             if v in embedded:
422                 del embedded[ embedded.index( v ) ]
423                 pass
424     parser.values.embedded = ",".join( embedded )
425     parser.values.standalone = ",".join( standalone )
426     pass
427
428 def store_boolean (option, opt, value, parser, *args):
429     if isinstance(value, types.StringType):
430         try:
431             value_conv = booleans[value.strip().lower()]
432             for attribute in args:
433                 setattr(parser.values, attribute, value_conv)
434         except KeyError:
435             raise optparse.OptionValueError(
436                 "option %s: invalid boolean value: %s (choose from %s)"
437                 % (opt, value, boolean_choices))
438     else:
439         for attribute in args:
440             setattr(parser.values, attribute, value)
441
442 def CreateOptionParser (theAdditionalOptions=[]):
443     # GUI/Terminal. Default: GUI
444     help_str = "Launch without GUI (in the terminal mode)."
445     o_t = optparse.Option("-t",
446                           "--terminal",
447                           action="store_false",
448                           dest="gui",
449                           help=help_str)
450
451     help_str = "Launch in Batch Mode. (Without GUI on batch machine)"
452     o_b = optparse.Option("-b",
453                           "--batch",
454                           action="store_true",
455                           dest="batch",
456                           help=help_str)
457
458     help_str = "Launch in GUI mode [default]."
459     o_g = optparse.Option("-g",
460                           "--gui",
461                           action="store_true",
462                           dest="gui",
463                           help=help_str)
464
465     # Show Desktop (inly in GUI mode). Default: True
466     help_str  = "1 to activate GUI desktop [default], "
467     help_str += "0 to not activate GUI desktop (Session_Server starts, but GUI is not shown). "
468     help_str += "Ignored in the terminal mode."
469     o_d = optparse.Option("-d",
470                           "--show-desktop",
471                           metavar="<1/0>",
472                           #type="choice", choices=boolean_choices,
473                           type="string",
474                           action="callback", callback=store_boolean, callback_args=('desktop',),
475                           dest="desktop",
476                           help=help_str)
477     help_str  = "Do not activate GUI desktop (Session_Server starts, but GUI is not shown). "
478     help_str += "The same as --show-desktop=0."
479     o_o = optparse.Option("-o",
480                           "--hide-desktop",
481                           action="store_false",
482                           dest="desktop",
483                           help=help_str)
484
485     # Use logger or log-file. Default: nothing.
486     help_str = "Redirect messages to the CORBA collector."
487     #o4 = optparse.Option("-l", "--logger", action="store_true", dest="logger", help=help_str)
488     o_l = optparse.Option("-l",
489                           "--logger",
490                           action="store_const", const="CORBA",
491                           dest="log_file",
492                           help=help_str)
493     help_str = "Redirect messages to the <log-file>"
494     o_f = optparse.Option("-f",
495                           "--log-file",
496                           metavar="<log-file>",
497                           type="string",
498                           action="store",
499                           dest="log_file",
500                           help=help_str)
501
502     # Execute python scripts. Default: None.
503     help_str  = "Python script(s) to be imported. Python scripts are imported "
504     help_str += "in the order of their appearance. In GUI mode python scripts "
505     help_str += "are imported in the embedded python interpreter of current study, "
506     help_str += "otherwise in an external python interpreter. "
507     help_str += "Note: this option is obsolete. Instead you can pass Python script(s) "
508     help_str += "directly as positional parameter."
509     o_u = optparse.Option("-u",
510                           "--execute",
511                           metavar="<script1,script2,...>",
512                           type="string",
513                           action="append",
514                           dest="py_scripts",
515                           help=help_str)
516
517     # Configuration XML file. Default: $(HOME)/.SalomeApprc.$(version).
518     help_str  = "Parse application settings from the <file> "
519     help_str += "instead of default $(HOME)/.SalomeApprc.$(version)"
520     o_r = optparse.Option("-r",
521                           "--resources",
522                           metavar="<file>",
523                           type="string",
524                           action="store",
525                           dest="resources",
526                           help=help_str)
527
528     # Use own xterm for each server. Default: False.
529     help_str = "Launch each SALOME server in own xterm console"
530     o_x = optparse.Option("-x",
531                           "--xterm",
532                           action="store_true",
533                           dest="xterm",
534                           help=help_str)
535
536     # Modules. Default: Like in configuration files.
537     help_str  = "SALOME modules list (where <module1>, <module2> are the names "
538     help_str += "of SALOME modules which should be available in the SALOME session)"
539     o_m = optparse.Option("-m",
540                           "--modules",
541                           metavar="<module1,module2,...>",
542                           type="string",
543                           action="append",
544                           dest="modules",
545                           help=help_str)
546
547     # Embedded servers. Default: Like in configuration files.
548     help_str  = "CORBA servers to be launched in the Session embedded mode. "
549     help_str += "Valid values for <serverN>: %s " % ", ".join( embedded_choices )
550     help_str += "[by default the value from the configuration files is used]"
551     o_e = optparse.Option("-e",
552                           "--embedded",
553                           metavar="<server1,server2,...>",
554                           type="string",
555                           action="callback",
556                           dest="embedded",
557                           callback=check_embedded,
558                           help=help_str)
559
560     # Standalone servers. Default: Like in configuration files.
561     help_str  = "CORBA servers to be launched in the standalone mode (as separate processes). "
562     help_str += "Valid values for <serverN>: %s " % ", ".join( standalone_choices )
563     help_str += "[by default the value from the configuration files is used]"
564     o_s = optparse.Option("-s",
565                           "--standalone",
566                           metavar="<server1,server2,...>",
567                           type="string",
568                           action="callback",
569                           dest="standalone",
570                           callback=check_standalone,
571                           help=help_str)
572
573     # Kill with port. Default: False.
574     help_str = "Kill SALOME with the current port"
575     o_p = optparse.Option("-p",
576                           "--portkill",
577                           action="store_true",
578                           dest="portkill",
579                           help=help_str)
580
581     # Kill all. Default: False.
582     help_str = "Kill all running SALOME sessions"
583     o_k = optparse.Option("-k",
584                           "--killall",
585                           action="store_true",
586                           dest="killall",
587                           help=help_str)
588
589     # Additional python interpreters. Default: 0.
590     help_str  = "The number of additional external python interpreters to run. "
591     help_str += "Each additional python interpreter is run in separate "
592     help_str += "xterm session with properly set SALOME environment"
593     o_i = optparse.Option("-i",
594                           "--interp",
595                           metavar="<N>",
596                           type="int",
597                           action="store",
598                           dest="interp",
599                           help=help_str)
600
601     # Splash. Default: True.
602     help_str  = "1 to display splash screen [default], "
603     help_str += "0 to disable splash screen. "
604     help_str += "This option is ignored in the terminal mode. "
605     help_str += "It is also ignored if --show-desktop=0 option is used."
606     o_z = optparse.Option("-z",
607                           "--splash",
608                           metavar="<1/0>",
609                           #type="choice", choices=boolean_choices,
610                           type="string",
611                           action="callback", callback=store_boolean, callback_args=('splash',),
612                           dest="splash",
613                           help=help_str)
614
615     # Catch exceptions. Default: True.
616     help_str  = "1 (yes,true,on,ok) to enable centralized exception handling [default], "
617     help_str += "0 (no,false,off,cancel) to disable centralized exception handling."
618     o_c = optparse.Option("-c",
619                           "--catch-exceptions",
620                           metavar="<1/0>",
621                           #type="choice", choices=boolean_choices,
622                           type="string",
623                           action="callback", callback=store_boolean, callback_args=('catch_exceptions',),
624                           dest="catch_exceptions",
625                           help=help_str)
626
627     # Print free port and exit
628     help_str = "Print free port and exit"
629     o_a = optparse.Option("--print-port",
630                           action="store_true",
631                           dest="print_port", default=False,
632                           help=help_str)
633
634     # Do not relink ${HOME}/.omniORB_last.cfg
635     help_str = "Do not save current configuration ${HOME}/.omniORB_last.cfg"
636     o_n = optparse.Option("--nosave-config",
637                           action="store_false",
638                           dest="save_config", default=True,
639                           help=help_str)
640
641     # Launch with interactive python console. Default: False.
642     help_str = "Launch with interactive python console."
643     o_pi = optparse.Option("--pinter",
644                           action="store_true",
645                           dest="pinter",
646                           help=help_str)
647
648     # Print Naming service port into a user file. Default: False.
649     help_str = "Print Naming Service Port into a user file."
650     o_nspl = optparse.Option("--ns-port-log",
651                              metavar="<ns_port_log_file>",
652                              type="string",
653                              action="store",
654                              dest="ns_port_log_file",
655                              help=help_str)
656
657     # Write/read test script file with help of TestRecorder. Default: False.
658     help_str = "Write/read test script file with help of TestRecorder."
659     o_test = optparse.Option("--test",
660                              metavar="<test_script_file>",
661                              type="string",
662                              action="store",
663                              dest="test_script_file",
664                              help=help_str)
665
666     # Reproducing test script with help of TestRecorder. Default: False.
667     help_str = "Reproducing test script with help of TestRecorder."
668     o_play = optparse.Option("--play",
669                              metavar="<play_script_file>",
670                              type="string",
671                              action="store",
672                              dest="play_script_file",
673                              help=help_str)
674
675     # gdb session
676     help_str = "Launch session with gdb"
677     o_gdb = optparse.Option("--gdb-session",
678                             action="store_true",
679                             dest="gdb_session", default=False,
680                             help=help_str)
681
682     # ddd session
683     help_str = "Launch session with ddd"
684     o_ddd = optparse.Option("--ddd-session",
685                             action="store_true",
686                             dest="ddd_session", default=False,
687                             help=help_str)
688
689
690     # valgrind session
691     help_str = "Launch session with valgrind $VALGRIND_OPTIONS"
692     o_valgrind = optparse.Option("--valgrind-session",
693                                  action="store_true",
694                                  dest="valgrind_session", default=False,
695                                  help=help_str)
696
697     # shutdown-servers. Default: False.
698     help_str  = "1 to shutdown standalone servers when leaving python interpreter, "
699     help_str += "0 to keep the standalone servers as daemon [default]. "
700     help_str += "This option is only useful in batchmode "
701     help_str += "(terminal mode or without showing desktop)."
702     o_shutdown = optparse.Option("--shutdown-servers",
703                                  metavar="<1/0>",
704                                  #type="choice", choices=boolean_choices,
705                                  type="string",
706                                  action="callback", callback=store_boolean, callback_args=('shutdown_servers',),
707                                  dest="shutdown_servers",
708                                  help=help_str)
709
710     # All options
711     opt_list = [o_t,o_g, # GUI/Terminal
712                 o_d,o_o, # Desktop
713                 o_b,     # Batch
714                 o_l,o_f, # Use logger or log-file
715                 o_u,     # Execute python scripts
716                 o_r,     # Configuration XML file
717                 o_x,     # xterm
718                 o_m,     # Modules
719                 o_e,     # Embedded servers
720                 o_s,     # Standalone servers
721                 o_p,     # Kill with port
722                 o_k,     # Kill all
723                 o_i,     # Additional python interpreters
724                 o_z,     # Splash
725                 o_c,     # Catch exceptions
726                 o_a,     # Print free port and exit
727                 o_n,     # --nosave-config
728                 o_pi,    # Interactive python console
729                 o_nspl,
730                 o_test,  # Write/read test script file with help of TestRecorder
731                 o_play,  # Reproducing test script with help of TestRecorder
732                 o_gdb,
733                 o_ddd,
734                 o_valgrind,
735                 o_shutdown,
736                 ]
737
738     #std_options = ["gui", "desktop", "log_file", "py_scripts", "resources",
739     #               "xterm", "modules", "embedded", "standalone",
740     #               "portkill", "killall", "interp", "splash",
741     #               "catch_exceptions", "print_port", "save_config", "ns_port_log_file"]
742
743     opt_list += theAdditionalOptions
744
745     a_usage = "%prog [options] [STUDY_FILE] [PYTHON_FILE [PYTHON_FILE ...]]"
746     version_str = "Salome %s" % version()
747     pars = optparse.OptionParser(usage=a_usage, version=version_str, option_list=opt_list)
748
749     return pars
750
751 # -----------------------------------------------------------------------------
752
753 ###
754 # Get the environment
755 ###
756
757 # this attribute is obsolete
758 args = {}
759 #def get_env():
760 #args = []
761 def get_env(theAdditionalOptions=[], appname="SalomeApp"):
762     ###
763     # Collect launch configuration files:
764     # - The environment variable "<appname>Config" (SalomeAppConfig) which can
765     #   define a list of directories (separated by ':' or ';' symbol) is checked
766     # - If the environment variable "<appname>Config" is not set, only
767     #   ${GUI_ROOT_DIR}/share/salome/resources/gui is inspected
768     # - ${GUI_ROOT_DIR}/share/salome/resources/gui directory is always inspected
769     #   so it is not necessary to put it in the "<appname>Config" variable
770     # - The directories which are inspected are checked for files "<appname?salomeappname>.xml"
771     #  (SalomeApp.xml) which define SALOME configuration
772     # - These directories are analyzed beginning from the last one in the list,
773     #   so the first directory listed in "<appname>Config" environment variable
774     #   has higher priority: it means that if some configuration options
775     #   is found in the next analyzed cofiguration file - it will be replaced
776     # - The last configuration file which is parsed is user configuration file
777     #   situated in the home directory: "~/.<appname>rc[.<version>]" (~/SalomeApprc.3.2.0)
778     #   (if it exists)
779     # - Command line options have the highest priority and replace options
780     #   specified in configuration file(s)
781     ###
782
783     global args
784     config_var = appname+'Config'
785
786     separator = ":"
787     if os.sys.platform == 'win32':
788         separator = ";"
789
790     # check KERNEL_ROOT_DIR
791     try:
792         kernel_root_dir=os.environ["KERNEL_ROOT_DIR"]
793     except:
794         print """
795         For each SALOME module, the environment variable <moduleN>_ROOT_DIR must be set.
796         KERNEL_ROOT_DIR is mandatory.
797         """
798         sys.exit(1)
799         pass
800
801     ############################
802     # parse command line options
803     pars = CreateOptionParser(theAdditionalOptions)
804     (cmd_opts, cmd_args) = pars.parse_args(sys.argv[1:])
805     ############################
806
807     # Process --print-port option
808     if cmd_opts.print_port:
809         from runSalome import searchFreePort
810         searchFreePort({})
811         print "port:%s"%(os.environ['NSPORT'])
812         sys.exit(0)
813         pass
814
815     # set resources variable SalomeAppConfig if it is not set yet
816     dirs = []
817     if os.getenv(config_var):
818         if sys.platform == 'win32':
819             dirs += re.split(';', os.getenv(config_var))
820         else:
821             dirs += re.split('[;|:]', os.getenv(config_var))
822
823     gui_available = True
824     if os.getenv("GUI_ROOT_DIR") and os.path.isdir( os.getenv("GUI_ROOT_DIR") + "/share/salome/resources/gui" ):
825         dirs += [os.getenv("GUI_ROOT_DIR") + "/share/salome/resources/gui"]
826         pass
827     else:
828         gui_available = False
829         if os.getenv("KERNEL_ROOT_DIR") and os.path.isdir( os.getenv("KERNEL_ROOT_DIR") + "/bin/salome/appliskel" ):
830             dirs += [os.getenv("KERNEL_ROOT_DIR") + "/bin/salome/appliskel"]
831         pass
832     os.environ[config_var] = separator.join(dirs)
833
834     dirs.reverse() # reverse order, like in "path" variable - FILO-style processing
835
836     try:
837         dirs.remove('') # to remove empty dirs if the variable terminate by ":" or if there are "::" inside
838     except:
839         pass
840
841     _opts = {} # associative array of options to be filled
842
843     # parse SalomeApp.xml files in directories specified by SalomeAppConfig env variable
844     for dir in dirs:
845         #filename = dir+'/'+appname+'.xml'
846         filename = dir+'/'+salomeappname+'.xml'
847         if not os.path.exists(filename):
848             print "Configure parser: Warning : could not find configuration file %s" % filename
849         else:
850             try:
851                 p = xml_parser(filename, _opts)
852                 _opts = p.opts
853             except:
854                 print "Configure parser: Error : can not read configuration file %s" % filename
855             pass
856
857     # parse user configuration file
858     # It can be set via --resources=<file> command line option
859     # or is given by default from ${HOME}/.<appname>rc.<version>
860     # If user file for the current version is not found the nearest to it is used
861     user_config = cmd_opts.resources
862     if not user_config:
863         user_config = userFile(appname)
864     if not user_config or not os.path.exists(user_config):
865         print "Configure parser: Warning : could not find user configuration file"
866     else:
867         try:
868             p = xml_parser(user_config, _opts)
869             _opts = p.opts
870         except:
871             print 'Configure parser: Error : can not read user configuration file'
872             user_config = ""
873
874     args = _opts
875
876     args['user_config'] = user_config
877     #print "User Configuration file: ", args['user_config']
878
879     # set default values for options which are NOT set in config files
880     for aKey in listKeys:
881         if not args.has_key( aKey ):
882             args[aKey]=[]
883
884     for aKey in boolKeys:
885         if not args.has_key( aKey ):
886             args[aKey]=0
887
888     if args[file_nam]:
889         afile=args[file_nam]
890         args[file_nam]=[afile]
891
892     args[appname_nam] = appname
893
894     # get the port number
895     from salome_utils import getPortNumber
896     my_port = getPortNumber()
897
898     args[port_nam] = my_port
899
900     ####################################################
901     # apply command-line options to the arguments
902     # each option given in command line overrides the option from xml config file
903     #
904     # Options: gui, desktop, log_file, py_scripts, resources,
905     #          xterm, modules, embedded, standalone,
906     #          portkill, killall, interp, splash,
907     #          catch_exceptions, pinter
908
909     # GUI/Terminal, Desktop, Splash, STUDY_HDF
910     args["session_gui"] = False
911     args[batch_nam] = False
912     args["study_hdf"] = None
913     if cmd_opts.gui is not None:
914         args[gui_nam] = cmd_opts.gui
915     if cmd_opts.batch is not None:
916         args[batch_nam] = True
917
918     if not gui_available:
919         args[gui_nam] = False
920
921     if args[gui_nam]:
922         args["session_gui"] = True
923         if cmd_opts.desktop is not None:
924             args["session_gui"] = cmd_opts.desktop
925             args[splash_nam]    = cmd_opts.desktop
926         if args["session_gui"]:
927             if cmd_opts.splash is not None:
928                 args[splash_nam] = cmd_opts.splash
929     else:
930         args["session_gui"] = False
931         args[splash_nam] = False
932
933     # Logger/Log file
934     if cmd_opts.log_file is not None:
935         if cmd_opts.log_file == 'CORBA':
936             args[logger_nam] = True
937         else:
938             args[file_nam] = [cmd_opts.log_file]
939
940     # Naming Service port log file
941     if cmd_opts.ns_port_log_file is not None:
942       args["ns_port_log_file"] = cmd_opts.ns_port_log_file
943
944     # Python scripts
945     args[script_nam] = []
946     if cmd_opts.py_scripts is not None:
947         listlist = cmd_opts.py_scripts
948         for listi in listlist:
949             if os.sys.platform == 'win32':
950                 args[script_nam] += re.split( "[;,]", listi)
951             else:
952                 args[script_nam] += re.split( "[:;,]", listi)
953     for arg in cmd_args:
954         if arg[-3:] == ".py":
955             args[script_nam].append(arg)
956         elif not args["study_hdf"]:
957             args["study_hdf"] = arg
958             pass
959         pass
960
961     # xterm
962     if cmd_opts.xterm is not None: args[xterm_nam] = cmd_opts.xterm
963
964     # Modules
965     if cmd_opts.modules is not None:
966         args[modules_nam] = []
967         listlist = cmd_opts.modules
968         for listi in listlist:
969             args[modules_nam] += re.split( "[:;,]", listi)
970     else:
971         # if --modules (-m) command line option is not given
972         # try SALOME_MODULES environment variable
973         if os.getenv( "SALOME_MODULES" ):
974             args[modules_nam] = re.split( "[:;,]", os.getenv( "SALOME_MODULES" ) )
975             pass
976
977     # Embedded
978     if cmd_opts.embedded is not None:
979         args[embedded_nam] = filter( lambda a: a.strip(), re.split( "[:;,]", cmd_opts.embedded ) )
980
981     # Standalone
982     if cmd_opts.standalone is not None:
983         args[standalone_nam] = filter( lambda a: a.strip(), re.split( "[:;,]", cmd_opts.standalone ) )
984
985     # Normalize the '--standalone' and '--embedded' parameters
986     standalone, embedded = process_containers_params( args.get( standalone_nam ),
987                                                       args.get( embedded_nam ) )
988     if standalone is not None:
989         args[ standalone_nam ] = standalone
990     if embedded is not None:
991         args[ embedded_nam ] = embedded
992
993     # Kill
994     if cmd_opts.portkill is not None: args[portkill_nam] = cmd_opts.portkill
995     if cmd_opts.killall  is not None: args[killall_nam]  = cmd_opts.killall
996
997     # Interpreter
998     if cmd_opts.interp is not None:
999         args[interp_nam] = cmd_opts.interp
1000
1001     # Exceptions
1002     if cmd_opts.catch_exceptions is not None:
1003         args[except_nam] = not cmd_opts.catch_exceptions
1004
1005     # Relink config file
1006     if cmd_opts.save_config is not None:
1007         args['save_config'] = cmd_opts.save_config
1008
1009     # Interactive python console
1010     if cmd_opts.pinter is not None:
1011         args[pinter_nam] = cmd_opts.pinter
1012
1013     # Gdb session in xterm
1014     if cmd_opts.gdb_session is not None:
1015         args[gdb_session_nam] = cmd_opts.gdb_session
1016
1017     # Ddd session in xterm
1018     if cmd_opts.ddd_session is not None:
1019         args[ddd_session_nam] = cmd_opts.ddd_session
1020
1021     # valgrind session
1022     if cmd_opts.valgrind_session is not None:
1023         args[valgrind_session_nam] = cmd_opts.valgrind_session
1024
1025     # Shutdown servers
1026     if cmd_opts.shutdown_servers is None:
1027         args[shutdown_servers_nam] = 0
1028     else:
1029         args[shutdown_servers_nam] = cmd_opts.shutdown_servers
1030         pass
1031
1032     ####################################################
1033     # Add <theAdditionalOptions> values to args
1034     for add_opt in theAdditionalOptions:
1035         cmd = "args[\"%s\"] = cmd_opts.%s"%(add_opt.dest,add_opt.dest)
1036         exec(cmd)
1037     ####################################################
1038
1039     # disable signals handling
1040     if args[except_nam] == 1:
1041         os.environ["NOT_INTERCEPT_SIGNALS"] = "1"
1042         pass
1043
1044     # now modify SalomeAppConfig environment variable
1045     # to take into account the SALOME modules
1046     if os.sys.platform == 'win32':
1047         dirs = re.split('[;]', os.environ[config_var] )
1048     else:
1049         dirs = re.split('[;|:]', os.environ[config_var] )
1050     for m in args[modules_nam]:
1051         if m not in ["KERNEL", "GUI", ""] and os.getenv("%s_ROOT_DIR"%m):
1052             d1 = os.getenv("%s_ROOT_DIR"%m) + "/share/salome/resources/" + m.lower()
1053             d2 = os.getenv("%s_ROOT_DIR"%m) + "/share/salome/resources"
1054             #if os.path.exists( "%s/%s.xml"%(d1, appname) ):
1055             if os.path.exists( "%s/%s.xml"%(d1, salomeappname) ):
1056                 dirs.append( d1 )
1057             #elif os.path.exists( "%s/%s.xml"%(d2, appname) ):
1058             elif os.path.exists( "%s/%s.xml"%(d2, salomeappname) ):
1059                 dirs.append( d2 )
1060
1061     # Test
1062     if cmd_opts.test_script_file is not None:
1063         args[test_nam] = []
1064         filename = cmd_opts.test_script_file
1065         args[test_nam] += re.split( "[:;,]", filename )
1066
1067     # Play
1068     if cmd_opts.play_script_file is not None:
1069         args[play_nam] = []
1070         filename = cmd_opts.play_script_file
1071         args[play_nam] += re.split( "[:;,]", filename )
1072
1073     # return arguments
1074     os.environ[config_var] = separator.join(dirs)
1075     #print "Args: ", args
1076     return args