Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
bindgen_main.cpp
Go to the documentation of this file.
1#include <algorithm>
2#include <iostream>
3#include <fstream>
4#include <sstream>
5#include <vector>
6#include <string>
7#include <algorithm>
8
9const std::vector<std::string> PATCHES = {"#pragma warning(disable:4996)", "#pragma warning(disable:4244)"};
10
11struct Param
12{
13 std::string type;
14 std::string name;
15};
16
18{
19 std::string returnType;
20 std::string name;
21 std::vector<Param> params;
22 std::string rawLine;
23 int lineNumber = 0;
24};
25
26bool isHandleType(const std::string &type)
27{
28 return type == "HANDLE" || type == "HMODULE" || type == "HWND" || type == "HINSTANCE" || type == "HDC";
29}
30
31bool isSupportedParam(const std::string &type)
32{
33 if (isHandleType(type))
34 {
35 return true;
36 }
37
38 std::string t = type;
39 std::erase(t, ' ');
40 return t == "BOOL" || t == "DWORD" || t == "int" || t == "LONG" || t == "UINT" || t == "ULONG" || t == "float" ||
41 t == "double" || t == "LPCSTR" || t == "LPSTR" || t == "constchar*" || t == "LPCWSTR" || t == "LPWSTR" ||
42 t == "constwchar_t*";
43}
44
45std::string trim(const std::string &str)
46{
47 size_t start = str.find_first_not_of(" \t\r\n");
48 if (start == std::string::npos)
49 {
50 return "";
51 }
52 size_t end = str.find_last_not_of(" \t\r\n");
53 return str.substr(start, end - start + 1);
54}
55
56Function parseFunction(const std::string &line, int lineNumber)
57{
58 Function f;
59 f.rawLine = line;
60 f.lineNumber = lineNumber;
61
62 std::string clean = line;
63 std::erase(clean, ';');
64
65 size_t paren = clean.find('(');
66 if (paren == std::string::npos)
67 {
68 return f;
69 }
70
71 std::string retAndName = clean.substr(0, paren);
72 std::string paramStr = clean.substr(paren + 1, clean.find(')') - paren - 1);
73
74 std::istringstream iss(retAndName);
75 iss >> f.returnType >> f.name;
76
77 paramStr = trim(paramStr);
78 if (paramStr.empty() || paramStr == "void")
79 {
80 return f;
81 }
82
83 std::istringstream pstream(paramStr);
84 std::string param;
85 while (std::getline(pstream, param, ','))
86 {
87 param = trim(param);
88 if (param.empty())
89 {
90 continue;
91 }
92
93 std::istringstream ps(param);
94 Param p;
95 ps >> p.type >> p.name;
96
97 if (!isSupportedParam(p.type))
98 {
99 f.returnType.clear();
100 break;
101 }
102
103 f.params.push_back(p);
104 }
105
106 return f;
107}
108
109void generateWrapper(const Function &f, std::ostream &out)
110{
111 if (f.returnType.empty())
112 {
113 return;
114 }
115
116 out << "// " << f.rawLine << " @ln:" << f.lineNumber << "\n";
117 out << "static PhasorValue win32_" << f.name
118 << "([[maybe_unused]] PhasorVM* vm, [[maybe_unused]] int argc, [[maybe_unused]] const PhasorValue* argv) {\n";
119
120 for (size_t i = 0; i < f.params.size(); ++i)
121 {
122 const auto &p = f.params[i];
123
124 if (isHandleType(p.type))
125 {
126 out << " " << p.type << " " << p.name << " = HandleSystem::resolve<" << p.type << ">(phasor_to_int(argv["
127 << i << "]));\n";
128 continue;
129 }
130
131 std::string conv;
132 if (p.type == "BOOL")
133 {
134 conv = "phasor_to_bool(argv[" + std::to_string(i) + "])";
135 }
136 else if (p.type == "DWORD" || p.type == "int" || p.type == "LONG" || p.type == "UINT" || p.type == "ULONG")
137 {
138 conv = "(" + p.type + ")phasor_to_int(argv[" + std::to_string(i) + "])";
139 }
140 else if (p.type == "float" || p.type == "double")
141 {
142 conv = "(" + p.type + ")phasor_to_float(argv[" + std::to_string(i) + "])";
143 }
144 else if (p.type == "LPCSTR" || p.type == "constchar*")
145 {
146 conv = "(const char*)phasor_to_string(argv[" + std::to_string(i) + "])";
147 }
148 else if (p.type == "LPSTR")
149 {
150 conv = "(char*)phasor_to_string(argv[" + std::to_string(i) + "])";
151 }
152 else if (p.type == "LPCWSTR" || p.type == "constwchar_t*")
153 {
154 conv = "(const wchar_t*)phasor_to_string(argv[" + std::to_string(i) + "])";
155 }
156 else
157 {
158 conv = "(wchar_t*)phasor_to_string(argv[" + std::to_string(i) + "])";
159 }
160
161 out << " " << p.type << " " << p.name << " = " << conv << ";\n";
162 }
163
164 out << " auto result = " << f.name << "(";
165 for (size_t i = 0; i < f.params.size(); ++i)
166 {
167 if (i != 0u)
168 {
169 out << ", ";
170 }
171 out << f.params[i].name;
172 }
173 out << ");\n";
174
175 if (isHandleType(f.returnType))
176 {
177 out << " auto id = HandleSystem::store(result);\n";
178 out << " return phasor_make_int(id);\n";
179 }
180 else if (f.returnType == "BOOL")
181 {
182 out << " return phasor_make_bool(result);\n";
183 }
184 else if (f.returnType == "float" || f.returnType == "double")
185 {
186 out << " return phasor_make_float(result);\n";
187 }
188 else if (f.returnType == "DWORD" || f.returnType == "int" || f.returnType == "LONG" || f.returnType == "UINT" ||
189 f.returnType == "ULONG")
190 {
191 out << " return phasor_make_int(result);\n";
192 }
193 else
194 {
195 out << " return phasor_make_null();\n";
196 }
197
198 out << "}\n\n";
199}
200
201int main(int argc, char **argv)
202{
203 std::string inputFile = "winapi.h";
204 std::string outputFile = "phasor_winapi.cpp";
205
206 if (argc >= 2)
207 {
208 inputFile = argv[1];
209 }
210 if (argc >= 4 && std::string(argv[2]) == "-o")
211 {
212 outputFile = argv[3];
213 }
214
215 std::ifstream infile(inputFile);
216 std::ofstream outfile(outputFile);
217
218 outfile << "#define PHASOR_FFI_BUILD_DLL\n";
219 outfile << "#include <PhasorFFI.h>\n";
220 outfile << "#include <windows.h>\n";
221 outfile << "#include \"../src/Bindings/win32/handle.hpp\"\n\n";
222 outfile << "// =====BEGIN PATCHES=====\n";
223 for (const auto &patch : PATCHES)
224 {
225 outfile << patch << "\n";
226 }
227 outfile << "// ======END PATCHES======\n\n";
228
229 std::string line;
230 int lineNumber = 0;
231 std::vector<Function> funcs;
232
233 while (std::getline(infile, line))
234 {
235 lineNumber++;
236 if (line.empty())
237 {
238 continue;
239 }
240
241 Function f = parseFunction(line, lineNumber);
242 if (!f.returnType.empty())
243 {
244 funcs.push_back(f);
245 }
246 }
247
248 for (const auto &f : funcs)
249 {
250 generateWrapper(f, outfile);
251 }
252
253 outfile << "PHASOR_FFI_EXPORT void phasor_plugin_entry(const PhasorAPI* api, PhasorVM* vm) {\n";
254 for (const auto &f : funcs)
255 {
256 outfile << " api->register_function(vm, \"win32_" << f.name << "\", win32_" << f.name << ");\n";
257 }
258 outfile << "}\n";
259}
int main()
Definition LSP_main.cpp:130
bool isSupportedParam(const std::string &type)
std::string trim(const std::string &str)
const std::vector< std::string > PATCHES
bool isHandleType(const std::string &type)
Function parseFunction(const std::string &line, int lineNumber)
void generateWrapper(const Function &f, std::ostream &out)
std::string name
std::string rawLine
std::vector< Param > params
std::string returnType
std::string name
std::string type