1 module clang.util;
2 
3 
4 version (Windows) {
5     extern(C) private int _mktemp_s(char* nameTemplate, size_t sizeInChars) nothrow @safe @nogc;
6 }
7 
8 
9 /**
10    Makes a member variable lazy so that it's only computed if necessary.
11    Very hacky, uses undefined behaviour by casting const away as if
12    it were using C++'s `mutable`.
13  */
14 mixin template Lazy(alias memberVariable) {
15 
16     import std.format: format;
17 
18     private enum id = __traits(identifier, memberVariable);
19     static assert(id[0] == '_',
20                   "`" ~ id ~ "` does not start with an underscore");
21 
22     private enum initVar = id ~ `Init`;
23     mixin(`bool `, initVar, `;`);
24 
25     private enum str = q{
26             ref %s()() @property const scope return {
27                 import std.traits: Unqual;
28                 if(!%s) {
29                     () @trusted { cast(bool) %s = true; }();
30                     () @trusted { cast(Unqual!(typeof(%s))) %s = %s; }();
31                 }
32                 return %s;
33             }
34         }.format(
35             id[1..$],
36             initVar,
37             initVar,
38             id, id, id ~ `Create`,
39             id,
40         )
41     ;
42 
43     //pragma(msg, str);
44     mixin(str);
45 }
46 
47 
48 /**
49    Returns a suitable temporary file name
50  */
51 string getTempFileName() @trusted {
52     import std.file: tempDir;
53     import std.path: buildPath;
54     import std.string: fromStringz;
55     import std.process: environment;
56 
57     const dir = environment.get("APPVEYOR", null) is null
58         ? tempDir
59         : ".";
60 
61     char[] tmpnamBuf = buildPath(dir, "libclangXXXXXX\0").dup;
62 
63     version (Posix) {
64         import core.sys.posix.stdlib: mkstemp;
65         mkstemp(&tmpnamBuf[0]);
66     }
67     else version (Windows)
68         _mktemp_s(&tmpnamBuf[0], tmpnamBuf.length);
69 
70     return tmpnamBuf.idup;
71 }