@ -21,6 +21,7 @@
import os
import sys
import re
import traceback
import json
import yaml
import math
@ -134,11 +135,23 @@ def string_is_arridx(v):
def metadata_lookup_object ( meta , obj_id ) :
return meta [ ' _objid_to_object ' ] [ obj_id ]
def metadata_lookup_object_and_index ( meta , obj_id ) :
for i , t in enumerate ( meta [ ' objects ' ] ) :
if t [ ' id ' ] == obj_id :
return t , i
return None , None
def metadata_lookup_property ( obj , key ) :
for p in obj [ ' properties ' ] :
if p [ ' key ' ] == key :
return p
raise Exception ( ' cannot find property %s from object %s ' % ( key , obj_id ) )
return None
def metadata_lookup_property_and_index ( obj , key ) :
for i , t in enumerate ( obj [ ' properties ' ] ) :
if t [ ' key ' ] == key :
return t , i
return None , None
# Remove disabled objects and properties.
def metadata_remove_disabled ( meta ) :
@ -187,18 +200,6 @@ def metadata_delete_dangling_references_to_object(meta, obj_id):
# Merge a user YAML file into current metadata.
def metadata_merge_user_objects ( meta , user_meta ) :
# XXX: could be reused from other call sites
def _findObject ( objid ) :
for i , t in enumerate ( meta [ ' objects ' ] ) :
if t [ ' id ' ] == objid :
return t , i
return None , None
def _findProp ( obj , key ) :
for i , t in enumerate ( obj [ ' properties ' ] ) :
if t [ ' key ' ] == key :
return t , i
return None , None
if user_meta . has_key ( ' add_objects ' ) :
raise Exception ( ' " add_objects " removed, use " objects " with " add: True " ' )
if user_meta . has_key ( ' replace_objects ' ) :
@ -210,7 +211,7 @@ def metadata_merge_user_objects(meta, user_meta):
if o . get ( ' disable ' , False ) :
print ( ' Skip disabled object: %s ' % o [ ' id ' ] )
continue
targ , targ_idx = _findObject ( o [ ' id ' ] )
targ , targ_idx = metadata_lookup_object_and_index ( meta , o [ ' id ' ] )
if o . get ( ' delete ' , False ) :
print ( ' Delete object: %s ' % targ [ ' id ' ] )
@ -251,7 +252,7 @@ def metadata_merge_user_objects(meta, user_meta):
continue
prop = None
prop_idx = None
prop , prop_idx = _findProp ( targ , p [ ' key ' ] )
prop , prop_idx = metadata_lookup_property_and_index ( targ , p [ ' key ' ] )
if prop is not None :
if p . get ( ' delete ' , False ) :
print ( ' Delete property %s of %s ' % ( p [ ' key ' ] , o [ ' id ' ] ) )
@ -435,6 +436,13 @@ def metadata_normalize_shorthand(meta):
val = structprop [ ' value ' ] [ ' value ' ]
return decodeStructuredValue ( val )
def clonePropShared ( prop ) :
res = { }
for k in [ ' key ' , ' attributes ' , ' autoLightfunc ' ] :
if prop . has_key ( k ) :
res [ k ] = prop [ k ]
return res
for idx , obj in enumerate ( meta [ ' objects ' ] ) :
props = [ ]
repl_props = [ ]
@ -449,7 +457,8 @@ def metadata_normalize_shorthand(meta):
if isinstance ( val [ ' value ' ] , dict ) and val [ ' value ' ] [ ' type ' ] == ' function ' :
# Function shorthand.
subfun = decodeFunctionShorthand ( val )
prop = { ' key ' : val [ ' key ' ] , ' value ' : { ' type ' : ' object ' , ' id ' : subfun [ ' id ' ] } , ' attributes ' : val [ ' attributes ' ] }
prop = clonePropShared ( val )
prop [ ' value ' ] = { ' type ' : ' object ' , ' id ' : subfun [ ' id ' ] }
repl_props . append ( prop )
elif isinstance ( val [ ' value ' ] , dict ) and val [ ' value ' ] [ ' type ' ] == ' accessor ' and \
( val [ ' value ' ] . has_key ( ' getter ' ) or val [ ' value ' ] . has_key ( ' setter ' ) ) :
@ -457,14 +466,16 @@ def metadata_normalize_shorthand(meta):
# but are differentiated by properties.
sub_getter = decodeGetterShorthand ( val [ ' key ' ] , val )
sub_setter = decodeSetterShorthand ( val [ ' key ' ] , val )
prop = { ' key ' : val [ ' key ' ] , ' value ' : { ' type ' : ' accessor ' , ' getter_id ' : sub_getter [ ' id ' ] , ' setter_id ' : sub_setter [ ' id ' ] } , ' attributes ' : val [ ' attributes ' ] }
prop = clonePropShared ( val )
prop [ ' value ' ] = { ' type ' : ' accessor ' , ' getter_id ' : sub_getter [ ' id ' ] , ' setter_id ' : sub_setter [ ' id ' ] }
assert ( ' a ' in prop [ ' attributes ' ] ) # If missing, weird things happen runtime
#print('Expand accessor shorthand: %r -> %r' % (val, prop))
repl_props . append ( prop )
elif isinstance ( val [ ' value ' ] , dict ) and val [ ' value ' ] [ ' type ' ] == ' structured ' :
# Structured shorthand.
subval = decodeStructuredShorthand ( val )
prop = { ' key ' : val [ ' key ' ] , ' value ' : subval , ' attributes ' : val [ ' attributes ' ] }
prop = clonePropShared ( val )
prop [ ' value ' ] = subval
repl_props . append ( prop )
print ( ' Decoded structured shorthand for object %s , property %s ' % ( obj [ ' id ' ] , val [ ' key ' ] ) )
elif isinstance ( val [ ' value ' ] , dict ) and val [ ' value ' ] [ ' type ' ] == ' buffer ' :
@ -620,6 +631,93 @@ def metadata_normalize_missing_strings(meta, user_meta):
s [ ' _auto_add_user ' ] = True
meta [ ' strings ' ] . append ( s )
# Convert built-in function properties into lightfuncs where applicable.
def metadata_convert_lightfuncs ( meta ) :
num_converted = 0
num_skipped = 0
for o in meta [ ' objects ' ] :
for p in o [ ' properties ' ] :
v = p [ ' value ' ]
ptype = None
if isinstance ( v , dict ) :
ptype = p [ ' value ' ] [ ' type ' ]
if ptype != ' object ' :
continue
targ , targ_idx = metadata_lookup_object_and_index ( meta , p [ ' value ' ] [ ' id ' ] )
reasons = [ ]
if not targ . get ( ' callable ' , False ) :
reasons . append ( ' not-callable ' )
#if targ.get('constructable', False):
# reasons.append('constructable')
lf_len = 0
for p2 in targ [ ' properties ' ] :
# Don't convert if function has more properties than
# we're willing to sacrifice.
#print(' - Check %r . %s' % (o.get('id', None), p2['key']))
if p2 [ ' key ' ] == ' length ' and isinstance ( p2 [ ' value ' ] , ( int , long ) ) :
lf_len = p2 [ ' value ' ]
if p2 [ ' key ' ] not in [ ' length ' , ' name ' ] :
reasons . append ( ' nonallowed-property ' )
if not p . get ( ' autoLightfunc ' , True ) :
print ( ' Automatic lightfunc conversion rejected for key %s , explicitly requested in metadata ' % p [ ' key ' ] )
reasons . append ( ' no-auto-lightfunc ' )
# lf_len comes from actual property table (after normalization)
if targ . has_key ( ' magic ' ) :
try :
# Magic values which resolve to 'bidx' indices cannot
# be resolved here yet, because the bidx map is not
# yet ready. If so, reject the lightfunc conversion
# for now. In practice this doesn't matter.
lf_magic = resolve_magic ( targ . get ( ' magic ' ) , { } ) # empty map is a "fake" bidx map
#print('resolved magic ok -> %r' % lf_magic)
except Exception , e :
#print('Failed to resolve magic for %r: %r' % (p['key'], e))
reasons . append ( ' magic-resolve-failed ' )
lf_magic = 0xffffffff # dummy, will be out of bounds
else :
lf_magic = 0
if targ . get ( ' varargs ' , True ) :
lf_nargs = None
lf_varargs = True
else :
lf_nargs = targ [ ' nargs ' ]
lf_varargs = False
if lf_len < 0 or lf_len > 15 :
#print('lf_len out of bounds: %r' % lf_len)
reasons . append ( ' len-bounds ' )
if lf_magic < - 0x80 or lf_magic > 0x7f :
#print('lf_magic out of bounds: %r' % lf_magic)
reasons . append ( ' magic-bounds ' )
if not lf_varargs and ( lf_nargs < 0 or lf_nargs > 14 ) :
#print('lf_nargs out of bounds: %r' % lf_nargs)
reasons . append ( ' nargs-bounds ' )
if len ( reasons ) > 0 :
#print('Don\'t convert to lightfunc: %r %r (%r): %r' % (o.get('id', None), p.get('key', None), p['value']['id'], reasons))
num_skipped + = 1
continue
p_id = p [ ' value ' ] [ ' id ' ]
p [ ' value ' ] = {
' type ' : ' lightfunc ' ,
' native ' : targ [ ' native ' ] ,
' length ' : lf_len ,
' magic ' : lf_magic ,
' nargs ' : lf_nargs ,
' varargs ' : lf_varargs
}
#print(' - Convert to lightfunc: %r %r (%r) -> %r' % (o.get('id', None), p.get('key', None), p_id, p['value']))
num_converted + = 1
print ( ' Converted %d built-in function properties to lightfuncs, %d skipped as non-eligible ' % ( num_converted , num_skipped ) )
# Detect objects not reachable from any object with a 'bidx'. This is usually
# a user error because such objects can't be reached at runtime so they're
# useless in RAM or ROM init data.
@ -659,16 +757,20 @@ def metadata_remove_orphan_objects(meta):
if reachable_count == len ( reachable . keys ( ) ) :
break
num_deleted = 0
deleted = True
while deleted :
deleted = False
for i , o in enumerate ( meta [ ' objects ' ] ) :
if not reachable . has_key ( o [ ' id ' ] ) :
print ( ' WARNING: object %s not reachable, dropping ' % o [ ' id ' ] )
#print('WARNING: object %s not reachable, dropping' % o['id'] )
meta [ ' objects ' ] . pop ( i )
deleted = True
num_deleted + = 1
break
print ( ' Deleted %d unreachable objects ' % num_deleted )
# Add C define names for builtin strings. These defines are added to all
# strings, even when they won't get a stridx because the define names are
# used to autodetect referenced strings.
@ -883,6 +985,11 @@ def load_metadata(opts, rom=False, build_info=None):
if rom :
metadata_normalize_rom_property_attributes ( meta )
# Convert built-in function properties automatically into
# lightfuncs if requested and function is eligible.
if rom and opts . rom_auto_lightfunc :
metadata_convert_lightfuncs ( meta )
# Create a list of objects needing a 'bidx'. This is now just
# based on the 'builtins' metadata list but could be dynamically
# scanned somehow. Ensure 'objects' and 'objects_bidx' match
@ -1121,9 +1228,7 @@ def resolve_magic(elem, objid_to_bidx):
v = int ( elem )
if not ( v > = - 0x8000 and v < = 0x7fff ) :
raise Exception ( ' invalid plain value for magic: %s ' % repr ( v ) )
# Magic is a 16-bit signed value, but convert to 16-bit signed
# for encoding
return v & 0xffff
return v
if not isinstance ( elem , dict ) :
raise Exception ( ' invalid magic: %r ' % elem )
@ -1136,9 +1241,7 @@ def resolve_magic(elem, objid_to_bidx):
v = elem [ ' value ' ]
if not ( v > = - 0x8000 and v < = 0x7fff ) :
raise Exception ( ' invalid plain value for magic: %s ' % repr ( v ) )
# Magic is a 16-bit signed value, but convert to 16-bit signed
# for encoding
return v & 0xffff
return v
elif elem [ ' type ' ] == ' math_onearg ' :
return math_onearg_magic [ elem [ ' funcname ' ] ]
elif elem [ ' type ' ] == ' math_twoarg ' :
@ -1516,7 +1619,8 @@ def gen_ramobj_initdata_for_object(meta, be, bi, string_to_stridx, natfunc_name_
else :
be . bits ( 0 , 1 ) # flag: not constructable
magic = resolve_magic ( bi . get ( ' magic ' ) , objid_to_bidx )
# Convert signed magic to 16-bit unsigned for encoding
magic = resolve_magic ( bi . get ( ' magic ' ) , objid_to_bidx ) & 0xffff
if magic != 0 :
assert ( magic > = 0 )
assert ( magic < ( 1 << MAGIC_BITS ) )
@ -1708,6 +1812,9 @@ def gen_ramobj_initdata_for_props(meta, be, bi, string_to_stridx, natfunc_name_t
assert ( setter_fn [ ' nargs ' ] == 1 )
assert ( getter_fn [ ' magic ' ] == 0 )
assert ( setter_fn [ ' magic ' ] == 0 )
elif val [ ' type ' ] == ' lightfunc ' :
print ( ' WARNING: RAM init data format doesn \' t support " lightfunc " now, value replaced with " undefined " : %r ' % valspec )
be . bits ( PROP_TYPE_UNDEFINED , PROP_TYPE_BITS )
else :
raise Exception ( ' unsupported value: %s ' % repr ( val ) )
else :
@ -1739,7 +1846,8 @@ def gen_ramobj_initdata_for_props(meta, be, bi, string_to_stridx, natfunc_name_t
# XXX: make this check conditional to minimize bit count
# (there are quite a lot of function properties)
magic = resolve_magic ( funobj . get ( ' magic ' ) , objid_to_bidx )
# Convert signed magic to 16-bit unsigned for encoding
magic = resolve_magic ( funobj . get ( ' magic ' ) , objid_to_bidx ) & 0xffff
if magic != 0 :
assert ( magic > = 0 )
assert ( magic < ( 1 << MAGIC_BITS ) )
@ -1772,6 +1880,10 @@ def get_ramobj_native_func_maps(meta):
target = metadata_lookup_object ( meta , val [ ' id ' ] )
if target . has_key ( ' native ' ) :
native_funcs_found [ target [ ' native ' ] ] = True
if val [ ' type ' ] == ' lightfunc ' :
# No lightfunc support for RAM initializer now.
pass
for idx , k in enumerate ( sorted ( native_funcs_found . keys ( ) ) ) :
native_funcs . append ( k ) # native func names
natfunc_name_to_natidx [ k ] = idx
@ -1933,6 +2045,9 @@ def rom_get_value_initializer(meta, val, bi_str_map, bi_obj_map):
elif v [ ' type ' ] == ' undefined ' :
init_type = ' duk_rom_tval_undefined '
init_lit = ' DUK__TVAL_UNDEFINED() '
elif v [ ' type ' ] == ' null ' :
init_type = ' duk_rom_tval_null '
init_lit = ' DUK__TVAL_UNDEFINED() '
elif v [ ' type ' ] == ' object ' :
init_type = ' duk_rom_tval_object '
init_lit = ' DUK__TVAL_OBJECT(& %s ) ' % bi_obj_map [ v [ ' id ' ] ]
@ -1940,7 +2055,28 @@ def rom_get_value_initializer(meta, val, bi_str_map, bi_obj_map):
getter_object = metadata_lookup_object ( meta , v [ ' getter_id ' ] )
setter_object = metadata_lookup_object ( meta , v [ ' setter_id ' ] )
init_type = ' duk_rom_tval_accessor '
init_lit = ' { (const duk_hobject *) & %s , (const duk_hobject *) & %s } ' % ( bi_obj_map [ getter_object [ ' id ' ] ] , bi_obj_map [ setter_object [ ' id ' ] ] )
init_lit = ' DUK__TVAL_ACCESSOR(& %s , & %s ) ' % ( bi_obj_map [ getter_object [ ' id ' ] ] , bi_obj_map [ setter_object [ ' id ' ] ] )
elif v [ ' type ' ] == ' lightfunc ' :
# Match DUK_LFUNC_FLAGS_PACK() in duk_tval.h.
if v . has_key ( ' length ' ) :
assert ( v [ ' length ' ] > = 0 and v [ ' length ' ] < = 15 )
lf_length = v [ ' length ' ]
else :
lf_length = 0
if v . get ( ' varargs ' , True ) :
lf_nargs = 15 # varargs marker
else :
assert ( v [ ' nargs ' ] > = 0 and v [ ' nargs ' ] < = 14 )
lf_nargs = v [ ' nargs ' ]
if v . has_key ( ' magic ' ) :
assert ( v [ ' magic ' ] > = - 0x80 and v [ ' magic ' ] < = 0x7f )
lf_magic = v [ ' magic ' ] & 0xff
else :
lf_magic = 0
lf_flags = ( lf_magic << 8 ) + ( lf_length << 4 ) + lf_nargs
init_type = ' duk_rom_tval_lightfunc '
init_lit = ' DUK__TVAL_LIGHTFUNC( %s , %d L) ' % ( v [ ' native ' ] , lf_flags )
else :
raise Exception ( ' unhandled value: %r ' % val )
else :
@ -2152,11 +2288,17 @@ def rom_emit_object_initializer_types_and_macros(genc):
genc . emitLine ( ' \t { { { { (heaphdr_flags), (refcount), NULL, NULL }, (duk_uint8_t *) DUK_LOSE_CONST(props), (duk_hobject *) DUK_LOSE_CONST(iproto), (esize), (enext), (asize), (hsize) }, (nativefunc), (duk_int16_t) (nargs), (duk_int16_t) (magic) } } ' )
genc . emitLine ( ' #endif /* DUK_USE_HEAPPTR16 */ ' )
# Initializer typedef for a dummy function pointer. ROM support assumes
# function pointers are 32 bits. Using a dummy function pointer type
# avoids function pointer to normal pointer cast which emits warnings.
genc . emitLine ( ' typedef void (*duk_rom_funcptr)(void); ' )
# Emit duk_tval structs. This gets a bit messier with packed/unpacked
# duk_tval, endianness variants, pointer sizes, etc.
genc . emitLine ( ' #if defined(DUK_USE_PACKED_TVAL) ' )
genc . emitLine ( ' typedef struct duk_rom_tval_undefined duk_rom_tval_undefined; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_null duk_rom_tval_null; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_lightfunc duk_rom_tval_lightfunc; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_boolean duk_rom_tval_boolean; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_number duk_rom_tval_number; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_object duk_rom_tval_object; ' )
@ -2169,18 +2311,21 @@ def rom_emit_object_initializer_types_and_macros(genc):
genc . emitLine ( ' struct duk_rom_tval_string { const void *ptr; duk_uint32_t hiword; }; ' )
genc . emitLine ( ' struct duk_rom_tval_undefined { const void *ptr; duk_uint32_t hiword; }; ' )
genc . emitLine ( ' struct duk_rom_tval_null { const void *ptr; duk_uint32_t hiword; }; ' )
genc . emitLine ( ' struct duk_rom_tval_lightfunc { duk_rom_funcptr ptr; duk_uint32_t hiword; }; ' )
genc . emitLine ( ' struct duk_rom_tval_boolean { duk_uint32_t dummy; duk_uint32_t hiword; }; ' )
genc . emitLine ( ' #elif defined(DUK_USE_DOUBLE_BE) ' )
genc . emitLine ( ' struct duk_rom_tval_object { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_string { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_undefined { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_null { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_lightfunc { duk_uint32_t hiword; duk_rom_funcptr ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_boolean { duk_uint32_t hiword; duk_uint32_t dummy; }; ' )
genc . emitLine ( ' #elif defined(DUK_USE_DOUBLE_ME) ' )
genc . emitLine ( ' struct duk_rom_tval_object { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_string { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_undefined { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_null { duk_uint32_t hiword; const void *ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_lightfunc { duk_uint32_t hiword; duk_rom_funcptr ptr; }; ' )
genc . emitLine ( ' struct duk_rom_tval_boolean { duk_uint32_t hiword; duk_uint32_t dummy; }; ' )
genc . emitLine ( ' #else ' )
genc . emitLine ( ' #error invalid endianness defines ' )
@ -2208,6 +2353,8 @@ def rom_emit_object_initializer_types_and_macros(genc):
genc . emitLine ( ' struct duk_rom_tval_object { duk_small_uint_t tag; duk_small_uint_t extra; const duk_heaphdr *val; }; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_string duk_rom_tval_string; ' )
genc . emitLine ( ' struct duk_rom_tval_string { duk_small_uint_t tag; duk_small_uint_t extra; const duk_heaphdr *val; }; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_lightfunc duk_rom_tval_lightfunc; ' )
genc . emitLine ( ' struct duk_rom_tval_lightfunc { duk_small_uint_t tag; duk_small_uint_t extra; duk_rom_funcptr ptr; }; ' )
genc . emitLine ( ' typedef struct duk_rom_tval_accessor duk_rom_tval_accessor; ' )
genc . emitLine ( ' struct duk_rom_tval_accessor { const duk_hobject *get; const duk_hobject *set; }; ' )
genc . emitLine ( ' #endif /* DUK_USE_PACKED_TVAL */ ' )
@ -2232,18 +2379,21 @@ def rom_emit_object_initializer_types_and_macros(genc):
genc . emitLine ( ' #if defined(DUK_USE_DOUBLE_LE) ' )
genc . emitLine ( ' #define DUK__TVAL_UNDEFINED() { (const void *) NULL, (DUK_TAG_UNDEFINED << 16) } ' )
genc . emitLine ( ' #define DUK__TVAL_NULL() { (const void *) NULL, (DUK_TAG_NULL << 16) } ' )
genc . emitLine ( ' #define DUK__TVAL_LIGHTFUNC(func,flags) { (duk_rom_funcptr) (func), (DUK_TAG_LIGHTFUNC << 16) + (flags) } ' )
genc . emitLine ( ' #define DUK__TVAL_BOOLEAN(bval) { 0, (DUK_TAG_BOOLEAN << 16) + (bval) } ' )
genc . emitLine ( ' #define DUK__TVAL_OBJECT(ptr) { (const void *) (ptr), (DUK_TAG_OBJECT << 16) } ' )
genc . emitLine ( ' #define DUK__TVAL_STRING(ptr) { (const void *) (ptr), (DUK_TAG_STRING << 16) } ' )
genc . emitLine ( ' #elif defined(DUK_USE_DOUBLE_BE) ' )
genc . emitLine ( ' #define DUK__TVAL_UNDEFINED() { (DUK_TAG_UNDEFINED << 16), (const void *) NULL } ' )
genc . emitLine ( ' #define DUK__TVAL_NULL() { (DUK_TAG_NULL << 16), (const void *) NULL } ' )
genc . emitLine ( ' #define DUK__TVAL_LIGHTFUNC(func,flags) { (DUK_TAG_LIGHTFUNC << 16) + (flags), (duk_rom_funcptr) (func) } ' )
genc . emitLine ( ' #define DUK__TVAL_BOOLEAN(bval) { (DUK_TAG_BOOLEAN << 16) + (bval), 0 } ' )
genc . emitLine ( ' #define DUK__TVAL_OBJECT(ptr) { (DUK_TAG_OBJECT << 16), (const void *) (ptr) } ' )
genc . emitLine ( ' #define DUK__TVAL_STRING(ptr) { (DUK_TAG_STRING << 16), (const void *) (ptr) } ' )
genc . emitLine ( ' #elif defined(DUK_USE_DOUBLE_ME) ' )
genc . emitLine ( ' #define DUK__TVAL_UNDEFINED() { (DUK_TAG_UNDEFINED << 16), (const void *) NULL } ' )
genc . emitLine ( ' #define DUK__TVAL_NULL() { (DUK_TAG_NULL << 16), (const void *) NULL } ' )
genc . emitLine ( ' #define DUK__TVAL_LIGHTFUNC(func,flags) { (DUK_TAG_LIGHTFUNC << 16) + (flags), (duk_rom_funcptr) (func) } ' )
genc . emitLine ( ' #define DUK__TVAL_BOOLEAN(bval) { (DUK_TAG_BOOLEAN << 16) + (bval), 0 } ' )
genc . emitLine ( ' #define DUK__TVAL_OBJECT(ptr) { (DUK_TAG_OBJECT << 16), (const void *) (ptr) } ' )
genc . emitLine ( ' #define DUK__TVAL_STRING(ptr) { (DUK_TAG_STRING << 16), (const void *) (ptr) } ' )
@ -2257,7 +2407,9 @@ def rom_emit_object_initializer_types_and_macros(genc):
genc . emitLine ( ' #define DUK__TVAL_BOOLEAN(bval) { DUK_TAG_BOOLEAN, 0, (bval), 0 } ' )
genc . emitLine ( ' #define DUK__TVAL_OBJECT(ptr) { DUK_TAG_OBJECT, 0, (const duk_heaphdr *) (ptr) } ' )
genc . emitLine ( ' #define DUK__TVAL_STRING(ptr) { DUK_TAG_STRING, 0, (const duk_heaphdr *) (ptr) } ' )
genc . emitLine ( ' #define DUK__TVAL_LIGHTFUNC(func,flags) { DUK_TAG_LIGHTFUNC, (flags), (duk_rom_funcptr) (func) } ' )
genc . emitLine ( ' #endif /* DUK_USE_PACKED_TVAL */ ' )
genc . emitLine ( ' #define DUK__TVAL_ACCESSOR(getter,setter) { (const duk_hobject *) (getter), (const duk_hobject *) (setter) } ' )
# Emit ROM objects source: the object/function headers themselves, property
# table structs for different property table sizes/types, and property table
@ -2628,20 +2780,30 @@ def rom_emit_objects_header(genc, meta):
def emit_header_native_function_declarations ( genc , meta ) :
emitted = { } # To suppress duplicates
funclist = [ ]
def _emit ( fname ) :
if not emitted . has_key ( fname ) :
emitted [ fname ] = True
funclist . append ( fname )
for o in meta [ ' objects ' ] :
if not o . has_key ( ' native ' ) :
continue
fname = o [ ' native ' ]
if emitted . has_key ( fname ) :
continue # already emitted, suppress duplicate
emitted [ fname ] = True
if o . has_key ( ' native ' ) :
_emit ( o [ ' native ' ] )
for p in o [ ' properties ' ] :
v = p [ ' value ' ]
if isinstance ( v , dict ) and v [ ' type ' ] == ' lightfunc ' :
assert ( v . has_key ( ' native ' ) )
_emit ( v [ ' native ' ] )
#print('Lightfunc function declaration: %r' % v['native'])
for fname in funclist :
# Visibility depends on whether the function is Duktape internal or user.
# Use a simple prefix for now.
if fname [ : 4 ] == ' duk_ ' :
genc . emitLine ( ' DUK_INTERNAL_DECL duk_ret_t %s (duk_context *ctx); ' % o [ ' native ' ] )
genc . emitLine ( ' DUK_INTERNAL_DECL duk_ret_t %s (duk_context *ctx); ' % fname )
else :
genc . emitLine ( ' extern duk_ret_t %s (duk_context *ctx); ' % o [ ' native ' ] )
genc . emitLine ( ' extern duk_ret_t %s (duk_context *ctx); ' % fname )
#
# Main
@ -2654,7 +2816,9 @@ def main():
parser . add_option ( ' --strings-metadata ' , dest = ' strings_metadata ' , help = ' Built-in strings metadata file, YAML format ' )
parser . add_option ( ' --objects-metadata ' , dest = ' objects_metadata ' , help = ' Built-in objects metadata file, YAML format ' )
parser . add_option ( ' --user-builtin-metadata ' , dest = ' user_builtin_metadata ' , action = ' append ' , default = [ ] , help = ' User strings and objects to add, YAML format (can be repeated for multiple overrides) ' )
parser . add_option ( ' --ram-support ' , dest = ' ram_support ' , action = ' store_true ' , default = False , help = ' Support RAM strings/objects ' )
parser . add_option ( ' --rom-support ' , dest = ' rom_support ' , action = ' store_true ' , default = False , help = ' Support ROM strings/objects (increases output size considerably) ' )
parser . add_option ( ' --rom-auto-lightfunc ' , dest = ' rom_auto_lightfunc ' , action = ' store_true ' , default = False , help = ' Convert ROM built-in function properties into lightfuncs automatically whenever possible ' )
parser . add_option ( ' --out-header ' , dest = ' out_header ' , help = ' Output header file ' )
parser . add_option ( ' --out-source ' , dest = ' out_source ' , help = ' Output source file ' )
parser . add_option ( ' --out-metadata-json ' , dest = ' out_metadata_json ' , help = ' Output metadata file ' )
@ -2684,9 +2848,10 @@ def main():
ramstr_data , ramstr_maxlen = gen_ramstr_initdata_bitpacked ( ram_meta )
ram_native_funcs , ram_natfunc_name_to_natidx = get_ramobj_native_func_maps ( ram_meta )
ramobj_data_le = gen_ramobj_initdata_bitpacked ( ram_meta , ram_native_funcs , ram_natfunc_name_to_natidx , ' little ' )
ramobj_data_be = gen_ramobj_initdata_bitpacked ( ram_meta , ram_native_funcs , ram_natfunc_name_to_natidx , ' big ' )
ramobj_data_me = gen_ramobj_initdata_bitpacked ( ram_meta , ram_native_funcs , ram_natfunc_name_to_natidx , ' mixed ' )
if opts . ram_support :
ramobj_data_le = gen_ramobj_initdata_bitpacked ( ram_meta , ram_native_funcs , ram_natfunc_name_to_natidx , ' little ' )
ramobj_data_be = gen_ramobj_initdata_bitpacked ( ram_meta , ram_native_funcs , ram_natfunc_name_to_natidx , ' big ' )
ramobj_data_me = gen_ramobj_initdata_bitpacked ( ram_meta , ram_native_funcs , ram_natfunc_name_to_natidx , ' mixed ' )
# Write source and header files.
@ -2713,16 +2878,19 @@ def main():
else :
gc_src . emitLine ( ' #error ROM support not enabled, rerun make_dist.py with --rom-support ' )
gc_src . emitLine ( ' #else /* DUK_USE_ROM_OBJECTS */ ' )
emit_ramobj_source_nativefunc_array ( gc_src , ram_native_funcs ) # endian independent
gc_src . emitLine ( ' #if defined(DUK_USE_DOUBLE_LE) ' )
emit_ramobj_source_objinit_data ( gc_src , ramobj_data_le )
gc_src . emitLine ( ' #elif defined(DUK_USE_DOUBLE_BE) ' )
emit_ramobj_source_objinit_data ( gc_src , ramobj_data_be )
gc_src . emitLine ( ' #elif defined(DUK_USE_DOUBLE_ME) ' )
emit_ramobj_source_objinit_data ( gc_src , ramobj_data_me )
gc_src . emitLine ( ' #else ' )
gc_src . emitLine ( ' #error invalid endianness defines ' )
gc_src . emitLine ( ' #endif ' )
if opts . ram_support :
emit_ramobj_source_nativefunc_array ( gc_src , ram_native_funcs ) # endian independent
gc_src . emitLine ( ' #if defined(DUK_USE_DOUBLE_LE) ' )
emit_ramobj_source_objinit_data ( gc_src , ramobj_data_le )
gc_src . emitLine ( ' #elif defined(DUK_USE_DOUBLE_BE) ' )
emit_ramobj_source_objinit_data ( gc_src , ramobj_data_be )
gc_src . emitLine ( ' #elif defined(DUK_USE_DOUBLE_ME) ' )
emit_ramobj_source_objinit_data ( gc_src , ramobj_data_me )
gc_src . emitLine ( ' #else ' )
gc_src . emitLine ( ' #error invalid endianness defines ' )
gc_src . emitLine ( ' #endif ' )
else :
gc_src . emitLine ( ' #error RAM support not enabled, rerun make_dist.py with --ram-support ' )
gc_src . emitLine ( ' #endif /* DUK_USE_ROM_OBJECTS */ ' )
gc_hdr = dukutil . GenerateC ( )
@ -2737,8 +2905,11 @@ def main():
else :
gc_hdr . emitLine ( ' #error ROM support not enabled, rerun make_dist.py with --rom-support ' )
gc_hdr . emitLine ( ' #else /* DUK_USE_ROM_STRINGS */ ' )
emit_header_stridx_defines ( gc_hdr , ram_meta )
emit_ramstr_header_strinit_defines ( gc_hdr , ram_meta , ramstr_data , ramstr_maxlen )
if opts . ram_support :
emit_header_stridx_defines ( gc_hdr , ram_meta )
emit_ramstr_header_strinit_defines ( gc_hdr , ram_meta , ramstr_data , ramstr_maxlen )
else :
gc_hdr . emitLine ( ' #error RAM support not enabled, rerun make_dist.py with --ram-support ' )
gc_hdr . emitLine ( ' #endif /* DUK_USE_ROM_STRINGS */ ' )
gc_hdr . emitLine ( ' ' )
gc_hdr . emitLine ( ' #if defined(DUK_USE_ROM_OBJECTS) ' )
@ -2755,20 +2926,23 @@ def main():
emit_header_native_function_declarations ( gc_hdr , rom_meta )
rom_emit_objects_header ( gc_hdr , rom_meta )
else :
gc_hdr . emitLine ( ' #error ROM support not enabled, rerun make_dist.py with --rom-support ' )
gc_hdr . emitLine ( ' #else ' )
emit_header_native_function_declarations ( gc_hdr , rom_meta )
emit_ramobj_header_nativefunc_array ( gc_hdr , ram_native_funcs )
emit_ramobj_header_objects ( gc_hdr , ram_meta )
gc_hdr . emitLine ( ' #if defined(DUK_USE_DOUBLE_LE) ' )
emit_ramobj_header_initdata ( gc_hdr , ramobj_data_le )
gc_hdr . emitLine ( ' #elif defined(DUK_USE_DOUBLE_BE) ' )
emit_ramobj_header_initdata ( gc_hdr , ramobj_data_be )
gc_hdr . emitLine ( ' #elif defined(DUK_USE_DOUBLE_ME) ' )
emit_ramobj_header_initdata ( gc_hdr , ramobj_data_me )
gc_hdr . emitLine ( ' #else ' )
gc_hdr . emitLine ( ' #error invalid endianness defines ' )
gc_hdr . emitLine ( ' #endif ' )
gc_hdr . emitLine ( ' #error RAM support not enabled, rerun make_dist.py with --ram-support ' )
gc_hdr . emitLine ( ' #else /* DUK_USE_ROM_OBJECTS */ ' )
if opts . ram_support :
emit_header_native_function_declarations ( gc_hdr , ram_meta )
emit_ramobj_header_nativefunc_array ( gc_hdr , ram_native_funcs )
emit_ramobj_header_objects ( gc_hdr , ram_meta )
gc_hdr . emitLine ( ' #if defined(DUK_USE_DOUBLE_LE) ' )
emit_ramobj_header_initdata ( gc_hdr , ramobj_data_le )
gc_hdr . emitLine ( ' #elif defined(DUK_USE_DOUBLE_BE) ' )
emit_ramobj_header_initdata ( gc_hdr , ramobj_data_be )
gc_hdr . emitLine ( ' #elif defined(DUK_USE_DOUBLE_ME) ' )
emit_ramobj_header_initdata ( gc_hdr , ramobj_data_me )
gc_hdr . emitLine ( ' #else ' )
gc_hdr . emitLine ( ' #error invalid endianness defines ' )
gc_hdr . emitLine ( ' #endif ' )
else :
gc_hdr . emitLine ( ' #error RAM support not enabled, rerun make_dist.py with --ram-support ' )
gc_hdr . emitLine ( ' #endif /* DUK_USE_ROM_OBJECTS */ ' )
gc_hdr . emitLine ( ' #endif /* DUK_BUILTINS_H_INCLUDED */ ' )