1 /**
2  * Copyright: Copyright (c) 2015 Jacob Carlborg. All rights reserved.
3  * Authors: Jacob Carlborg
4  * Version: 1.1
5  * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6  *
7  * History:
8  *  1.0 Initial created: Jan 31, 2015 $(BR)
9  *      Jacob Carlborg
10  *  1.1 updated to clang 3.6 with additional internal header $(BR)
11  *      Joakim Brännström
12  */
13 module clang.Compiler;
14 
15 @safe:
16 
17 private const(string) uniquePathId;
18 
19 static this() {
20     import std.conv : text;
21     import std.random;
22 
23     // Keep the identifier the same while running.
24     // Easier for the user to reason about what it is, where it comes from.
25     uniquePathId = text(uniform(1, 10_000_000));
26 }
27 
28 /** Clang specific in-memory files.
29  *
30  * Imported into the binary during compilation time.
31  */
32 struct Compiler {
33     import std.algorithm : any, map, joiner;
34     import std.path : buildPath;
35     import std.meta : staticMap;
36 
37     HeaderResult extraHeaders() {
38         return HeaderResult(internalHeaders, extraIncludePath);
39     }
40 
41     /// Returns: The virtual path the internal headers are located at.
42     string extraIncludePath() {
43         if (virtual_path is null) {
44             virtual_path = virtualPath;
45         }
46 
47         return virtual_path;
48     }
49 
50     string[] extraIncludeFlags() {
51         import std.algorithm;
52         import std.array;
53 
54         return [extraIncludePath].map!(x => ["-isystem", x]).joiner.array;
55     }
56 
57 private:
58     string virtual_path;
59 
60     static template toInternalHeader(string file) {
61         enum toInternalHeader = InternalHeader(file, import(file));
62     }
63 
64     // dfmt off
65     enum internalHeaders = [
66         staticMap!(toInternalHeader,
67                    "__stddef_max_align_t.h",
68                    "float.h",
69                    "limits.h",
70                    "stdalign.h",
71                    "stdarg.h",
72                    "stdbool.h",
73                    "stddef.h",
74                    "stdint.h",
75                    )
76     ];
77     // dfmt on
78 }
79 
80 private:
81 
82 string virtualPath() @safe pure nothrow {
83     import std.path : buildPath;
84 
85     version (Windows) {
86         enum root = `C:\`;
87     } else {
88         enum root = "/";
89     }
90     enum root_suffix = "dextool_clang";
91 
92     return buildPath(root, uniquePathId, root_suffix);
93 }
94 
95 struct InternalHeader {
96     string filename;
97     string content;
98 }
99 
100 struct HeaderResult {
101     private InternalHeader[] hdrs;
102     private string virtual_path;
103     private size_t idx;
104 
105     InternalHeader front() @safe pure nothrow {
106         import std.path : buildPath;
107 
108         assert(!empty, "Can't get front of an empty range");
109         auto path = buildPath(virtual_path, hdrs[idx].filename);
110         return InternalHeader(path, hdrs[idx].content);
111     }
112 
113     void popFront() @safe pure nothrow {
114         assert(!empty, "Can't pop front of an empty range");
115         ++idx;
116     }
117 
118     bool empty() @safe pure nothrow const @nogc {
119         return idx == hdrs.length;
120     }
121 }