Skip to content

Commit eb4849c

Browse files
committed
Support evaluating arbitrary strings
1 parent 3379b27 commit eb4849c

File tree

8 files changed

+493
-0
lines changed

8 files changed

+493
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target
2+
Cargo.lock

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "duktape-sys/duktape"]
2+
path = duktape-sys/duktape
3+
url = https://github.com/svaarala/duktape-releases.git

Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "duk"
3+
version = "0.1.0"
4+
authors = ["David Flemström <[email protected]>"]
5+
6+
[dependencies.duktape-sys]
7+
path = "duktape-sys"

duktape-sys/Cargo.toml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
authors = ["David Flemström <[email protected]>"]
3+
build = "build.rs"
4+
name = "duktape-sys"
5+
version = "0.1.0"
6+
7+
[build-dependencies]
8+
bindgen = "0.18.0"
9+
gcc = "0.3.28"

duktape-sys/build.rs

+356
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,356 @@
1+
extern crate bindgen;
2+
extern crate gcc;
3+
4+
use std::borrow;
5+
use std::env;
6+
use std::path;
7+
use std::fs;
8+
9+
fn main() {
10+
use std::io::Write;
11+
12+
let value = &env::var("OUT_DIR").unwrap();
13+
let cur_dir = env::current_dir().unwrap();
14+
let out_dir = path::Path::new(value);
15+
16+
let duktape_header_path = cur_dir.join("duktape/src/duktape.h");
17+
let wrapper_header_path = out_dir.join("wrapper.h");
18+
let wrapper_c_file_path = out_dir.join("wrapper.c");
19+
20+
write_wrapper_header(&wrapper_header_path, &duktape_header_path);
21+
write_wrapper_c_file(&wrapper_c_file_path, &wrapper_header_path);
22+
23+
gcc::compile_library(
24+
"libduktape.a", &["duktape/src/duktape.c", wrapper_c_file_path.to_str().unwrap()]);
25+
26+
let bindings = bindgen::Builder::new()
27+
.header(wrapper_header_path.to_str().unwrap())
28+
.forbid_unknown_types()
29+
.derive_debug(true)
30+
.rust_enums(true)
31+
.builtins()
32+
.generate()
33+
.unwrap()
34+
.to_string()
35+
.replace("#![allow(dead_code,\n non_camel_case_types,\n non_upper_case_globals,\n non_snake_case)]", "");
36+
37+
fs::File::create(out_dir.join("ffi.rs"))
38+
.unwrap()
39+
.write_all(bindings.as_bytes())
40+
.unwrap();
41+
}
42+
43+
fn write_wrapper_header(path: &path::Path, duktape_header_path: &path::Path) {
44+
use std::io::Write;
45+
46+
let mut header_file = fs::File::create(path).unwrap();
47+
48+
writeln!(header_file, "#pragma once").unwrap();
49+
writeln!(header_file, "#include {:?}", duktape_header_path).unwrap();
50+
51+
for &(t, n) in MACRO_CONSTANTS {
52+
writeln!(header_file, "").unwrap();
53+
writeln!(header_file, "#pragma push_macro({:?})", n).unwrap();
54+
writeln!(header_file, "#undef {}", n).unwrap();
55+
writeln!(header_file, "const {} {};", t, n).unwrap();
56+
writeln!(header_file, "#pragma pop_macro({:?})", n).unwrap();
57+
}
58+
59+
for &(rt, n, ps) in MACRO_FUNCTIONS {
60+
writeln!(header_file, "").unwrap();
61+
writeln!(header_file, "#pragma push_macro({:?})", n).unwrap();
62+
writeln!(header_file, "#undef {}", n).unwrap();
63+
let params = join(ps.iter().map(|&(pt, pn)| format!("{} {}", pt, pn)), ", ");
64+
writeln!(header_file, "{} {}({});", rt, n, params).unwrap();
65+
writeln!(header_file, "#pragma pop_macro({:?})", n).unwrap();
66+
}
67+
}
68+
69+
fn write_wrapper_c_file(path: &path::Path, wrapper_header_path: &path::Path) {
70+
use std::io::Write;
71+
72+
let mut c_file = fs::File::create(path).unwrap();
73+
74+
writeln!(c_file, "#include {:?}", wrapper_header_path).unwrap();
75+
76+
for &(t, n) in MACRO_CONSTANTS {
77+
writeln!(c_file, "").unwrap();
78+
writeln!(c_file, "#pragma push_macro({:?})", n).unwrap();
79+
writeln!(c_file, "#undef {}", n).unwrap();
80+
writeln!(c_file, "const {} {} =", t, n).unwrap();
81+
writeln!(c_file, "#pragma pop_macro({:?})", n).unwrap();
82+
writeln!(c_file, " {};", n).unwrap();
83+
}
84+
85+
for &(rt, n, ps) in MACRO_FUNCTIONS {
86+
writeln!(c_file, "").unwrap();
87+
writeln!(c_file, "#pragma push_macro({:?})", n).unwrap();
88+
writeln!(c_file, "#undef {}", n).unwrap();
89+
let params = join(ps.iter().map(|&(pt, pn)| format!("{} {}", pt, pn)), ", ");
90+
writeln!(c_file, "{} {}({}) {{", rt, n, params).unwrap();
91+
writeln!(c_file, "#pragma pop_macro({:?})", n).unwrap();
92+
let args = join(ps.iter().map(|&(_, pn)| pn), ", ");
93+
let maybe_return = if rt == "void" { "" } else { "return " };
94+
writeln!(c_file, " {}{}({});", maybe_return, n, args).unwrap();
95+
writeln!(c_file, "}}").unwrap();
96+
}
97+
}
98+
99+
fn join<S, I>(iter: I, sep: &str) -> String where S: borrow::Borrow<str>, I: Iterator<Item=S> {
100+
iter.collect::<Vec<_>>().join(sep)
101+
}
102+
103+
const MACRO_CONSTANTS: &'static [(&'static str, &'static str)] = &[
104+
("duk_uint_t", "DUK_VERSION"),
105+
106+
("char *const", "DUK_GIT_COMMIT"),
107+
("char *const", "DUK_GIT_DESCRIBE"),
108+
("char *const", "DUK_GIT_BRANCH"),
109+
110+
("duk_uint_t", "DUK_DEBUG_PROTOCOL_VERSION"),
111+
112+
("duk_idx_t", "DUK_INVALID_INDEX"),
113+
114+
("duk_int_t", "DUK_VARARGS"),
115+
116+
("duk_size_t", "DUK_API_ENTRY_STACK"),
117+
118+
("duk_int_t", "DUK_TYPE_MIN"),
119+
("duk_int_t", "DUK_TYPE_NONE"),
120+
("duk_int_t", "DUK_TYPE_UNDEFINED"),
121+
("duk_int_t", "DUK_TYPE_NULL"),
122+
("duk_int_t", "DUK_TYPE_BOOLEAN"),
123+
("duk_int_t", "DUK_TYPE_NUMBER"),
124+
("duk_int_t", "DUK_TYPE_STRING"),
125+
("duk_int_t", "DUK_TYPE_OBJECT"),
126+
("duk_int_t", "DUK_TYPE_BUFFER"),
127+
("duk_int_t", "DUK_TYPE_POINTER"),
128+
("duk_int_t", "DUK_TYPE_LIGHTFUNC"),
129+
("duk_int_t", "DUK_TYPE_MAX"),
130+
131+
("duk_uint_t", "DUK_TYPE_MASK_NONE"),
132+
("duk_uint_t", "DUK_TYPE_MASK_UNDEFINED"),
133+
("duk_uint_t", "DUK_TYPE_MASK_NULL"),
134+
("duk_uint_t", "DUK_TYPE_MASK_BOOLEAN"),
135+
("duk_uint_t", "DUK_TYPE_MASK_NUMBER"),
136+
("duk_uint_t", "DUK_TYPE_MASK_STRING"),
137+
("duk_uint_t", "DUK_TYPE_MASK_OBJECT"),
138+
("duk_uint_t", "DUK_TYPE_MASK_BUFFER"),
139+
("duk_uint_t", "DUK_TYPE_MASK_POINTER"),
140+
("duk_uint_t", "DUK_TYPE_MASK_LIGHTFUNC"),
141+
("duk_uint_t", "DUK_TYPE_MASK_THROW"),
142+
143+
("duk_int_t", "DUK_HINT_NONE"),
144+
("duk_int_t", "DUK_HINT_STRING"),
145+
("duk_int_t", "DUK_HINT_NUMBER"),
146+
147+
("duk_uint_t", "DUK_ENUM_INCLUDE_NONENUMERABLE"),
148+
("duk_uint_t", "DUK_ENUM_INCLUDE_INTERNAL"),
149+
("duk_uint_t", "DUK_ENUM_OWN_PROPERTIES_ONLY"),
150+
("duk_uint_t", "DUK_ENUM_ARRAY_INDICES_ONLY"),
151+
("duk_uint_t", "DUK_ENUM_SORT_ARRAY_INDICES"),
152+
("duk_uint_t", "DUK_ENUM_NO_PROXY_BEHAVIOR"),
153+
154+
("duk_uint_t", "DUK_COMPILE_EVAL"),
155+
("duk_uint_t", "DUK_COMPILE_FUNCTION"),
156+
("duk_uint_t", "DUK_COMPILE_STRICT"),
157+
("duk_uint_t", "DUK_COMPILE_SAFE"),
158+
("duk_uint_t", "DUK_COMPILE_NORESULT"),
159+
("duk_uint_t", "DUK_COMPILE_NOSOURCE"),
160+
("duk_uint_t", "DUK_COMPILE_STRLEN"),
161+
("duk_uint_t", "DUK_COMPILE_NOFILENAME"),
162+
163+
("duk_uint_t", "DUK_DEFPROP_WRITABLE"),
164+
("duk_uint_t", "DUK_DEFPROP_ENUMERABLE"),
165+
("duk_uint_t", "DUK_DEFPROP_CONFIGURABLE"),
166+
("duk_uint_t", "DUK_DEFPROP_HAVE_WRITABLE"),
167+
("duk_uint_t", "DUK_DEFPROP_HAVE_ENUMERABLE"),
168+
("duk_uint_t", "DUK_DEFPROP_HAVE_CONFIGURABLE"),
169+
("duk_uint_t", "DUK_DEFPROP_HAVE_VALUE"),
170+
("duk_uint_t", "DUK_DEFPROP_HAVE_GETTER"),
171+
("duk_uint_t", "DUK_DEFPROP_HAVE_SETTER"),
172+
("duk_uint_t", "DUK_DEFPROP_FORCE"),
173+
("duk_uint_t", "DUK_DEFPROP_SET_WRITABLE"),
174+
("duk_uint_t", "DUK_DEFPROP_CLEAR_WRITABLE"),
175+
("duk_uint_t", "DUK_DEFPROP_SET_ENUMERABLE"),
176+
("duk_uint_t", "DUK_DEFPROP_CLEAR_ENUMERABLE"),
177+
("duk_uint_t", "DUK_DEFPROP_SET_CONFIGURABLE"),
178+
("duk_uint_t", "DUK_DEFPROP_CLEAR_CONFIGURABLE"),
179+
180+
("duk_uint_t", "DUK_THREAD_NEW_GLOBAL_ENV"),
181+
182+
("duk_uint_t", "DUK_STRING_PUSH_SAFE"),
183+
184+
("duk_errcode_t", "DUK_ERR_NONE"),
185+
("duk_errcode_t", "DUK_ERR_UNIMPLEMENTED_ERROR"),
186+
("duk_errcode_t", "DUK_ERR_UNSUPPORTED_ERROR"),
187+
("duk_errcode_t", "DUK_ERR_INTERNAL_ERROR"),
188+
("duk_errcode_t", "DUK_ERR_ALLOC_ERROR"),
189+
("duk_errcode_t", "DUK_ERR_ASSERTION_ERROR"),
190+
("duk_errcode_t", "DUK_ERR_API_ERROR"),
191+
("duk_errcode_t", "DUK_ERR_UNCAUGHT_ERROR"),
192+
193+
("duk_errcode_t", "DUK_ERR_ERROR"),
194+
("duk_errcode_t", "DUK_ERR_EVAL_ERROR"),
195+
("duk_errcode_t", "DUK_ERR_RANGE_ERROR"),
196+
("duk_errcode_t", "DUK_ERR_REFERENCE_ERROR"),
197+
("duk_errcode_t", "DUK_ERR_SYNTAX_ERROR"),
198+
("duk_errcode_t", "DUK_ERR_TYPE_ERROR"),
199+
("duk_errcode_t", "DUK_ERR_URI_ERROR"),
200+
201+
("duk_ret_t", "DUK_RET_UNIMPLEMENTED_ERROR"),
202+
("duk_ret_t", "DUK_RET_UNSUPPORTED_ERROR"),
203+
("duk_ret_t", "DUK_RET_INTERNAL_ERROR"),
204+
("duk_ret_t", "DUK_RET_ALLOC_ERROR"),
205+
("duk_ret_t", "DUK_RET_ASSERTION_ERROR"),
206+
("duk_ret_t", "DUK_RET_API_ERROR"),
207+
("duk_ret_t", "DUK_RET_UNCAUGHT_ERROR"),
208+
("duk_ret_t", "DUK_RET_ERROR"),
209+
("duk_ret_t", "DUK_RET_EVAL_ERROR"),
210+
("duk_ret_t", "DUK_RET_RANGE_ERROR"),
211+
("duk_ret_t", "DUK_RET_REFERENCE_ERROR"),
212+
("duk_ret_t", "DUK_RET_SYNTAX_ERROR"),
213+
("duk_ret_t", "DUK_RET_TYPE_ERROR"),
214+
("duk_ret_t", "DUK_RET_URI_ERROR"),
215+
216+
("duk_ret_t", "DUK_EXEC_SUCCESS"),
217+
("duk_ret_t", "DUK_EXEC_ERROR"),
218+
219+
("duk_int_t", "DUK_LOG_TRACE"),
220+
("duk_int_t", "DUK_LOG_DEBUG"),
221+
("duk_int_t", "DUK_LOG_INFO"),
222+
("duk_int_t", "DUK_LOG_WARN"),
223+
("duk_int_t", "DUK_LOG_ERROR"),
224+
("duk_int_t", "DUK_LOG_FATAL"),
225+
];
226+
227+
const MACRO_FUNCTIONS: &'static [(&'static str, &'static str, &'static [(&'static str, &'static str)])] = &[
228+
("duk_context *", "duk_create_heap_default", &[]),
229+
230+
("void", "duk_xmove_top",
231+
&[("duk_context *", "to_ctx"), ("duk_context *", "from_ctx"), ("duk_idx_t", "count")]),
232+
("void", "duk_xcopy_top",
233+
&[("duk_context *", "to_ctx"), ("duk_context *", "from_ctx"), ("duk_idx_t", "count")]),
234+
235+
("const char *", "duk_push_string_file",
236+
&[("duk_context *", "ctx"), ("const char *", "path")]),
237+
238+
("duk_idx_t", "duk_push_thread",
239+
&[("duk_context *", "ctx")]),
240+
("duk_idx_t", "duk_push_thread_new_globalenv",
241+
&[("duk_context *", "ctx")]),
242+
243+
("void *", "duk_push_buffer",
244+
&[("duk_context *", "ctx"), ("duk_size_t", "size"), ("duk_bool_t", "dynamic")]),
245+
("void *", "duk_push_fixed_buffer",
246+
&[("duk_context *", "ctx"), ("duk_size_t", "size")]),
247+
("void *", "duk_push_dynamic_buffer",
248+
&[("duk_context *", "ctx"), ("duk_size_t", "size")]),
249+
("void", "duk_push_external_buffer",
250+
&[("duk_context *", "ctx")]),
251+
252+
("duk_bool_t", "duk_is_callable",
253+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
254+
("duk_bool_t", "duk_is_primitive",
255+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
256+
("duk_bool_t", "duk_is_object_coercible",
257+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
258+
259+
("duk_bool_t", "duk_is_error",
260+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
261+
("duk_bool_t", "duk_is_eval_error",
262+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
263+
("duk_bool_t", "duk_is_range_error",
264+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
265+
("duk_bool_t", "duk_is_reference_error",
266+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
267+
("duk_bool_t", "duk_is_syntax_error",
268+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
269+
("duk_bool_t", "duk_is_type_error",
270+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
271+
("duk_bool_t", "duk_is_uri_error",
272+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
273+
274+
("void", "duk_require_type_mask",
275+
&[("duk_context *", "ctx"), ("duk_idx_t", "index"), ("duk_uint_t", "mask")]),
276+
277+
("void", "duk_require_callable",
278+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
279+
("void", "duk_require_object_coercible",
280+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
281+
282+
("void *", "duk_to_buffer",
283+
&[("duk_context *", "ctx"), ("duk_idx_t", "index"), ("duk_size_t *", "out_size")]),
284+
("void *", "duk_to_fixed_buffer",
285+
&[("duk_context *", "ctx"), ("duk_idx_t", "index"), ("duk_size_t *", "out_size")]),
286+
("void *", "duk_to_dynamic_buffer",
287+
&[("duk_context *", "ctx"), ("duk_idx_t", "index"), ("duk_size_t *", "out_size")]),
288+
289+
("const char *", "duk_safe_to_string",
290+
&[("duk_context *", "ctx"), ("duk_idx_t", "index")]),
291+
292+
("void", "duk_eval",
293+
&[("duk_context *", "ctx")]),
294+
("void", "duk_eval_noresult",
295+
&[("duk_context *", "ctx")]),
296+
("duk_int_t", "duk_peval",
297+
&[("duk_context *", "ctx")]),
298+
("duk_int_t", "duk_peval_noresult",
299+
&[("duk_context *", "ctx")]),
300+
("void", "duk_compile",
301+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags")]),
302+
("duk_int_t", "duk_pcompile",
303+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags")]),
304+
305+
("void", "duk_eval_string",
306+
&[("duk_context *", "ctx"), ("const char *", "src")]),
307+
("void", "duk_eval_string_noresult",
308+
&[("duk_context *", "ctx"), ("const char *", "src")]),
309+
("duk_int_t", "duk_peval_string",
310+
&[("duk_context *", "ctx"), ("const char *", "src")]),
311+
("duk_int_t", "duk_peval_string_noresult",
312+
&[("duk_context *", "ctx"), ("const char *", "src")]),
313+
("void", "duk_compile_string",
314+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "src")]),
315+
("void", "duk_compile_string_filename",
316+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "src")]),
317+
("duk_int_t", "duk_pcompile_string",
318+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "src")]),
319+
("duk_int_t", "duk_pcompile_string_filename",
320+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "src")]),
321+
322+
("void", "duk_eval_lstring",
323+
&[("duk_context *", "ctx"), ("const char *", "buf"), ("duk_size_t", "len")]),
324+
("void", "duk_eval_lstring_noresult",
325+
&[("duk_context *", "ctx"), ("const char *", "buf"), ("duk_size_t", "len")]),
326+
("duk_int_t", "duk_peval_lstring",
327+
&[("duk_context *", "ctx"), ("const char *", "buf"), ("duk_size_t", "len")]),
328+
("duk_int_t", "duk_peval_lstring_noresult",
329+
&[("duk_context *", "ctx"), ("const char *", "buf"), ("duk_size_t", "len")]),
330+
("void", "duk_compile_lstring",
331+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "buf"), ("duk_size_t", "len")]),
332+
("void", "duk_compile_lstring_filename",
333+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "buf"), ("duk_size_t", "len")]),
334+
("duk_int_t", "duk_pcompile_lstring",
335+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "buf"), ("duk_size_t", "len")]),
336+
("duk_int_t", "duk_pcompile_lstring_filename",
337+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "buf"), ("duk_size_t", "len")]),
338+
339+
("void", "duk_eval_file",
340+
&[("duk_context *", "ctx"), ("const char *", "path")]),
341+
("void", "duk_eval_file_noresult",
342+
&[("duk_context *", "ctx"), ("const char *", "path")]),
343+
("duk_int_t", "duk_peval_file",
344+
&[("duk_context *", "ctx"), ("const char *", "path")]),
345+
("duk_int_t", "duk_peval_file_noresult",
346+
&[("duk_context *", "ctx"), ("const char *", "path")]),
347+
("void", "duk_compile_file",
348+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "path")]),
349+
("duk_int_t", "duk_pcompile_file",
350+
&[("duk_context *", "ctx"), ("duk_uint_t", "flags"), ("const char *", "path")]),
351+
352+
("void", "duk_dump_context_stdout",
353+
&[("duk_context *", "ctx")]),
354+
("void", "duk_dump_context_stderr",
355+
&[("duk_context *", "ctx")]),
356+
];

duktape-sys/duktape

Submodule duktape added at 79ee589

duktape-sys/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#![allow(non_camel_case_types, non_snake_case)]
2+
3+
include!(concat!(env!("OUT_DIR"), "/ffi.rs"));

0 commit comments

Comments
 (0)