xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/libdruntime/rt/config.d (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 /**
2 * Configuration options for druntime
3 *
4 * Copyright: Copyright Digital Mars 2014.
5 * License: Distributed under the
6 *      $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7 *    (See accompanying file LICENSE)
8 * Authors:   Rainer Schuetze
9 * Source: $(DRUNTIMESRC src/rt/_config.d)
10 */
11 
12 module rt.config;
13 
14 // The default way to configure the runtime is by passing command line arguments
15 // starting with "--DRT-" and followed by the option name, e.g. "--DRT-gcopt" to
16 // configure the GC.
17 // Command line options starting with "--DRT-" are filtered out before calling main,
18 // so the program will not see them. They are still available via rt_args().
19 //
20 // Configuration via the command line can be disabled by declaring a variable for the
21 // linker to pick up before using it's default from the runtime:
22 //
23 //   extern(C) __gshared bool rt_cmdline_enabled = false;
24 //
25 // Likewise, declare a boolean rt_envvars_enabled to enable configuration via the
26 // environment variable "DRT_" followed by the option name, e.g. "DRT_GCOPT":
27 //
28 //   extern(C) __gshared bool rt_envvars_enabled = true;
29 //
30 // Setting default configuration properties in the executable can be done by specifying an
31 // array of options named rt_options:
32 //
33 //   extern(C) __gshared string[] rt_options = [ "gcopt=precise:1 profile:1"];
34 //
35 // Evaluation order of options is rt_options, then environment variables, then command
36 // line arguments, i.e. if command line arguments are not disabled, they can override
37 // options specified through the environment or embedded in the executable.
38 
39 import core.demangle : cPrefix;
40 
41 // put each variable in its own COMDAT by making them template instances
rt_envvars_enabled()42 template rt_envvars_enabled()
43 {
44     pragma(mangle, cPrefix ~ "rt_envvars_enabled") __gshared bool rt_envvars_enabled = false;
45 }
rt_cmdline_enabled()46 template rt_cmdline_enabled()
47 {
48     pragma(mangle, cPrefix ~ "rt_cmdline_enabled") __gshared bool rt_cmdline_enabled = true;
49 }
rt_options()50 template rt_options()
51 {
52     pragma(mangle, cPrefix ~ "rt_options") __gshared string[] rt_options = [];
53 }
54 
55 import core.stdc.ctype : toupper;
56 import core.stdc.stdlib : getenv;
57 import core.stdc.string : strlen;
58 
59 extern extern(C) string[] rt_args() @nogc nothrow;
60 
61 alias rt_configCallBack = string delegate(string) @nogc nothrow;
62 
63 /**
64 * get a druntime config option using standard configuration options
65 *      opt             name of the option to retreive
66 *      dg              if non-null, passes the option through this
67 *                      delegate and only returns its return value if non-null
68 *      reverse         reverse the default processing order cmdline/envvar/rt_options
69 *                      to allow overwriting settings in the delegate with values
70 *                      from higher priority
71 *
72 * returns the options' value if
73 *  - set on the command line as "--DRT-<opt>=value" (rt_cmdline_enabled enabled)
74 *  - the environment variable "DRT_<OPT>" is set (rt_envvars_enabled enabled)
75 *  - rt_options[] contains an entry "<opt>=value"
76 *  - null otherwise
77 */
78 string rt_configOption(string opt, scope rt_configCallBack dg = null, bool reverse = false) @nogc nothrow
79 {
80     if (!dg)
81         dg = (string s) => s;
82 
83     string s = (reverse ? rt_linkOption(opt, dg) : rt_cmdlineOption(opt, dg));
84     if (s != null)
85         return s;
86     s = rt_envvarsOption(opt, dg);
87     if (s != null)
88         return s;
89     s = (reverse ? rt_cmdlineOption(opt, dg) : rt_linkOption(opt, dg));
90     return s;
91 }
92 
rt_cmdlineOption(string opt,scope rt_configCallBack dg)93 string rt_cmdlineOption(string opt, scope rt_configCallBack dg) @nogc nothrow
94 {
95     if (rt_cmdline_enabled!())
96     {
97         foreach (a; rt_args)
98         {
99             if (a.length >= opt.length + 7 && a[0..6] == "--DRT-" &&
100                 a[6 .. 6 + opt.length] == opt && a[6 + opt.length] == '=')
101             {
102                 string s = dg(a[7 + opt.length .. $]);
103                 if (s != null)
104                     return s;
105             }
106         }
107     }
108     return null;
109 }
110 
rt_envvarsOption(string opt,scope rt_configCallBack dg)111 string rt_envvarsOption(string opt, scope rt_configCallBack dg) @nogc nothrow
112 {
113     if (rt_envvars_enabled!())
114     {
115         if (opt.length >= 32)
116             assert(0);
117 
118         char[40] var = void;
119         var[0 .. 4] = "DRT_";
120         foreach (i, c; opt)
121             var[4 + i] = cast(char) toupper(c);
122         var[4 + opt.length] = 0;
123 
124         auto p = getenv(var.ptr);
125         if (p)
126         {
127             string s = dg(cast(string) p[0 .. strlen(p)]);
128             if (s != null)
129                 return s;
130         }
131     }
132     return null;
133 }
134 
rt_linkOption(string opt,scope rt_configCallBack dg)135 string rt_linkOption(string opt, scope rt_configCallBack dg) @nogc nothrow
136 {
137     foreach (a; rt_options!())
138     {
139         if (a.length > opt.length && a[0..opt.length] == opt && a[opt.length] == '=')
140         {
141             string s = dg(a[opt.length + 1 .. $]);
142             if (s != null)
143                 return s;
144         }
145     }
146     return null;
147 }
148