comparison mde/setup/Init.d @ 151:e785e98d3b78

Updated for compatibility with tango 0.99.8.
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 04 Apr 2009 17:32:18 +0200
parents 9f035cd139c6
children 2934fcacbb97
comparison
equal deleted inserted replaced
150:42fb97d9ff9e 151:e785e98d3b78
57 import tango.util.container.LinkedList; 57 import tango.util.container.LinkedList;
58 58
59 //import tango.stdc.stringz : fromStringz; 59 //import tango.stdc.stringz : fromStringz;
60 import tango.io.Console; // for printing command-line usage 60 import tango.io.Console; // for printing command-line usage
61 import TimeStamp = tango.text.convert.TimeStamp, tango.time.WallClock; // output date in log file 61 import TimeStamp = tango.text.convert.TimeStamp, tango.time.WallClock; // output date in log file
62 import tango.util.Arguments; 62 import tango.util.ArgParser;
63 import tango.util.log.Log; 63 import tango.util.log.Log;
64 import tango.util.log.AppendConsole; 64 import tango.util.log.AppendConsole;
65 import tango.util.log.AppendFiles; 65 import tango.util.log.AppendFiles;
66 66
67 // Derelict imports 67 // Derelict imports
86 exitImmediately = new BoolContent ("MiscOptions.exitImmediately"); 86 exitImmediately = new BoolContent ("MiscOptions.exitImmediately");
87 maxThreads = new IntContent ("MiscOptions.maxThreads"); 87 maxThreads = new IntContent ("MiscOptions.maxThreads");
88 logLevel = new EnumContent ("MiscOptions.logLevel", 88 logLevel = new EnumContent ("MiscOptions.logLevel",
89 ["Trace", "Info", "Warn", "Error", "Fatal", "None"]); 89 ["Trace", "Info", "Warn", "Error", "Fatal", "None"]);
90 logOutput = new EnumContent ("MiscOptions.logOutput", 90 logOutput = new EnumContent ("MiscOptions.logOutput",
91 ["none", "console", "file", "both"]); 91 ["both", "file", "console", "none"]);
92
93 // Callback to set the logging level on change:
94 logLevel.addCallback (&setLogLevel);
92 } 95 }
93 96
94 /** this() − pre-init and init */ 97 /** this() − pre-init and init */
95 this(char[][] cmdArgs) 98 this(char[][] cmdArgs)
96 { 99 {
97 /********************************************************************** 100 /**********************************************************************
98 * Pre-init - init code written in this module. 101 * Pre-init - init code written in this module.
99 *********************************************************************/ 102 *********************************************************************/
100 debug logger.trace ("Init: starting pre-init"); 103 debug logger.trace ("Init: starting pre-init");
101 //FIXME: warn on invalid arguments, including base-path on non-Windows
102 // But Arguments doesn't support this (in tango 0.99.6 and in r3563).
103 Arguments args;
104 try { 104 try {
105 args = new Arguments(); 105 // Create without a default-argument delegate; let ArgParser throw:
106 args.define("base-path").parameters(1); 106 auto args = new ArgParser ();
107 args.define("data-path").parameters(1,-1); 107 char[] basePath = ".";
108 args.define("conf-path").parameters(1,-1); 108 bool printPaths = false;
109 args.define("font-path").parameters(1,-1); 109 args.bind("--", "base-path=", delegate void(char[] value){
110 args.define("paths"); 110 basePath=value;
111 args.define("q").aliases(["quick-exit"]); 111 });
112 args.define("help").aliases(["h"]); 112 args.bind("--", "data-path=", delegate void(char[] value){
113 args.parse(cmdArgs); 113 paths.extraDataPath = value;
114 if (args.contains("help")) // lazy way to print help 114 });
115 throw new InitException ("Help requested"); // and stop 115 args.bind("--", "conf-path=", delegate void(char[] value){
116 paths.extraConfPath = value;
117 });
118 args.bind("--", "font-path=", delegate void(char[] value){
119 paths.addFontPath (value);
120 });
121 args.bind("--", "paths", delegate void(char[]){
122 printPaths = true;
123 });
124 args.bind([Argument("--", "quick-exit"), Argument ("-", "q")],
125 delegate void(char[]){
126 imde.run = false;
127 });
128 args.bind([Argument("--", "help"), Argument ("-", "h")],
129 delegate void(char[]){
130 printUsage(cmdArgs[0]);
131 // Requesting help is an "error" in that normal program operation is cut short.
132 throw new InitException ("Help requested"); // stops program
133 });
134 args.parse(cmdArgs[1..$]);
135 paths.resolvePaths (basePath);
136
137 if (printPaths) {
138 paths.mdeDirectory.printPaths;
139 throw new InitException ("Paths requested"); // lazy way to stop
140 }
116 } catch (Exception e) { 141 } catch (Exception e) {
117 printUsage(cmdArgs[0]); 142 throw new InitException ("Command-line: "~e.msg);
118 throw new InitException ("Parsing arguments failed: "~e.msg);
119 }
120
121 // Find/create paths:
122 try {
123 if (args.contains("data-path"))
124 paths.extraDataPath = args["data-path"];
125 if (args.contains("conf-path"))
126 paths.extraConfPath = args["conf-path"];
127 if (args.contains("font-path"))
128 paths.addFontPath (args["font-path"]);
129
130 if (args.contains("base-path"))
131 paths.resolvePaths (args["base-path"]);
132 else
133 paths.resolvePaths();
134 } catch (Exception e) {
135 throw new InitException ("Resolving paths failed: " ~ e.msg);
136 }
137 if (args.contains("paths")) {
138 paths.mdeDirectory.printPaths;
139 throw new InitException ("Paths requested"); // lazy way to stop
140 } 143 }
141 debug logger.trace ("Init: resolved paths successfully"); 144 debug logger.trace ("Init: resolved paths successfully");
142 145
143 /* Load options now. Don't load in a thread since: 146 /* Load options now. Don't load in a thread since:
144 * Loading should be fast & most work is probably disk access 147 * Loading should be fast & most work is probably disk access
156 try { 159 try {
157 // Where logging is done to is determined at compile-time, currently just via static ifs. 160 // Where logging is done to is determined at compile-time, currently just via static ifs.
158 root = Log.root; 161 root = Log.root;
159 root.clear; // we may no longer want to log to the console 162 root.clear; // we may no longer want to log to the console
160 163
161 // Now re-set the logging level and add callback to set on change: 164 // logOutput == 0 enables both outputs, in case options aren't read
162 setLogLevel (); 165 if (!(logOutput() & 2)) { // first appender so root seperator messages don't show on console
163 logLevel.addCallback (&setLogLevel);
164
165 if (logOutput() & 2) { // first appender so root seperator messages don't show on console
166 // Use 2 log files with a maximum size of 16kiB: 166 // Use 2 log files with a maximum size of 16kiB:
167 root.add (new AppendFiles (paths.logDir~"/log-.txt", 2, 16*1024)); 167 root.add (new AppendFiles (paths.logDir~"/log-.txt", 2, 16*1024));
168 root.append (Level.None, ""); // some kind of separation between runs 168 root.append (Level.None, ""); // some kind of separation between runs
169 root.append (Level.None, ""); 169 root.append (Level.None, "");
170 } 170 }
171 if (logOutput() & 1) 171 if (!(logOutput() & 1))
172 root.add(new AppendConsole); 172 root.add(new AppendConsole);
173 logger.info ("Starting mde [no version] on " ~ TimeStamp.toString(WallClock.now)); 173 logger.info ("Starting mde [no version] on " ~ TimeStamp.toString(WallClock.now));
174 } catch (Exception e) { 174 } catch (Exception e) {
175 // Presumably it was only adding a file appender which failed; set up a new console 175 // Presumably it was only adding a file appender which failed; set up a new console
176 // logger and if that fails let the exception kill the program. 176 // logger and if that fails let the exception kill the program.
177 root.clear; 177 root.clear;
178 root.add (new AppendConsole); 178 root.add (new AppendConsole);
179 logger.warn ("Exception while setting up the logger; logging to the console instead."); 179 logger.error ("Exception while setting up the logger; logging to the console instead.");
180 } 180 }
181 181
182 // a debugging option: 182 // a debugging option:
183 imde.run = !args.contains("q") && !exitImmediately(); 183 imde.run = imde.run && !exitImmediately();
184 debug logger.trace ("Init: applied pre-init options"); 184 debug logger.trace ("Init: applied pre-init options");
185 185
186 //BEGIN Load dynamic libraries 186 //BEGIN Load dynamic libraries
187 /* Can be done by init functions but much neater to do here. 187 /* Can be done by init functions but much neater to do here.
188 * Also means that init functions aren't run if a library fails to load. */ 188 * Also means that init functions aren't run if a library fails to load. */
399 IntContent maxThreads; 399 IntContent maxThreads;
400 EnumContent logLevel, logOutput; 400 EnumContent logLevel, logOutput;
401 401
402 // Callback on logLevel 402 // Callback on logLevel
403 void setLogLevel (Content = null) { 403 void setLogLevel (Content = null) {
404 int level = logLevel();
405 if (level < Level.Trace || level > Level.None) {
406 logger.error ("incorrect logging level");
407 level = Level.Info;
408 return; // setting the level causes this function to be called again
409 }
410 debug {
411 Log.root.level (Level.Trace);
412 logger.trace ("Setting logging level {}", logLevel());
413 }
404 Log.root.level (logOutput() == 0 ? Level.None : cast(Level) logLevel(), true); 414 Log.root.level (logOutput() == 0 ? Level.None : cast(Level) logLevel(), true);
405 } 415 }
406 416
407 void printUsage (char[] progName) { 417 void printUsage (char[] progName) {
408 Cout ("mde [no version]").newline; 418 Cout ("mde [no version]").newline;
409 Cout ("Usage:").newline; 419 Cout ("Usage:").newline;
410 Cout (progName ~ ` [options]`).newline; 420 Cout (progName ~ ` [options]`).newline;
411 version(Windows) 421 version(Windows)
412 Cout ( 422 Cout (
413 ` --base-path path Use path as the base (install) path (Windows only). It 423 ` --base-path=path Use path as the base (install) path (Windows only). It
414 should contain the "data" directory.`).newline; 424 should contain the "data" directory.`).newline;
415 Cout ( 425 Cout (
416 ` --data-path path(s) Add path(s) as a potential location for data files. 426 ` --data-path=path Add path as a potential location for data files. May be
417 First path argument becomes the preffered location to 427 given multiple times. First path argument becomes
418 load data files from. 428 the prefered location to load data files from.
419 --conf-path path(s) Add path(s) as a potential location for config files. 429 --conf-path=path Add path as a potential location for config files. May
420 Configuration in the first path given take highest 430 be given multiple times. Configuration in the first
421 priority. 431 path given take highest priority.
422 --paths Print all paths found and exit. 432 --paths Print all paths found and exit.
423 --quick-exit, -q Exit immediately, without entering main loop. 433 --quick-exit, -q Exit immediately, without entering main loop.
424 --help, -h Print this message.`).newline; 434 --help, -h Print this message.`).newline;
425 } 435 }
426 } 436 }