Mercurial > projects > mde
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 } |