@@ -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):
9393 return 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):
620651 pp_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):
733764 synonym [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 (
12391271 module_name = module_name ,
1240- cmd_line = ' ' .join (argv ),
1272+ cmd_line = ' ' .join (sys . argv ),
12411273 pp_cmd = pp_cmd ,
12421274 objs = ", " .join (['%s(%s)' % (objname , parent_obj_names [objname ]) for objname in obj_names ]),
12431275 lv_headers = '\n ' .join ('#include "%s"' % header for header in input_headers )))
@@ -2218,7 +2250,7 @@ def register_int_ptr_type(convertor, *types):
22182250 enums [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 ])) ))
22222254 enum_name = '%s_%s' % (enum , list (enums [enum ].keys ())[0 ])
22232255 constant_metadata [enum_name .replace ('ENUM_' , '' ).replace ('LV_' , '' )] = {'py_type' : 'int' , 'c_type' : enum_name .replace ('ENUM_' , '' )}
22242256 del enums [enum ]
@@ -2327,14 +2359,17 @@ def get_user_data(func, func_name = None, containing_struct = None, containing_s
23272359 user_data = 'user_data'
23282360 user_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):
24382473 gen_func_error (decl , "Missing 'user_data' as a field of the first parameter of the callback function '%s_%s_callback'" % (struct_name , func_name ))
24392474 else :
24402475 gen_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 ))
24472480 else :
24482481 user_data = None
24492482 # Only allow write to non-const members
@@ -2455,20 +2488,16 @@ def try_generate_struct(struct_name, struct):
24552488 if isinstance (decl .type , c_ast .ArrayDecl ):
24562489 memcpy_size = 'sizeof(%s)*%s' % (gen .visit (decl .type .type ), gen .visit (decl .type .dim ))
24572490 if 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 ))
24642495 else :
24652496 if 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 ))
24722501 print ('''
24732502/*
24742503 * Struct {struct_name}
@@ -3082,7 +3111,7 @@ def gen_mp_func(func, obj_name):
30823111 prototype_str = gen .visit (function_prototype (func ))
30833112 if prototype_str in func_prototypes :
30843113 original_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 :
30863115 print ("/* Reusing %s for %s */" % (original_func .name , func .name ))
30873116 emit_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):
31583187 func = func .name ,
31593188 func_ptr = prototype_str ,
31603189 print_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
31623195 send_args = ", " .join ([(arg .name if (hasattr (arg , 'name' ) and arg .name ) else ("arg%d" % i )) for i ,arg in enumerate (args )]),
31633196 build_result = build_result ,
31643197 build_return_value = build_return_value ))
0 commit comments