1 module support; // dockerfile_parser;
2 
3 struct Result(T)
4 {
5 	string errorMessage;
6 	T* result;
7 }
8 
9 struct Command
10 {
11     string command;
12     string subCommand;
13     bool json;
14     string original;
15     int startLine;
16     int endLine;
17     string[] flags;
18     string[] values;
19 }
20 
21 export extern(C)
22 void* return_success(void* ret)
23 {
24 	auto result = new Result!(void*)(null,cast(void**)ret);
25 	return cast(void*) result;
26 }
27 
28 export extern(C)
29 void* raise(const(char)* errorMessage)
30 {
31 	import std..string : toStringz, fromStringz;
32 	import core.stdc.stdlib : free;
33 	bool shouldFree = true;
34 	auto niceErrorMessage = (errorMessage is null) ? "UNKNOWN GOLANG ERROR" : errorMessage.fromStringz.idup;
35 	auto result = new Result!(void*)(niceErrorMessage);
36 	if (errorMessage !is null)
37 		free(cast(void*)errorMessage);
38 	return cast(void*) result;
39 }
40 
41 export extern(C)
42 void* command(char* cmd, char* sub_cmd, int json, char* original, int start_line, int end_line, void* flags, void* value)
43 {
44 	import std..string : fromStringz;
45 	import core.stdc.stdlib : free;
46 
47 	auto ret = new Command;
48 	ret.command = cmd.fromStringz.idup;
49 	ret.subCommand = sub_cmd.fromStringz.idup;
50 	ret.json = (json != 0);
51 	ret.original = original.fromStringz.idup;
52 	ret.startLine = start_line;
53 	ret.endLine = end_line;
54 	auto flagsV = cast(StringSlice*) flags;
55 	ret.flags = (*flagsV).values;
56 	auto valuesV = cast(StringSlice*) value;
57 	ret.values = (*valuesV).values;
58 	free(cmd);
59 	free(sub_cmd);
60 	free(original);
61 	return cast(void*) new Result!Command(null,ret);
62 }
63 
64 extern(C) void* parse_string(const(char)* s);
65 extern(C) void* parse_file(const(char)* filename);
66 extern(C) void* all_commands();
67 
68 alias CommandResult = Result!Command;
69 alias CommandSlice = Slice!Command;
70 alias CommandSliceResult = Result!(Slice!Command);
71 alias StringSlice = Slice!string;
72 alias StringSliceResult = Result!(Slice!string);
73 
74 Command[] parseString(string s)
75 {
76 	import std..string : toStringz, fromStringz;
77 	import std.exception : enforce;
78 	auto p = cast(CommandSliceResult*) parse_string(s.toStringz);
79 	enforce(p !is null, "parse_string failed");
80 	enforce(p.errorMessage.length ==0, p.errorMessage);
81 	auto result = *p.result;
82 	return result.values;
83 }
84 
85 Command[] parseFile(string filename)
86 {
87 	import std..string : toStringz, fromStringz;
88 	import std.exception : enforce;
89 	auto p = cast(CommandSliceResult*) parse_file(filename.toStringz);
90 	enforce(p !is null, "parse_file failed");
91 	enforce(p.errorMessage.length ==0, p.errorMessage);
92 	auto result = *p.result;
93 	return result.values;
94 }
95 
96 string[] allCommands()
97 {
98 	import std..string : fromStringz;
99 	import std.exception : enforce;
100 	auto p = cast(StringSliceResult*) all_commands();
101 	enforce(p !is null, "all_commands failed");
102 	enforce(p.errorMessage.length ==0, p.errorMessage);
103 	auto result = *p.result;
104 	return result.values;
105 }
106 
107 
108 struct Slice(T)
109 {
110 	T[] values;
111 }
112 
113 export extern(C)
114 void* stringSlice(size_t length)
115 {
116 	auto ret = new Slice!string;
117 	ret.values.length = length;
118 	return cast(void*) ret;
119 }
120 
121 export extern(C)
122 void* commandSlice(size_t length)
123 {
124 	auto ret = new Slice!Command;
125 	ret.values.length = length;
126 	return cast(void*) ret;
127 }
128 
129 export extern(C)
130 void setStringElement(void* sliceV, size_t i, char* s)
131 {
132 	import core.stdc.stdlib : free;
133 	import std.exception : enforce;
134 	import std..string : fromStringz;
135 
136 	auto slice = cast(StringSlice*) sliceV;
137 	enforce(slice.values.length > i);
138 	slice.values[i] = fromStringz(s).idup;
139 	free(s);
140 }
141 
142 export extern(C)
143 void setCommandElement(void* sliceV, size_t i, void* p)
144 {
145 	import std.exception : enforce;
146 	assert(p !is null, "setCommandElement called with null");
147 	auto slice = cast(CommandSlice*) sliceV;
148 	enforce(slice.values.length > i);
149 	auto pTyped = cast(CommandResult*) p;
150 	slice.values[i] = *pTyped.result;
151 }
152