1
1
/*
2
2
TODO:
3
- - replace ffi shared lib version of Tcc with native version (needed for OSX)
4
3
- use EventEmitter for compile steps
5
4
- use ref.coerceType where appropriate
6
5
- enhance InlineGenerator with struct and array functionality
7
6
*/
7
+ 'use strict' ;
8
8
9
- var ffi = require ( 'ffi' ) ;
10
- var ref = require ( 'ref' ) ;
9
+ const ffi = require ( 'ffi' ) ;
10
+ const ref = require ( 'ref' ) ;
11
11
12
- var void_p = ref . refType ( ref . types . void ) ;
13
- var TCCState_p = void_p ;
14
-
15
- function Tcc ( tcclib , tccpath ) {
16
- if ( ! ( this instanceof Tcc ) )
17
- return new Tcc ( tcclib , tccpath ) ;
18
- this . lib = ffi . Library ( tcclib || './linux/lib/libtcc.so' , {
19
- // missing: tcc_enable_debug, tcc_set_error_func, tcc_set_warning, tcc_add_sysinclude_path, tcc_output_file
20
- 'tcc_new' : [ TCCState_p , [ ] ] ,
21
- 'tcc_delete' : [ 'void' , [ TCCState_p ] ] , // TODO: explicit destructor
22
- 'tcc_set_lib_path' : [ 'void' , [ TCCState_p , 'string' ] ] ,
23
- 'tcc_set_output_type' : [ 'int' , [ TCCState_p , 'int' ] ] ,
24
- 'tcc_set_options' : [ 'void' , [ TCCState_p , 'string' ] ] ,
25
- 'tcc_define_symbol' : [ 'void' , [ TCCState_p , 'string' , 'string' ] ] ,
26
- 'tcc_undefine_symbol' : [ 'void' , [ TCCState_p , 'string' ] ] ,
27
- 'tcc_add_include_path' : [ 'int' , [ TCCState_p , 'string' ] ] ,
28
- 'tcc_add_library' : [ 'int' , [ TCCState_p , 'string' ] ] ,
29
- 'tcc_add_library_path' : [ 'int' , [ TCCState_p , 'string' ] ] ,
30
- 'tcc_add_file' : [ 'int' , [ TCCState_p , 'string' ] ] , // TODO: check unicode compat
31
- 'tcc_compile_string' : [ 'int' , [ TCCState_p , 'string' ] ] ,
32
- 'tcc_relocate' : [ 'int' , [ TCCState_p , 'int' ] ] ,
33
- 'tcc_add_symbol' : [ 'int' , [ TCCState_p , 'string' , 'string' ] ] ,
34
- 'tcc_get_symbol' : [ void_p , [ TCCState_p , 'string' ] ] ,
35
- 'tcc_run' : [ 'int' , [ TCCState_p , 'int' , void_p ] ]
36
- } ) ;
37
- this . ctx = this . lib . tcc_new ( ) ;
38
- this . lib . tcc_set_lib_path ( this . ctx , tccpath || './linux/lib/tcc' ) ;
39
- this . lib . tcc_set_output_type ( this . ctx , 0 ) ; // memory build only
40
- this . _obj_refs = { } ;
41
- }
42
- Tcc . prototype . set_option = function ( option ) {
43
- this . lib . tcc_set_option ( this . ctx , option ) ;
44
- }
45
- Tcc . prototype . define = function ( symbol , value ) {
46
- this . lib . tcc_define_symbol ( this . ctx , symbol , value ) ;
47
- }
48
- Tcc . prototype . undefine = function ( symbol ) {
49
- this . lib . tcc_undefine_symbol ( this . ctx , symbol ) ;
50
- }
51
- Tcc . prototype . add_include_path = function ( path ) {
52
- if ( this . lib . tcc_add_include_path ( this . ctx , path ) == - 1 )
53
- throw new Error ( 'error add_include_path: ' + path ) ;
54
- }
55
- Tcc . prototype . add_library = function ( library ) {
56
- if ( this . lib . tcc_add_library ( this . ctx , library ) == - 1 )
57
- throw new Error ( 'error add_library: ' + library ) ;
58
- }
59
- Tcc . prototype . add_link_path = function ( path ) {
60
- if ( this . lib . tcc_add_library_path ( this . ctx , path ) == - 1 )
61
- throw new Error ( 'error add_link_path: ' + path ) ;
62
- }
63
- Tcc . prototype . add_file = function ( path ) {
64
- if ( this . lib . tcc_add_file ( this . ctx , path ) == - 1 )
65
- throw new Error ( 'error add_file: ' + path ) ;
66
- }
67
- Tcc . prototype . compile = function ( code ) {
68
- if ( this . lib . tcc_compile_string ( this . ctx , code ) == - 1 )
69
- throw new Error ( 'error compile' ) ;
70
- }
71
- Tcc . prototype . relocate = function ( ) {
72
- if ( this . lib . tcc_relocate ( this . ctx , 1 ) == - 1 )
73
- throw new Error ( 'compile relocate' ) ;
74
- }
75
- Tcc . prototype . run = function ( argc , argv ) {
76
- // TODO: handle string array
77
- return this . lib . tcc_run ( this . ctx , argc , argv ) ;
78
- }
79
- Tcc . prototype . add_symbol = function ( symbol , value ) { // TODO: hold ref for value
80
- if ( this . lib . tcc_add_symbol ( this . ctx , symbol , value ) == - 1 )
81
- throw new Error ( 'error add_symbol: ' + symbol ) ;
82
- }
83
- Tcc . prototype . get_symbol = function ( symbol ) {
84
- return this . lib . tcc_get_symbol ( this . ctx , symbol ) ;
85
- }
86
- Tcc . prototype . resolve_symbol = function ( symbol , type ) {
12
+ const Tcc = require ( './build/Release/tcc' ) . TCC ;
13
+ Tcc . prototype . resolveSymbol = function ( symbol , type ) {
87
14
// TODO: support array and struct
88
- if ( typeof type === "function" )
89
- return type ( this . get_symbol ( symbol ) ) ;
15
+ if ( typeof type === "function" ) {
16
+ return type ( this . getSymbol ( symbol ) ) ;
17
+ }
90
18
type = ref . coerceType ( type ) ;
91
- var res = this . get_symbol ( symbol ) . reinterpret ( type . size ) ;
19
+ let res = this . getSymbol ( symbol ) . reinterpret ( type . size ) ;
92
20
res . type = type ;
93
21
return res ;
94
- }
95
- Tcc . prototype . set_symbol = function ( symbol , value ) { // TODO: hold ref for value
96
- var buf = this . get_symbol ( symbol ) . reinterpret ( value . type . size ) ;
22
+ } ;
23
+ Tcc . prototype . setSymbol = function ( symbol , value ) {
24
+ let buf = this . getSymbol ( symbol ) . reinterpret ( value . type . size ) ;
97
25
buf . type = value . type ;
98
26
ref . set ( buf , 0 , value . deref ( ) ) ;
99
- }
100
- Tcc . prototype . set_function = function ( symbol , cb ) { // TODO: hold ref for value
101
- ref . set ( this . resolve_symbol ( symbol , 'void *' ) , 0 , cb ) ;
102
- }
103
-
27
+ } ;
28
+ Tcc . prototype . set_function = function ( symbol , cb ) {
29
+ ref . set ( this . resolveSymbol ( symbol , 'void *' ) , 0 , cb ) ;
30
+ } ;
104
31
105
32
/**
106
33
* C function type.
@@ -132,26 +59,24 @@ function Declaration(code, forward, symbols) {
132
59
function InlineGenerator ( ) {
133
60
if ( ! ( this instanceof InlineGenerator ) )
134
61
return new InlineGenerator ( ) ;
135
- var that = this ;
136
62
this . headerparts = [ ] ;
137
63
this . parts = [ ] ;
138
64
this . symbols = null ;
139
- this . callables = [ ] ;
140
65
}
141
66
142
67
/**
143
68
* Get C code of added declarations.
144
69
*/
145
70
InlineGenerator . prototype . code = function ( ) {
146
- var top = this . headerparts . join ( '\n' ) ;
147
- var forward = this . parts . map ( function ( el ) { return el . forward ; } ) . join ( '\n' ) ;
148
- var code = this . parts . map ( function ( el ) { return el . code ; } ) . join ( '\n' ) ;
71
+ let top = this . headerparts . join ( '\n' ) ;
72
+ let forward = this . parts . map ( function ( el ) { return el . forward ; } ) . join ( '\n' ) ;
73
+ let code = this . parts . map ( function ( el ) { return el . code ; } ) . join ( '\n' ) ;
149
74
return [
150
75
'/* top */' , top , '' ,
151
76
'/* forward */' , forward , '' ,
152
77
'/* code */' , code , ''
153
78
] . join ( '\n' ) ;
154
- }
79
+ } ;
155
80
156
81
/**
157
82
* Add a declaration to the generator.
@@ -162,14 +87,14 @@ InlineGenerator.prototype.add_declaration = function(decl) {
162
87
if ( ! ( decl instanceof Declaration ) )
163
88
throw new Error ( 'cannot add declaration' ) ;
164
89
this . parts . push ( decl ) ;
165
- }
90
+ } ;
166
91
167
92
/**
168
93
* Add a topdeclaration to the generator.
169
94
*/
170
95
InlineGenerator . prototype . add_topdeclaration = function ( decl ) {
171
96
this . headerparts . push ( decl . code ) ;
172
- }
97
+ } ;
173
98
174
99
/**
175
100
* Bind a tcc state to this generator.
@@ -179,27 +104,28 @@ InlineGenerator.prototype.add_topdeclaration = function(decl) {
179
104
InlineGenerator . prototype . bind_state = function ( state ) {
180
105
if ( this . symbols )
181
106
return this . symbols ;
182
- var all_symbols = { } ;
183
- for ( var i = 0 ; i < this . parts . length ; ++ i ) {
107
+ let all_symbols = { } ;
108
+ for ( let i = 0 ; i < this . parts . length ; ++ i ) {
184
109
if ( this . parts [ i ] . symbols . length )
185
- for ( var j = 0 ; j < this . parts [ i ] . symbols . length ; ++ j ) {
186
- var sym = this . parts [ i ] . symbols [ j ] ;
110
+ for ( let j = 0 ; j < this . parts [ i ] . symbols . length ; ++ j ) {
111
+ let sym = this . parts [ i ] . symbols [ j ] ;
187
112
if ( sym [ 0 ] instanceof FuncSymbol ) {
188
- ref . set ( state . resolve_symbol ( sym [ 1 ] , 'void *' ) , 0 , sym [ 0 ] . cb ) ;
113
+ ref . set ( state . resolveSymbol ( sym [ 1 ] , 'void *' ) , 0 , sym [ 0 ] . cb ) ;
189
114
} else {
190
- var resolved = state . resolve_symbol ( sym [ 1 ] , sym [ 0 ] ) ;
115
+ let resolved = state . resolveSymbol ( sym [ 1 ] , sym [ 0 ] ) ;
191
116
this . parts [ i ] . symbols_resolved [ sym [ 1 ] ] = resolved ;
192
117
all_symbols [ sym [ 1 ] ] = resolved ;
193
118
}
194
119
}
195
120
}
196
121
this . symbols = all_symbols ;
197
122
return all_symbols ;
198
- }
123
+ } ;
199
124
200
125
/**
201
126
* FuncSymbol - thin wrapper of ffi.Callback
202
- * needed to distingish type in `InlineGenerator.bind_state` for reverse symbol resolution of JS functions
127
+ * needed to distingish type in `InlineGenerator.bind_state` for reverse symbol resolution
128
+ * of JS functions
203
129
*/
204
130
function FuncSymbol ( restype , args , f ) {
205
131
if ( ! ( this instanceof FuncSymbol ) )
@@ -221,21 +147,21 @@ function c_callable(restype, name, args, f) {
221
147
/**
222
148
* Convenient function to create a C function in C useable from JS
223
149
*/
224
- var c_function = function ( restype , name , args , code ) {
225
- var header = restype + ' ' + name + '(' + args . map ( function ( el ) { return el . join ( ' ' ) } ) . join ( ', ' ) + ')' ;
226
- var declaration = new Declaration (
150
+ const c_function = function ( restype , name , args , code ) {
151
+ let header = restype + ' ' + name + '(' + args . map ( function ( el ) { return el . join ( ' ' ) } ) . join ( ', ' ) + ')' ;
152
+ let declaration = new Declaration (
227
153
header + '\n{' + code + '}\n' ,
228
154
header + ';' ,
229
155
[ [ CFuncType ( restype , args . map ( function ( el ) { return el [ 0 ] ; } ) ) , name ] ]
230
156
) ;
231
- var func = function ( ) {
157
+ let func = function ( ) {
232
158
if ( func . declaration . symbols_resolved [ name ] )
233
159
return func . declaration . symbols_resolved [ name ] . apply ( this , arguments ) ;
234
160
throw new Error ( 'c_function "' + name + '" must be compiled and bound before usage' ) ;
235
161
} ;
236
162
func . declaration = declaration ;
237
163
return func ;
238
- }
164
+ } ;
239
165
240
166
module . exports . Tcc = Tcc ;
241
167
module . exports . CFuncType = CFuncType ;
0 commit comments