[SHELL32] Fix Control_RunDLLW (#5400)
[reactos.git] / sdk / tools / ofw_interface / ofw_interface.cpp
1 #include <stdio.h>
2 #include <iostream>
3 #include <fstream>
4 #include <sstream>
5 #include <string>
6 #include <vector>
7
8 class ofw_wrappers {
9 public:
10 int base, ctindex, method_ctindex;
11 std::string functions;
12 std::string names;
13 std::string calltable;
14 std::string le_stubs;
15 std::string of_call;
16 };
17
18 class vartype {
19 public:
20 vartype( const std::string &typestr ) {
21 size_t amp = typestr.find('&');
22 size_t col = typestr.find(':');
23 if( amp != std::string::npos ) {
24 if( col > amp && col != std::string::npos )
25 lit_value = typestr.substr(amp+1,col-amp+1);
26 else lit_value = typestr.substr(amp+1);
27 }
28 if( col != std::string::npos ) {
29 if( amp > col && amp != std::string::npos )
30 len = typestr.substr(col+1,amp-col+1);
31 else len = typestr.substr(col+1);
32 }
33
34 if( amp != std::string::npos && amp < col ) col = amp;
35 if( col == std::string::npos ) col = typestr.size();
36 c_type = typestr.substr(0,col);
37 }
38
39 vartype( const vartype &other )
40 : c_type(other.c_type),
41 len(other.len),
42 lit_value(other.lit_value) {
43 }
44
45 vartype &operator = ( const vartype &other ) {
46 c_type = other.c_type;
47 len = other.len;
48 lit_value = other.lit_value;
49 return *this;
50 }
51
52 std::string c_type;
53 std::string len;
54 std::string lit_value;
55 };
56
57 std::string uppercase( const std::string &toucase ) {
58 std::vector<char> ucase_work(toucase.size());
59 for( size_t i = 0; i < toucase.size(); i++ ) {
60 ucase_work[i] = toupper(toucase[i]);
61 }
62 return std::string(&ucase_work[0], toucase.size());
63 }
64
65 std::string clip_eol( std::string in, const std::string &eol_marks ) {
66 size_t found;
67 for( size_t i = 0; i < eol_marks.size(); i++ ) {
68 found = in.find( eol_marks[i] );
69 if( found != std::string::npos )
70 in = in.substr( 0, found );
71 }
72 return in;
73 }
74
75 int round_up( int x, int factor ) {
76 return (x + (factor - 1)) & ~(factor - 1);
77 }
78
79 void populate_definition( ofw_wrappers &wrapper, const std::string &line ) {
80 std::istringstream iss(line);
81 bool make_function = true, method_call = false, make_stub = true, comma;
82 std::string name, nametext, argtype, rettype;
83 std::vector<vartype> argtypes;
84 int args, rets, i, local_offset, total_stack, userarg_start = 0;
85 size_t f;
86 std::ostringstream function, ct_csource, le_stub, of_call;
87
88 iss >> name >> args >> rets;
89
90 if( !name.size() ) return;
91
92 if( (f = name.find('!')) != std::string::npos ) {
93 nametext = name.substr(f+1);
94 name = name.substr(0,f);
95 }
96 if( name[0] == '-' ) {
97 name = name.substr(1);
98 make_function = false;
99 }
100 if( name[0] == '+' ) {
101 name = name.substr(1);
102 make_stub = false;
103 }
104 if( name[0] == '@' ) {
105 name = name.substr(1);
106 method_call = true;
107 make_function = false;
108 }
109
110 if( !nametext.size() ) nametext = name;
111
112 for( i = 1; i < (int)name.size(); i++ )
113 if( name[i] == '-' ) name[i] = '_';
114
115 if( nametext == "call-method" )
116 wrapper.method_ctindex = wrapper.ctindex;
117
118 for( i = 0; i < args; i++ ) {
119 iss >> argtype;
120 argtypes.push_back(vartype(argtype));
121 }
122
123 if( method_call ) {
124 userarg_start = 1;
125 args += 2;
126 }
127
128 iss >> rettype;
129 if( !rettype.size() ) rettype = "void";
130
131 local_offset = (3 + rets + args) * 4;
132 total_stack = round_up(12 + local_offset, 16);
133
134 function << "asm_ofw_" << name << ":\n"
135 << "\t/* Reserve stack space */\n"
136 << "\tsubi %r1,%r1," << total_stack << "\n"
137 << "\t/* Store r8, r9, lr */\n"
138 << "\tstw %r8," << (local_offset + 0) << "(%r1)\n"
139 << "\tstw %r9," << (local_offset + 4) << "(%r1)\n"
140 << "\tmflr %r8\n"
141 << "\tstw %r8," << (local_offset + 8) << "(%r1)\n"
142 << "\t/* Get read name */\n"
143 << "\tlis %r8," << name << "_ofw_name@ha\n"
144 << "\taddi %r9,%r8," << name << "_ofw_name@l\n"
145 << "\tstw %r9,0(%r1)\n"
146 << "\t/* " << args << " arguments and " << rets << " return */\n"
147 << "\tli %r9," << args << "\n"
148 << "\tstw %r9,4(%r1)\n"
149 << "\tli %r9," << rets << "\n"
150 << "\tstw %r9,8(%r1)\n";
151
152 for( int i = 0; i < args; i++ )
153 function << "\tstw %r" << (i+3) << "," << (4 * (i + 3)) << "(%r1)\n";
154
155 function << "\t/* Load up the call address */\n"
156 << "\tlis %r10,ofw_call_addr@ha\n"
157 << "\tlwz %r9,ofw_call_addr@l(%r10)\n"
158 << "\tmtlr %r9\n"
159 << "\t/* Set argument */\n"
160 << "\tmr %r3,%r1\n"
161 << "\t/* Fire */\n"
162 << "\tblrl\n"
163 << "\tlwz %r3," << (local_offset - 4) << "(%r1)\n"
164 << "\t/* Restore registers */\n"
165 << "\tlwz %r8," << (local_offset + 8) << "(%r1)\n"
166 << "\tmtlr %r8\n"
167 << "\tlwz %r9," << (local_offset + 4) << "(%r1)\n"
168 << "\tlwz %r8," << (local_offset + 0) << "(%r1)\n"
169 << "\t/* Return */\n"
170 << "\taddi %r1,%r1," << total_stack << "\n"
171 << "\tblr\n";
172
173 if( method_call ) {
174 argtypes.insert(argtypes.begin(),vartype("int"));
175 argtypes.insert(argtypes.begin(),vartype("char*"));
176 }
177
178 le_stub << rettype << " ofw_" << name << "(";
179
180 comma = false;
181 for( i = userarg_start; i < args; i++ ) {
182 if( !argtypes[i].lit_value.size() ) {
183 if( !comma ) comma = true; else le_stub << ",";
184 le_stub << argtypes[i].c_type << " arg" << i;
185 }
186 }
187 le_stub << ")";
188 of_call << le_stub.str() << ";\n";
189
190 le_stub << " {\n";
191 if( rettype != "void" )
192 le_stub << "\t" << rettype << " ret;\n";
193
194 if( method_call ) {
195 le_stub << "\tchar arg0["
196 << round_up(nametext.size()+1,8)
197 << "] = \"" << nametext << "\";\n";
198 }
199
200 for( i = 0; i < args; i++ ) {
201 if( argtypes[i].lit_value.size() ) {
202 le_stub << "\t" << argtypes[i].c_type << " arg" << i << " = "
203 << argtypes[i].lit_value << ";\n";
204 }
205 }
206
207 le_stub << "\t";
208 if( rettype != "void" ) le_stub << "ret = (" << rettype << ")";
209
210 le_stub << "ofproxy(" <<
211 (method_call ? (wrapper.method_ctindex * 4) : (wrapper.ctindex * 4));
212
213 for( i = 0; i < 6; i++ ) {
214 if( i < args ) le_stub << ",(void *)arg" << i;
215 else le_stub << ",NULL";
216 }
217
218 le_stub << ");\n";
219
220 if( rettype != "void" )
221 le_stub << "\treturn ret;\n";
222
223 le_stub << "}\n";
224
225 if( make_function ) wrapper.functions += function.str();
226 if( make_stub ) {
227 wrapper.le_stubs += le_stub.str();
228 wrapper.of_call += of_call.str();
229 }
230 if( !method_call ) {
231 wrapper.names += name + "_ofw_name:\n\t.asciz \"" + nametext + "\"\n";
232 wrapper.calltable += std::string("\t.long asm_ofw_") + name + "\n";
233 wrapper.ctindex++;
234 }
235 }
236
237 int main( int argc, char **argv ) {
238 int status = 0;
239 std::ifstream in;
240 std::ofstream out, outcsource, outcheader;
241 std::string line;
242 const char *eol_marks = "#\r\n";
243 ofw_wrappers wrappers;
244
245 wrappers.base = 0xe00000;
246 wrappers.ctindex = 0;
247
248 if( argc < 5 ) {
249 fprintf( stderr, "%s [interface.ofw] [ofw.s] [le_stub.c] [le_stub.h]\n", argv[0] );
250 return 1;
251 }
252
253 in.open( argv[1] );
254 if( !in ) {
255 fprintf( stderr, "can't open %s\n", argv[1] );
256 status = 1;
257 goto error;
258 }
259
260 out.open( argv[2] );
261 if( !out ) {
262 fprintf( stderr, "can't open %s\n", argv[2] );
263 status = 1;
264 goto error;
265 }
266
267 outcsource.open( argv[3] );
268 if( !outcsource ) {
269 fprintf( stderr, "can't open %s\n", argv[3] );
270 status = 1;
271 goto error;
272 }
273
274 outcheader.open( argv[4] );
275 if( !outcheader ) {
276 fprintf( stderr, "can't open %s\n", argv[4] );
277 status = 1;
278 goto error;
279 }
280
281 while( std::getline( in, line ) ) {
282 line = clip_eol( line, eol_marks );
283 if( line.size() ) populate_definition( wrappers, line );
284 }
285
286 out << "/* AUTOMATICALLY GENERATED BY ofw_interface */\n"
287 << "\t.section .text\n"
288 << "\t.align 4\n"
289 << "\t.globl _start\n"
290 << "\t.globl ofw_functions\n"
291 << "\t.globl ofw_call_addr\n"
292 << "ofw_call_addr:\n"
293 << "\t.long 0\n"
294 << "\n/* Function Wrappers */\n\n"
295 << wrappers.functions
296 << "\n/* Function Names */\n\n"
297 << wrappers.names
298 << "\n/* Function Call Table for Freeldr */\n\n"
299 << "\t.align 4\n"
300 << "ofw_functions:\n"
301 << wrappers.calltable
302 << "\n/* End */\n";
303
304 outcsource << "/* AUTOMATICALLY GENERATED BY ofw_interface */\n"
305 << "#include \"of.h\"\n"
306 << wrappers.le_stubs;
307
308 outcheader << "/* AUTOMATICALLY GENERATE BY ofw_interface */\n"
309 << "#ifndef _OFW_CALLS_H\n"
310 << "#define _OFW_CALLS_H\n"
311 << wrappers.of_call
312 << "#endif/*_OFW_CALLS_H*/\n";
313
314 error:
315 return status;
316 }