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;
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 private:
51     string virtual_path;
52 
53     static template toInternalHeader(string file) {
54         enum toInternalHeader = InternalHeader(file, import(file));
55     }
56 
57     // dfmt off
58     enum internalHeaders = [
59         staticMap!(toInternalHeader,
60                    "float.h",
61                    "limits.h",
62                    "stdalign.h",
63                    "stdarg.h",
64                    "stdbool.h",
65                    "stddef.h",
66                    "stdint.h",
67                    "__stddef_max_align_t.h"
68                    )
69     ];
70     // dfmt on
71 }
72 
73 private:
74 
75 string virtualPath() @safe pure nothrow {
76     import std.path : buildPath;
77 
78     version (Windows) {
79         enum root = `C:\`;
80     } else {
81         enum root = "/";
82     }
83     enum root_suffix = "dextool_clang";
84 
85     return buildPath(root, uniquePathId, root_suffix);
86 }
87 
88 struct InternalHeader {
89     string filename;
90     string content;
91 }
92 
93 struct HeaderResult {
94     private InternalHeader[] hdrs;
95     private string virtual_path;
96     private size_t idx;
97 
98     InternalHeader front() @safe pure nothrow {
99         import std.path : buildPath;
100 
101         assert(!empty, "Can't get front of an empty range");
102         auto path = buildPath(virtual_path, hdrs[idx].filename);
103         return InternalHeader(path, hdrs[idx].content);
104     }
105 
106     void popFront() @safe pure nothrow {
107         assert(!empty, "Can't pop front of an empty range");
108         ++idx;
109     }
110 
111     bool empty() @safe pure nothrow const @nogc {
112         return idx == hdrs.length;
113     }
114 }