@@ -25,7 +25,6 @@ def eprint(*args, **kwargs):
2525# from pudb.remote import set_trace
2626# set_trace(term_size=(180, 50))
2727
28- from sys import argv
2928import sys
3029import os
3130
@@ -35,7 +34,8 @@ def eprint(*args, **kwargs):
3534from os .path import commonprefix
3635
3736script_path = dirname (abspath (__file__ ))
38- pycparser_path = os .path .join (script_path ,'..' ,'lib' ,'pycparser' )
37+ project_path = os .path .abspath (os .path .join (script_path ,'..' ))
38+ pycparser_path = os .path .join (project_path ,'lib' ,'pycparser' )
3939
4040
4141sys .path .insert (0 ,os .path .abspath (pycparser_path ))
@@ -93,8 +93,7 @@ def Node__repr__(self):
9393return result
9494
9595
96- c_ast ._repr = _repr
97- setattr (c_ast .Node ,'__repr__' ,Node__repr__ )
96+
9897
9998
10099#
@@ -110,15 +109,47 @@ def Node__repr__(self):
110109argParser .add_argument ('--board' ,dest = 'board' ,help = 'Board or OS' ,metavar = '<Board or OS>' ,action = 'store' ,default = '' )
111110argParser .add_argument ('--output' ,dest = 'output' ,help = 'Output file path' ,metavar = '<Output path>' ,action = 'store' )
112111argParser .add_argument ('--debug' ,dest = 'debug' ,help = 'enable debugging output' ,action = 'store_true' )
113- argParser .add_argument ('--header_file' ,dest = 'input ' ,action = 'append ' ,default = [] )
112+ argParser .add_argument ('--header_file' ,dest = 'header ' ,action = 'store ' ,default = None )
114113
115114args ,unknownargs = argParser .parse_known_args ()
116115
117116module_name = args .module_name
118117module_prefix = args .module_prefix if args .module_prefix else args .module_name
119- input_headers = args .input [:]
118+ input_header = args .header
120119DEBUG = args .debug
121120
121+ lvgl_path = os .path .dirname (input_header )
122+ private_header = os .path .join (lvgl_path ,'lv_private.h' )
123+
124+ lv_config_path = os .path .abspath (os .path .join (lvgl_path ,'..' ,'lv_conf.h' ))
125+ gen_json_path = os .path .join (lvgl_path ,'scripts/gen_json' )
126+
127+ sys .path .insert (0 ,gen_json_path )
128+
129+ original_nodes = {}
130+
131+ import inspect
132+
133+ for key ,value in c_ast .__dict__ .items ():
134+ if inspect .isclass (value ):
135+ original_nodes [key ]= value
136+
137+
138+ import gen_json
139+
140+
141+ json_ast = gen_json .run (None ,lv_config_path ,False ,os .path .join (project_path ,'build' ,'lvgl_header.h' ),False )
142+ lvgl_json = json_ast .to_dict ()
143+
144+
145+ for key ,value in original_nodes .items ():
146+ setattr (c_ast ,key ,value )
147+
148+
149+ c_ast ._repr = _repr
150+ setattr (c_ast .Node ,'__repr__' ,Node__repr__ )
151+
152+
122153pp_file = args .output .rsplit ('.' ,1 )[0 ]+ '.pp'
123154
124155if DEBUG :
@@ -269,7 +300,7 @@ def get_path(name: str, p: str) -> str:
269300cpp_cmd .extend ([f'-D{ define } ' for define in args .define ])
270301cpp_cmd .extend (['-DPYCPARSER' ,'-E' ,f'-I{ fake_libc_path } ' ])
271302cpp_cmd .extend ([f'-I{ include } ' for include in args .include ])
272- cpp_cmd .append (f'"{ input_headers [ 0 ] } "' )
303+ cpp_cmd .append (f'"{ input_header } "' )
273304
274305
275306if sys .platform .startswith ('win' ):
@@ -439,7 +470,7 @@ def function_prototype(func):
439470create_obj_pattern = re .compile ('^{prefix}_(.+)_create$' .format (prefix = module_prefix ))
440471lv_method_pattern = re .compile ('^{prefix}_[^_]+_(.+)' .format (prefix = module_prefix ),re .IGNORECASE )
441472lv_base_obj_pattern = re .compile ('^(struct _){{0,1}}{prefix}_{base_name}_t( [*]){{0,1}}' .format (prefix = module_prefix ,base_name = base_obj_name ))
442- lv_str_enum_pattern = re .compile ('^_{prefix}_STR_(.+)' .format (prefix = module_prefix .upper ()))
473+ lv_str_enum_pattern = re .compile ('^_? {prefix}_STR_(.+)' .format (prefix = module_prefix .upper ()))
443474lv_callback_type_pattern = re .compile ('({prefix}_){{0,1}}(.+)_cb(_t){{0,1}}' .format (prefix = module_prefix ))
444475lv_global_callback_pattern = re .compile ('.*g_cb_t' )
445476lv_func_returns_array = re .compile ('.*_array$' )
@@ -620,7 +651,7 @@ def is_struct(type):
620651pp_data = f .read ()
621652
622653cparser = pycparser .CParser ()
623- ast = cparser .parse (pp_data ,input_headers [ 0 ] )
654+ ast = cparser .parse (pp_data ,input_header )
624655
625656forward_struct_decls = {}
626657
@@ -733,18 +764,17 @@ def my_excepthook(exc_type, exc_value, tb):
733764synonym [t .declname ]= t .type .name
734765# eprint('%s === struct %s' % (t.declname, t.type.name))
735766struct_typedefs = [typedef for typedef in typedefs if is_struct (typedef .type )]
736- structs = collections .OrderedDict ((typedef .declname ,typedef .type )for typedef in struct_typedefs if typedef .declname and typedef .type .decls )# and not lv_base_obj_pattern.match(typedef.declname))
737767structs_without_typedef = collections .OrderedDict ((decl .type .name ,decl .type )for decl in ast .ext if hasattr (decl ,'type' )and is_struct (decl .type ))
738- #
739- ## for typedefs that referenced to a forward declaration struct, replace it with the real definition.
740- # for typedef in struct_typedefs:
741- # if typedef.type.decls is None: # None means it's a forward declaration
742- # struct_name = typedef.type.name
743- # # check if it's found in `structs_without_typedef`. It actually has the typedef. Replace type with it.
744- # if typedef.type.name in structs_without_typedef:
745- # typedef.type = structs_without_typedef[struct_name]
746- #
747- # structs = collections.OrderedDict((typedef.declname, typedef.type) for typedef in struct_typedefs if typedef.declname and typedef.type.decls) # and not lv_base_obj_pattern.match(typedef.declname))
768+
769+ # for typedefs that referenced to a forward declaration struct, replace it with the real definition.
770+ for typedef in struct_typedefs :
771+ if typedef .type .decls is None :# None means it's a forward declaration
772+ struct_name = typedef .type .name
773+ # check if it's found in `structs_without_typedef`. It actually has the typedef. Replace type with it.
774+ if typedef .type .name in structs_without_typedef :
775+ typedef .type = structs_without_typedef [struct_name ]
776+
777+ structs = collections .OrderedDict ((typedef .declname ,typedef .type )for typedef in struct_typedefs if typedef .declname and typedef .type .decls )# and not lv_base_obj_pattern.match(typedef.declname))
748778structs .update (structs_without_typedef )# This is for struct without typedef
749779explicit_structs = collections .OrderedDict ((typedef .type .name ,typedef .declname )for typedef in struct_typedefs if typedef .type .name )# and not lv_base_obj_pattern.match(typedef.type.name))
750780opaque_structs = collections .OrderedDict ((typedef .declname ,c_ast .Struct (name = typedef .declname ,decls = []))for typedef in typedefs if isinstance (typedef .type ,c_ast .Struct )and typedef .type .decls == None )
@@ -1202,6 +1232,8 @@ def register_int_ptr_type(convertor, *types):
12021232# Emit Header
12031233#
12041234
1235+ input_headers = [input_header ,private_header ]
1236+
12051237print ("""
12061238/*
12071239 * Auto-Generated file, DO NOT EDIT!
@@ -1237,7 +1269,7 @@ def register_int_ptr_type(convertor, *types):
12371269{lv_headers}
12381270""" .format (
12391271module_name = module_name ,
1240- cmd_line = ' ' .join (argv ),
1272+ cmd_line = ' ' .join (sys . argv ),
12411273pp_cmd = pp_cmd ,
12421274objs = ", " .join (['%s(%s)' % (objname ,parent_obj_names [objname ])for objname in obj_names ]),
12431275lv_headers = '\n ' .join ('#include "%s"' % header for header in input_headers )))
@@ -2218,7 +2250,7 @@ def register_int_ptr_type(convertor, *types):
22182250enums [enum_name ]= enum
22192251
22202252for enum in [enum for enum in enums if len (enums [enum ])== 1 and enum .startswith ('ENUM' )]:
2221- int_constants .append ('%s_%s' % (enum ,list ( enums [enum ]. keys ())[ 0 ] ))
2253+ int_constants .append ('%s_%s' % (enum ,next ( iter ( enums [enum ])) ))
22222254enum_name = '%s_%s' % (enum ,list (enums [enum ].keys ())[0 ])
22232255constant_metadata [enum_name .replace ('ENUM_' ,'' ).replace ('LV_' ,'' )]= {'py_type' :'int' ,'c_type' :enum_name .replace ('ENUM_' ,'' )}
22242256del enums [enum ]
@@ -2327,14 +2359,17 @@ def get_user_data(func, func_name = None, containing_struct = None, containing_s
23272359user_data = 'user_data'
23282360user_data_found = user_data in [decl .name for decl in flatten_struct_decls ]
23292361# print('/* --> callback: user_data=%s user_data_found=%s containing_struct=%s */' % (user_data, user_data_found, containing_struct))
2330-
2331- ud_accessors = get_user_data_accessors (containing_struct ,containing_struct_name )
2332- if user_data_found :
2333- res = (user_data , )
2334- else :
2335- res = (None , )
2336-
2337- return res + ud_accessors
2362+ if not user_data_found and lvgl_json is not None :
2363+ containing_struct_j = next ((struct for struct in lvgl_json ["structures" ]if struct ["name" ]== struct_arg_type_name ),None )
2364+ if (containing_struct_j is None
2365+ and struct_arg_type_name .startswith ("lv_" )
2366+ and None is not next ((fwd_decl for fwd_decl in lvgl_json ["forward_decls" ]if fwd_decl ["name" ]== struct_arg_type_name ),None )
2367+ ):
2368+ struct_arg_type_name_with_underscore = "_" + struct_arg_type_name
2369+ containing_struct_j = next ((struct for struct in lvgl_json ["structures" ]if struct ["name" ]== struct_arg_type_name_with_underscore ),None )
2370+ if containing_struct_j is not None :
2371+ user_data_found = any (user_data == field ["name" ]for field in containing_struct_j ["fields" ])
2372+ return (user_data if user_data_found else None ),* get_user_data_accessors (containing_struct ,containing_struct_name )
23382373
23392374#
23402375# Generate structs when needed
@@ -2438,12 +2473,10 @@ def try_generate_struct(struct_name, struct):
24382473gen_func_error (decl ,"Missing 'user_data' as a field of the first parameter of the callback function '%s_%s_callback'" % (struct_name ,func_name ))
24392474else :
24402475gen_func_error (decl ,"Missing 'user_data' member in struct '%s'" % struct_name )
2441-
2442- write_cases .append ('case MP_QSTR_{field}: data->{field} = {cast}mp_lv_callback(dest[1], {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}, NULL, NULL, NULL); break; // converting to callback {type_name}' .
2443- format (struct_name = struct_name ,field = sanitize (decl .name ),lv_callback = lv_callback ,user_data = full_user_data_ptr ,type_name = type_name ,cast = cast ))
2444- read_cases .append ('case MP_QSTR_{field}: dest[0] = mp_lv_funcptr(&mp_{funcptr}_mpobj, {cast}data->{field}, {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}); break; // converting from callback {type_name}' .
2445- format (struct_name = struct_name ,field = sanitize (decl .name ),lv_callback = lv_callback ,funcptr = lv_to_mp_funcptr [type_name ],user_data = full_user_data ,type_name = type_name ,cast = cast ))
2446- attribute_meta [sanitize (decl .name )]= {'py_type' :'Callable' ,'c_type' :type_name ,'is_writeable' :True ,'is_readable' :True }
2476+ write_cases .append ('case MP_QSTR_{field}: data->{decl_name} = {cast}mp_lv_callback(dest[1], {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}, NULL, NULL, NULL); break; // converting to callback {type_name}' .
2477+ format (struct_name = struct_name ,field = sanitize (decl .name ),decl_name = decl .name ,lv_callback = lv_callback ,user_data = full_user_data_ptr ,type_name = type_name ,cast = cast ))
2478+ read_cases .append ('case MP_QSTR_{field}: dest[0] = mp_lv_funcptr(&mp_{funcptr}_mpobj, {cast}data->{decl_name}, {lv_callback} ,MP_QSTR_{struct_name}_{field}, {user_data}); break; // converting from callback {type_name}' .
2479+ format (struct_name = struct_name ,field = sanitize (decl .name ),decl_name = decl .name ,lv_callback = lv_callback ,funcptr = lv_to_mp_funcptr [type_name ],user_data = full_user_data ,type_name = type_name ,cast = cast ))
24472480else :
24482481user_data = None
24492482# Only allow write to non-const members
@@ -2455,20 +2488,16 @@ def try_generate_struct(struct_name, struct):
24552488if isinstance (decl .type ,c_ast .ArrayDecl ):
24562489memcpy_size = 'sizeof(%s)*%s' % (gen .visit (decl .type .type ),gen .visit (decl .type .dim ))
24572490if is_writeable :
2458- write_cases .append ('case MP_QSTR_{field}: memcpy((void*)&data->{field}, {cast}{convertor}(dest[1]), {size}); break; // converting to {type_name}' .
2459- format (field = sanitize (decl .name ),convertor = mp_to_lv_convertor ,type_name = type_name ,cast = cast ,size = memcpy_size ))
2460-
2461-
2462- read_cases .append ('case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{field}); break; // converting from {type_name}' .
2463- format (field = sanitize (decl .name ),convertor = lv_to_mp_convertor ,type_name = type_name ,cast = cast ))
2491+ write_cases .append ('case MP_QSTR_{field}: memcpy((void*)&data->{decl_name}, {cast}{convertor}(dest[1]), {size}); break; // converting to {type_name}' .
2492+ format (field = sanitize (decl .name ),decl_name = decl .name ,convertor = mp_to_lv_convertor ,type_name = type_name ,cast = cast ,size = memcpy_size ))
2493+ read_cases .append ('case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{decl_name}); break; // converting from {type_name}' .
2494+ format (field = sanitize (decl .name ),decl_name = decl .name ,convertor = lv_to_mp_convertor ,type_name = type_name ,cast = cast ))
24642495else :
24652496if is_writeable :
2466- write_cases .append ('case MP_QSTR_{field}: data->{field} = {cast}{convertor}(dest[1]); break; // converting to {type_name}' .
2467- format (field = sanitize (decl .name ),convertor = mp_to_lv_convertor ,type_name = type_name ,cast = cast ))
2468-
2469- read_cases .append (
2470- 'case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{field}); break; // converting from {type_name}' .
2471- format (field = sanitize (decl .name ),convertor = lv_to_mp_convertor ,type_name = type_name ,cast = cast ))
2497+ write_cases .append ('case MP_QSTR_{field}: data->{decl_name} = {cast}{convertor}(dest[1]); break; // converting to {type_name}' .
2498+ format (field = sanitize (decl .name ),decl_name = decl .name ,convertor = mp_to_lv_convertor ,type_name = type_name ,cast = cast ))
2499+ read_cases .append ('case MP_QSTR_{field}: dest[0] = {convertor}({cast}data->{decl_name}); break; // converting from {type_name}' .
2500+ format (field = sanitize (decl .name ),decl_name = decl .name ,convertor = lv_to_mp_convertor ,type_name = type_name ,cast = cast ))
24722501print ('''
24732502/*
24742503 * Struct {struct_name}
@@ -3082,7 +3111,7 @@ def gen_mp_func(func, obj_name):
30823111prototype_str = gen .visit (function_prototype (func ))
30833112if prototype_str in func_prototypes :
30843113original_func = func_prototypes [prototype_str ]
3085- if not original_func . name . endswith ( 'cb_t' ) and generated_funcs [original_func .name ]== True :
3114+ if generated_funcs [original_func .name ]== True :
30863115print ("/* Reusing %s for %s */" % (original_func .name ,func .name ))
30873116emit_func_obj (func .name ,original_func .name ,param_count ,func .name ,is_static_member (func ,base_obj_type ))
30883117
@@ -3158,7 +3187,11 @@ def gen_mp_func(func, obj_name):
31583187func = func .name ,
31593188func_ptr = prototype_str ,
31603189print_func = gen .visit (func ),
3161- build_args = "\n " .join (build_args ),
3190+ build_args = "\n " .join ([build_mp_func_arg (arg ,i ,func ,obj_name )for i ,arg in enumerated_args
3191+ if isinstance (arg ,c_ast .EllipsisParam )or
3192+ (not isinstance (arg .type ,c_ast .TypeDecl ))or
3193+ (not isinstance (arg .type .type ,c_ast .IdentifierType ))or
3194+ 'void' not in arg .type .type .names ]),# Handle the case of 'void' param which should be ignored
31623195send_args = ", " .join ([(arg .name if (hasattr (arg ,'name' )and arg .name )else ("arg%d" % i ))for i ,arg in enumerate (args )]),
31633196build_result = build_result ,
31643197build_return_value = build_return_value ))