1 module test;
2 
3 import std.algorithm;
4 import std.array;
5 import std.conv;
6 import std.file;
7 import std.path;
8 import std.exception;
9 import std.process;
10 import std.string;
11 import std.stdio;
12 import std.typetuple;
13 import std.typecons;
14 import std.traits;
15 import std.range;
16 import std.regex;
17 
18 /**
19     Helper script which translates header files into D modules.
20 
21     Unsupported:
22         - typedefs and inline function definitions, these need to be manually ported
23         - #define's are not translated
24 */
25 
26 string translate(string input)
27 {
28     input = input.replace(regex(`GIT_EXTERN\(([^)]+)\)`, "g"), "$1");
29 
30     input = input.replace("GIT_BEGIN_DECL", "");
31     input = input.replace(`#include "`, "import git.c.");
32     input = input.replace(`.h"`, ";");
33     input = input.replace("import git.c.object;", "import git.c.object_;");
34     input = input.replace("import git.c.version;", "import git.c.version_;");
35 
36     input = input.replace(`/** @} */`, "");
37 
38     input = input.replace("#ifndef", "// #ifndef");
39     input = input.replace("#define", "// #define");
40 
41     input = input.replace("(void)", "()");
42     input = input.replace("const void *", "const(void)* ");
43     input = input.replace("unsigned short", "ushort");
44     input = input.replace("unsigned char", "ubyte");
45     input = input.replace("unsigned int", "uint");
46     input = input.replace("unsigned", "uint");
47     input = input.replace("**out,", "**out_,");
48     input = input.replace("*out,", "*out_,");
49     input = input.replace("**out)", "**out_)");
50     input = input.replace("*out)", "*out_)");
51     input = input.replace(" version;", " version_;");
52     input = input.replace(" ref,", "ref_,");
53     input = input.replace("*ref)", "*ref_)");
54     input = input.replace(" *ref, ", " *ref_, ");
55     input = input.replace(" *ref,", " *ref_,");
56 
57     input = input.replace("const char **", "const(char)** ");
58     input = input.replace("const char *", "const(char)* ");
59     input = input.replace("const char*", "const(char)*");
60     input = input.replace("const git_config *", "const(git_config)* ");
61     input = input.replace("const git_commit *", "const(git_commit)* ");
62     input = input.replace("const git_indexer_stream *", "const(git_indexer_stream)* ");
63     input = input.replace("const git_diff_file *", "const(git_diff_file)* ");
64     input = input.replace("const git_oid *", "const(git_oid)* ");
65     input = input.replace("const git_blob *", "const(git_blob)* ");
66     input = input.replace("const git_object *", "const(git_object)* ");
67     input = input.replace("const git_clone_options *", "const(git_clone_options)* ");
68     input = input.replace("const git_signature *", "const(git_signature)* ");
69     input = input.replace("const git_tree *", "const(git_tree)* ");
70     input = input.replace("const git_cvar_map *", "const(git_cvar_map)* ");
71     input = input.replace("const git_config_entry *", "const(git_config_entry)* ");
72     input = input.replace("const git_error *", "const(git_error)* ");
73     input = input.replace("const git_note *", "const(git_note)* ");
74     input = input.replace("const git_remote *", "const(git_remote)* ");
75     input = input.replace("const git_reference *", "const(git_reference)* ");
76     input = input.replace("const git_reflog_entry *", "const(git_reflog_entry)* ");
77     input = input.replace("const git_refspec *", "const(git_refspec)* ");
78     input = input.replace("const git_strarray *", "const(git_strarray)* ");
79     input = input.replace("const git_tree_entry *", "const(git_tree_entry)* ");
80     input = input.replace("const git_tag *", "const(git_tag)* ");
81     input = input.replace("const git_index *", "const(git_index)* ");
82     input = input.replace("const git_index_entry **", "const(git_index_entry)** ");
83     input = input.replace("const git_index_entry *", "const(git_index_entry)* ");
84     input = input.replace("const git_transfer_progress *", "const(git_transfer_progress)* ");
85     input = input.replace("const git_status_options *", "const(git_status_options)* ");
86     input = input.replace("const git_merge_tree_opts *", "const(git_merge_tree_opts)* ");
87     input = input.replace("const git_status_entry *", "const(git_status_entry)* ");
88     input = input.replace("const git_index_name_entry *", "const(git_index_name_entry)* ");
89     input = input.replace("const git_index_reuc_entry *", "const(git_index_reuc_entry)* ");
90 
91     input = input.replace("struct git_odb *", "git_odb* ");
92 
93     input = input.replace("GIT_END_DECL", "");
94     input = input.replace("#endif", "//#endif");
95 
96     input = input.replace("typedef enum", "enum");
97     input = input.replace("typedef struct", "struct");
98     input = input.replace("};", "}");
99 
100     return input;
101 }
102 
103 void main(string[] args)
104 {
105     args.popFront();
106 
107     bool force;
108     string name;
109 
110     foreach (arg; args)
111     {
112         if (arg == "-force" || arg == "--force")
113             force = true;
114         else
115             name = arg;
116     }
117 
118     auto str = cast(string)std.file.read(name);
119 
120     auto res = str.translate;
121 
122     auto app = appender!string();
123     app ~= format("module git.c.%s;\n\n", name.stripExtension.baseName);
124     app ~= "extern (C):\n\n";
125     app ~= res;
126 
127     string path = buildPath(".", name.stripExtension.baseName.setExtension(".d"))
128         .absolutePath.buildNormalizedPath;
129     //~ writeln(path);
130 
131     if (!force)
132         enforce(!path.exists, format("Won't overwrite file '%s'", path));
133 
134     std.file.write(path, app.data);
135 
136     executeShell(format("scite %s", path));
137 }
138