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