forked from livecode/livecode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathweak_stub_maker.lc
More file actions
320 lines (280 loc) · 9.61 KB
/
weak_stub_maker.lc
File metadata and controls
320 lines (280 loc) · 9.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
#! /usr/bin/revolution -ui
local sgModuleSymbols
local sgModuleDetails
on startup
try
process
catch tError
write tError & return to stdout
end try
end startup
on process
local tSpec
read from stdin until eof
put it into tSpec
local tLine, tModule
repeat for each line tLine in tSpec
if word 1 to -1 of tLine is empty then
next repeat
end if
if char 1 of word 1 of tLine is "#" then
next repeat
end if
if char 1 of tLine is not tab then
put word 1 of tLine into tModule
put word 2 to -1 of tLine into sgModuleDetails[tModule]
else if word 1 to -1 of (char 2 to -1 of tLine) is not empty then
put word 1 to -1 of (char 2 to -1 of tLine) & return after sgModuleSymbols[tModule]
end if
end repeat
output "#include <stdlib.h>"
output "#include <stdio.h>"
output "#include <cstring>"
output "#if defined(_MACOSX) || defined(_MAC_SERVER)"
output "#define SYMBOL_PREFIX " & quote & "_" & quote
output "#else"
output "#define SYMBOL_PREFIX"
output "#endif"
output
output "typedef void *module_t;"
output "typedef void *handler_t;"
output
output "extern " & quote & "C" & quote & " void *MCU_loadmodule(const char *);"
output "extern " & quote & "C" & quote & " void MCU_unloadmodule(void *);"
output "extern " & quote & "C" & quote & " void *MCU_resolvemodulesymbol(void *, const char *);"
output
output "extern " & quote & "C" & quote
output "{"
output ;
output "static int module_load(const char *p_source, module_t *r_module)"
output "{"
output " module_t t_module;"
output " t_module = (module_t)MCU_loadmodule(p_source);"
output " if (t_module == NULL)"
output " return 0;"
output " *r_module = t_module;"
output " return 1;"
output "}"
output
-- MM-2014-02-14: [[ LibOpenSSL 1.0.1e ]] Implemented module_unload for Android.
output "static int module_unload(module_t p_module)"
output "{"
output " MCU_unloadmodule(p_module);"
output " return 1;"
output "}"
output
output "static int module_resolve(module_t p_module, const char *p_name, handler_t *r_handler)"
output "{"
output " handler_t t_handler;"
output " t_handler = MCU_resolvemodulesymbol(p_module, p_name);"
output " if (t_handler == NULL)"
output " return 0;"
output " *r_handler = t_handler;"
output " return 1;"
output "}"
output
repeat for each line tModule in the keys of sgModuleDetails
generateModule tModule
end repeat
#include <assert.h>
output "}"
end process
on generateModule pModule
local tUnixLibrary, tDarwinLibrary, tWindowsLibrary
put word 1 of sgModuleDetails[pModule] into tUnixLibrary
put word 2 of sgModuleDetails[pModule] into tDarwinLibrary
put word 3 of sgModuleDetails[pModule] into tWindowsLibrary
local tSymbols
put sgModuleSymbols[pModule] into tSymbols
local tSymbol
repeat for each line tSymbol in tSymbols
if not symbolIsReference(tSymbol) then
output "typedef " & typelistToProto(symbolOutputs(tSymbol), false) & "(*" & symbolName(tSymbol) & "_t)(" & typelistToProto(symbolInputs(tSymbol), true) & ");"
output symbolName(tSymbol) & "_t" && symbolName(tSymbol) & "_ptr = NULL;"
else
output "void *" & symbolName(tSymbol) & "_ptr = NULL;"
end if
# output "handler_t " & tSymbol & "_ptr = NULL;"
end repeat
output
output "#if defined(_MACOSX) || defined(TARGET_SUBPLATFORM_IPHONE) || defined(_MAC_SERVER)"
output "#define MODULE_" & toUpper(pModule) & "_NAME" && quote & tDarwinLibrary & quote
output "#elif defined(_LINUX)"
output "#define MODULE_" & toUpper(pModule) & "_NAME" && quote & tUnixLibrary & quote
-- MM-2014-02-10: [[ LipOpenSSL 1.0.1e ]] Prefix android modules with lib.
output "#elif defined(TARGET_SUBPLATFORM_ANDROID)"
output "#define MODULE_" & toUpper(pModule) & "_NAME" && quote & "lib" & tUnixLibrary & quote
output "#elif defined(_WINDOWS)"
output "#define MODULE_" & toUpper(pModule) & "_NAME" && quote & tWindowsLibrary & quote
output "#endif"
output
output "static module_t module_" & pModule & " = NULL;"
output
-- MM-2014-02-14: [[ LibOpenSSL 1.0.1e ]] Added finalise function and made sure staid variables are initialised to NULL.
output "void finalise_weak_link_" & pModule & "(void)"
output "{"
output " module_unload(module_" & pModule & ");"
output " module_" & pModule & " = NULL;"
output "}"
output
-- IM-2014-03-21: [[ revBrowserCEF ]] Modify init function to take a path
output "int initialise_weak_link_" & pModule & "_with_path(const char *p_path)"
output "{"
output " module_" & pModule & " = NULL;"
output merge(" if (!module_load(p_path, &module_[[pModule]]))")
output "{"
output "#ifdef _DEBUG"
output " fprintf(stderr, " & quote & "Unable to load library: %s\n" & quote & ", p_path);"
output "#endif"
output "goto err;"
output "}"
output
repeat for each line tSymbol in tSymbols
if symbolIsOptional(tSymbol) then
output merge("module_resolve(module_[[pModule]], SYMBOL_PREFIX [[quote]][[symbolName(tSymbol)]][[quote]], (handler_t *)&[[symbolName(tSymbol)]]_ptr);")
else
output merge(" if (!module_resolve(module_[[pModule]], SYMBOL_PREFIX [[quote]][[symbolName(tSymbol)]][[quote]], (handler_t *)&[[symbolName(tSymbol)]]_ptr))")
output "{"
output "#ifdef _DEBUG"
output "fprintf(stderr, " & quote & "Unable to load: " & symbolName(tSymbol) & "\n" & quote & "); "
output "#endif"
output "goto err; "
output "}"
end if
end repeat
output
output " return 1;"
output
output "err:"
output merge(" if (module_[[pModule]] != NULL)")
output merge(" module_unload(module_[[pModule]]);")
output
output " return 0;"
output "}"
output
-- IM-2014-03-21: [[ revBrowserCEF ]] Standard init calls initialise_weak_link_*_with_path
output "int initialise_weak_link_" & pModule & "(void)"
output "{"
output "#if defined(_LINUX)"
--Modified to allow comma seperated list of possible lib names on linux
set the itemdelimiter to ","
local tModuleItem
repeat for each item tModuleItem in tUnixLibrary
output merge(" if (!initialise_weak_link_[[pModule]]_with_path([[quote & tModuleItem & quote]]))")
end repeat
output "#else"
output merge(" if (!initialise_weak_link_[[pModule]]_with_path(MODULE_[[toUpper(pModule)]]_NAME))")
output "#endif"
output "{"
output "#ifdef _DEBUG"
output " fprintf(stderr, " & quote & "Unable to load library: " & tUnixLibrary & "\n" & quote & ") ;"
output "#endif"
output "return 0;"
output "}"
output
output "return -1;"
output "}"
output
repeat for each line tSymbol in tSymbols
local tInputs, tOutputs, tArgs, tIndex
if symbolIsReference(tSymbol) then
next repeat
end if
put typelistToProto(symbolOutputs(tSymbol), false) into tOutputs
put typelistToProto(symbolInputs(tSymbol), true) into tInputs
put empty into tArgs
if tInputs is not "void" then
repeat with tIndex = 1 to the number of items of tInputs
put "pArg" & tIndex & comma & space after tArgs
end repeat
delete char -2 to -1 of tArgs
end if
output merge("[[tOutputs]][[symbolName(tSymbol)]]([[tInputs]])")
output "{"
if tOutputs is not "void " then
output merge(" return [[symbolName(tSymbol)]]_ptr([[tArgs]]);")
else
output merge(" [[symbolName(tSymbol)]]_ptr([[tArgs]]);")
end if
output "}"
output
end repeat
end generateModule
function symbolName pSymbol
set the itemDelimiter to ":"
if word 1 of item 1 of pSymbol is "?" then
return word 2 of item 1 of pSymbol
else if word 1 of item 1 of pSymbol is "@" then
return word 2 of item 1 of pSymbol
end if
return item 1 of pSymbol
end symbolName
function symbolIsOptional pSymbol
return char 1 of pSymbol is "?"
end symbolIsOptional
function symbolIsReference pSymbol
return char 1 of pSymbol is "@"
end symbolIsReference
function symbolInputs pSymbol
local tSpec, tResultList, tResult, tItem
set the itemDelimiter to ":"
put item 2 of pSymbol into tSpec
put char 2 to -2 of word 1 to -1 of (char 1 to offset("->", tSpec) - 1 of tSpec) into tResultList
set the itemDelimiter to comma
repeat for each item tItem in tResultList
put word 1 to -1 of tItem & return after tResult
end repeat
delete the last char of tResult
return tResult
end symbolInputs
function symbolOutputs pSymbol
local tSpec, tResultList, tResult, tItem
set the itemDelimiter to ":"
put item 2 of pSymbol into tSpec
put char 2 to -2 of word 1 to -1 of (char offset("->", tSpec) + 3 to -1 of tSpec) into tResultList
set the itemDelimiter to comma
repeat for each item tItem in tResultList
put word 1 to -1 of tItem & return after tResult
end repeat
delete the last char of tResult
return tResult
end symbolOutputs
function typelistToProto pList, pWithArgs
local tProto, tType, tIndex
put 1 into tIndex
repeat for each line tType in pList
switch tType
case "pointer"
put "void *" after tProto
break
case "integer"
put "int " after tProto
break
case "integer64"
put "long long int " after tProto
break
case "double"
put "double " after tProto
break
default
throw "Unknown type specified: " & tType
break
end switch
if pWithArgs then
put "pArg" & tIndex after tProto
end if
put comma & space after tProto
add 1 to tIndex
end repeat
delete char -2 to -1 of tProto
if tProto is empty then
put "void" into tProto
if not pWithArgs then
put space after tProto
end if
end if
return tProto
end typelistToProto
on output pLine
write pLine & return to stdout
end output