/** * Configuration options for druntime * * Copyright: Copyright Digital Mars 2014. * License: Distributed under the * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0). * (See accompanying file LICENSE) * Authors: Rainer Schuetze * Source: $(DRUNTIMESRC src/rt/_config.d) */ module rt.config; // The default way to configure the runtime is by passing command line arguments // starting with "--DRT-" and followed by the option name, e.g. "--DRT-gcopt" to // configure the GC. // Command line options starting with "--DRT-" are filtered out before calling main, // so the program will not see them. They are still available via rt_args(). // // Configuration via the command line can be disabled by declaring a variable for the // linker to pick up before using it's default from the runtime: // // extern(C) __gshared bool rt_cmdline_enabled = false; // // Likewise, declare a boolean rt_envvars_enabled to enable configuration via the // environment variable "DRT_" followed by the option name, e.g. "DRT_GCOPT": // // extern(C) __gshared bool rt_envvars_enabled = true; // // Setting default configuration properties in the executable can be done by specifying an // array of options named rt_options: // // extern(C) __gshared string[] rt_options = [ "gcopt=precise:1 profile:1"]; // // Evaluation order of options is rt_options, then environment variables, then command // line arguments, i.e. if command line arguments are not disabled, they can override // options specified through the environment or embedded in the executable. import core.demangle : cPrefix; // put each variable in its own COMDAT by making them template instances template rt_envvars_enabled() { pragma(mangle, cPrefix ~ "rt_envvars_enabled") __gshared bool rt_envvars_enabled = false; } template rt_cmdline_enabled() { pragma(mangle, cPrefix ~ "rt_cmdline_enabled") __gshared bool rt_cmdline_enabled = true; } template rt_options() { pragma(mangle, cPrefix ~ "rt_options") __gshared string[] rt_options = []; } import core.stdc.ctype : toupper; import core.stdc.stdlib : getenv; import core.stdc.string : strlen; extern extern(C) string[] rt_args() @nogc nothrow; alias rt_configCallBack = string delegate(string) @nogc nothrow; /** * get a druntime config option using standard configuration options * opt name of the option to retreive * dg if non-null, passes the option through this * delegate and only returns its return value if non-null * reverse reverse the default processing order cmdline/envvar/rt_options * to allow overwriting settings in the delegate with values * from higher priority * * returns the options' value if * - set on the command line as "--DRT-=value" (rt_cmdline_enabled enabled) * - the environment variable "DRT_" is set (rt_envvars_enabled enabled) * - rt_options[] contains an entry "=value" * - null otherwise */ string rt_configOption(string opt, scope rt_configCallBack dg = null, bool reverse = false) @nogc nothrow { if (!dg) dg = (string s) => s; string s = (reverse ? rt_linkOption(opt, dg) : rt_cmdlineOption(opt, dg)); if (s != null) return s; s = rt_envvarsOption(opt, dg); if (s != null) return s; s = (reverse ? rt_cmdlineOption(opt, dg) : rt_linkOption(opt, dg)); return s; } string rt_cmdlineOption(string opt, scope rt_configCallBack dg) @nogc nothrow { if(rt_cmdline_enabled!()) { foreach (a; rt_args) { if (a.length >= opt.length + 7 && a[0..6] == "--DRT-" && a[6 .. 6 + opt.length] == opt && a[6 + opt.length] == '=') { string s = dg(a[7 + opt.length .. $]); if (s != null) return s; } } } return null; } string rt_envvarsOption(string opt, scope rt_configCallBack dg) @nogc nothrow { if(rt_envvars_enabled!()) { if (opt.length >= 32) assert(0); char[40] var; var[0 .. 4] = "DRT_"; foreach (i, c; opt) var[4 + i] = cast(char) toupper(c); var[4 + opt.length] = 0; auto p = getenv(var.ptr); if (p) { string s = dg(cast(string) p[0 .. strlen(p)]); if (s != null) return s; } } return null; } string rt_linkOption(string opt, scope rt_configCallBack dg) @nogc nothrow { foreach (a; rt_options!()) { if(a.length > opt.length && a[0..opt.length] == opt && a[opt.length] == '=') { string s = dg(a[opt.length + 1 .. $]); if (s != null) return s; } } return null; }