1# -*- coding: utf-8 -*- 2 3import sys 4import os 5 6try: 7 from pycparser import c_ast # NOQA 8except ImportError: 9 sys.stderr.write( 10 '\nThe pycparser library is missing, ' 11 'please run "pip install pycparser" to install it.\n' 12 ) 13 sys.stderr.flush() 14 sys.exit(-500) 15 16from pycparser.c_generator import CGenerator 17from collections import OrderedDict 18 19 20generator = CGenerator() 21 22 23BASIC_TYPES = [ 24 'float', 25 'double', 26 'long', 27 'ulong', 28 'unsigned long', 29 'long double', 30 'signed long double', 31 'unsigned long double', 32 'long long', 33 'signed long long', 34 'unsigned long long', 35 'int', 36 'uint', 37 'signed int', 38 'unsigned int', 39 'long int', 40 'signed long int', 41 'unsigned long int', 42 'short' 43 'ushort', 44 'signed short', 45 'unsigned short', 46 'void', 47 'char', 48 'uchar', 49 'signed char', 50 'unsigned char', 51 'bool' 52] 53 54STDLIB_TYPES = [ 55 'size_t', 56 'uint8_t', 57 'uint16_t', 58 'uint32_t', 59 'uint64_t', 60 'int8_t', 61 'int16_t', 62 'int32_t', 63 'int64_t', 64 'va_list', 65 'uintptr_t', 66 'intptr_t', 67] 68 69enums = {} 70functions = {} 71structures = {} 72unions = {} 73typedefs = {} 74macros = {} 75 76FILTER_PRIVATE = False 77 78 79def filter_node(n): 80 if hasattr(n, 'coord') and n.coord is not None: 81 if 'fake_libc_include' in n.coord.file: 82 return True 83 if FILTER_PRIVATE and '_private.h' not in n.coord.file: 84 return True 85 86 return False 87 88 89class ArrayDecl(c_ast.ArrayDecl): 90 91 def process(self): 92 self.type.process() 93 94 def __init__(self, *args, **kwargs): 95 super().__init__(*args, **kwargs) 96 self._parent = None 97 98 @property 99 def name(self): 100 return None 101 102 @property 103 def parent(self): 104 return self._parent 105 106 @parent.setter 107 def parent(self, value): 108 self._parent = value 109 self.type.parent = self 110 111 def to_dict(self): 112 if filter_node(self): 113 return None 114 115 if self.dim is None: 116 dim = None 117 else: 118 dim = generator.visit(self.dim) 119 120 if isinstance(self.type, TypeDecl): 121 res = self.type.to_dict() 122 res['json_type'] = 'array' 123 res['dim'] = dim 124 res['quals'].extend(self.dim_quals) 125 return res 126 127 res = OrderedDict([ 128 ('type', self.type.to_dict()), 129 ('json_type', 'array'), 130 ('dim', dim), 131 ('quals', self.dim_quals) 132 ]) 133 134 return res 135 136 137class Constant(c_ast.Constant): 138 139 def process(self): 140 pass 141 142 def __init__(self, *args, **kwargs): 143 super().__init__(*args, **kwargs) 144 self._parent = None 145 146 @property 147 def parent(self): 148 return self._parent 149 150 @parent.setter 151 def parent(self, value): 152 self._parent = value 153 self.type.parent = self 154 155 def to_dict(self): 156 if filter_node(self): 157 return None 158 159 return self.value 160 161 162collected_types = [] 163 164forward_decls = {} 165 166 167class Decl(c_ast.Decl): 168 169 def process(self): 170 self.type.process() 171 172 def __init__(self, *args, **kwargs): 173 super().__init__(*args, **kwargs) 174 self._parent = None 175 176 @property 177 def parent(self): 178 return self._parent 179 180 @parent.setter 181 def parent(self, value): 182 self._parent = value 183 self.type.parent = self 184 185 def to_dict(self): 186 if filter_node(self): 187 return None 188 189 if self.name and self.name == '_silence_gcc_warning': 190 return None 191 192 if not self.name: 193 try: 194 name = self.type.name 195 except AttributeError: 196 name = None 197 198 if name: 199 if name == '_silence_gcc_warning': 200 return None 201 else: 202 name = self.name 203 204 if isinstance(self.parent, (Struct, Union)): 205 if self.bitsize: 206 bitsize = self.bitsize.to_dict() 207 else: 208 bitsize = None 209 210 res = OrderedDict([ 211 ('name', name), 212 ('type', self.type.to_dict()), 213 ('json_type', 'field'), 214 ('bitsize', bitsize) 215 ]) 216 elif isinstance(self.parent, FuncDecl): 217 res = OrderedDict([ 218 ('name', name), 219 ('type', self.type.to_dict()), 220 ('json_type', 'arg'), 221 ]) 222 elif isinstance(self.type, Enum): 223 res = self.type.to_dict() 224 res['name'] = name 225 226 elif isinstance(self.type, (FuncDef, FuncDecl)): 227 res = self.type.to_dict() 228 res['name'] = name 229 230 else: 231 if isinstance(self.type, (Struct, Union)): 232 res = self.type.to_dict() 233 234 if 'quals' in res: 235 res['quals'].extend(self.quals) 236 else: 237 res['quals'] = self.quals 238 239 if res['json_type'] == 'forward_decl': 240 if res['name'] and res['name'] not in forward_decls: 241 forward_decls[res['name']] = res 242 243 return None 244 245 return res 246 247 if self.name: 248 name = self.name 249 else: 250 name = self.type.name 251 252 doc_search = get_var_docs(name) # NOQA 253 254 if doc_search is None: 255 docstring = '' 256 else: 257 docstring = doc_search.description 258 259 if ( 260 isinstance(self.type, PtrDecl) and 261 isinstance(self.type.type, FuncDecl) 262 ): 263 type_dict = self.type.type.to_dict() 264 type_dict['json_type'] = 'function_pointer' 265 266 if docstring: 267 type_dict['docstring'] = docstring 268 269 if 'quals' in type_dict: 270 type_dict['quals'].extend(self.quals) 271 else: 272 type_dict['quals'] = self.quals 273 274 return type_dict 275 276 res = OrderedDict([ 277 ('name', name), 278 ('type', self.type.to_dict()), 279 ('json_type', 'variable'), 280 ('docstring', docstring), 281 ('quals', self.quals), 282 ('storage', self.storage) 283 ]) 284 285 return res 286 287 288class EllipsisParam(c_ast.EllipsisParam): 289 290 def process(self): 291 pass 292 293 def __init__(self, *args, **kwargs): 294 super().__init__(*args, **kwargs) 295 self._parent = None 296 297 @property 298 def parent(self): 299 return self._parent 300 301 @parent.setter 302 def parent(self, value): 303 self._parent = value 304 305 def to_dict(self): 306 if filter_node(self): 307 return None 308 309 res = OrderedDict([ 310 ('name', '...'), 311 ('type', OrderedDict([ 312 ('name', 'ellipsis'), 313 ('json_type', 'special_type') 314 ])), 315 ('json_type', 'arg'), 316 ('docstring', None) 317 ]) 318 319 return res 320 321 @property 322 def name(self): 323 return '...' 324 325 326member_namespace = {} 327 328 329class Enum(c_ast.Enum): 330 331 def process(self): 332 name = self.name 333 parent = self.parent 334 335 while parent is not None and name is None: 336 try: 337 name = parent.name 338 except AttributeError: 339 pass 340 341 parent = parent.parent 342 343 if name and name not in collected_types: 344 collected_types.append(name) 345 346 for item in (self.values or []): 347 item.process() 348 349 def __init__(self, *args, **kwargs): 350 super().__init__(*args, **kwargs) 351 self._parent = None 352 353 @property 354 def parent(self): 355 return self._parent 356 357 @parent.setter 358 def parent(self, value): 359 self._parent = value 360 if self.values: 361 self.values.parent = self 362 363 def to_dict(self): 364 if filter_node(self): 365 return None 366 367 if self.name: 368 doc_search = get_enum_docs(self.name) # NOQA 369 370 if doc_search is None: 371 docstring = '' 372 else: 373 docstring = doc_search.description 374 else: 375 docstring = '' 376 377 members = [] 378 value_num = 0 379 380 for item in (self.values or []): 381 item_dict = item.to_dict() 382 try: 383 code = generator.visit(item.value) 384 385 try: 386 value = eval("bytearray([b'" + code + "'])[0]") 387 except: # NOQA 388 index = code.find('L') 389 390 while index >= 1: 391 if code[index - 1].isdigit(): 392 code = list(code) 393 code.pop(index) 394 code = ''.join(code) 395 396 index = code.find('L', index + 1) 397 398 value = eval(code, member_namespace) 399 400 member_namespace[item_dict['name']] = value 401 402 value_num = value + 1 403 404 code = f'0x{hex(value)[2:].upper()}' 405 value = code 406 except: # NOQA 407 value = f'0x{hex(value_num)[2:].upper()}' 408 member_namespace[item_dict['name']] = value_num 409 value_num += 1 410 411 item_dict['value'] = value 412 members.append(item_dict) 413 414 hex_len = len(hex(value_num)[2:]) 415 for member in members: 416 member['value'] = ( 417 f'0x{hex(int(member["value"], 16))[2:].zfill(hex_len).upper()}' 418 ) 419 420 res = OrderedDict([ 421 ('name', self.name), 422 ('type', OrderedDict([ 423 ('name', 'int'), 424 ('json_type', 'primitive_type') 425 ])), 426 ('json_type', 'enum'), 427 ('docstring', docstring), 428 ('members', members) 429 ]) 430 431 return res 432 433 434class Enumerator(c_ast.Enumerator): 435 436 def process(self): 437 pass 438 439 def __init__(self, *args, **kwargs): 440 super().__init__(*args, **kwargs) 441 self._parent = None 442 443 @property 444 def parent(self): 445 return self._parent 446 447 @parent.setter 448 def parent(self, value): 449 self._parent = value 450 451 def to_dict(self): 452 if filter_node(self): 453 return None 454 455 parent_name = self.parent.name 456 parent = self.parent 457 458 while parent is not None and parent_name is None: 459 try: 460 parent_name = parent.name 461 except AttributeError: 462 continue 463 464 parent = parent.parent 465 466 if parent_name and parent_name.startswith('_'): 467 if parent_name[1:] in collected_types: 468 type_ = OrderedDict([ 469 ('name', parent_name[1:]), 470 ('json_type', 'lvgl_type') 471 ]) 472 elif parent_name in collected_types: 473 type_ = OrderedDict([ 474 ('name', parent_name), 475 ('json_type', 'lvgl_type') 476 ]) 477 else: 478 type_ = OrderedDict([ 479 ('name', 'int'), 480 ('json_type', 'primitive_type') 481 ]) 482 483 elif parent_name and parent_name in collected_types: 484 type_ = OrderedDict([ 485 ('name', parent_name), 486 ('json_type', 'lvgl_type') 487 ]) 488 else: 489 type_ = OrderedDict([ 490 ('name', 'int'), 491 ('json_type', 'primitive_type') 492 ]) 493 494 doc_search = get_enum_item_docs(self.name) # NOQA 495 496 if doc_search is None: 497 docstring = '' 498 else: 499 docstring = doc_search.description 500 501 res = OrderedDict([ 502 ('name', self.name), 503 ('type', type_), 504 ('json_type', 'enum_member'), 505 ('docstring', docstring) 506 ]) 507 508 return res 509 510 511class EnumeratorList(c_ast.EnumeratorList): 512 513 def process(self, indent): 514 pass 515 516 def __init__(self, *args, **kwargs): 517 super().__init__(*args, **kwargs) 518 self._parent = None 519 520 @property 521 def parent(self): 522 return self._parent 523 524 @parent.setter 525 def parent(self, value): 526 self._parent = value 527 528 for item in (self.enumerators or []): 529 item.parent = value 530 531 def to_dict(self): 532 if filter_node(self): 533 return None 534 535 pass 536 537 538def is_type(obj, type_): 539 if isinstance(obj, list): 540 return type_ == 'typedef' 541 542 return obj['json_type'] == type_ 543 544 545found_types = {} 546 547get_enum_item_docs = None 548get_enum_docs = None 549get_func_docs = None 550get_var_docs = None 551get_union_docs = None 552get_struct_docs = None 553get_typedef_docs = None 554get_macro_docs = None 555get_macros = None 556 557 558_enums = {} 559_functions = {} 560_structures = {} 561_unions = {} 562_typedefs = {} 563_variables = {} 564_function_pointers = {} 565_forward_decls = {} 566 567 568class FileAST(c_ast.FileAST): 569 570 def __init__(self, *args, **kwargs): 571 super().__init__(*args, **kwargs) 572 self._parent = None 573 574 def setup_docs(self, no_docstrings, temp_directory): # NOQA 575 global get_enum_item_docs 576 global get_enum_docs 577 global get_func_docs 578 global get_var_docs 579 global get_union_docs 580 global get_struct_docs 581 global get_typedef_docs 582 global get_macro_docs 583 global get_macros 584 585 if no_docstrings: 586 587 def dummy_list(): 588 return [] 589 590 def dummy_doc(_): 591 return None 592 593 get_enum_item_docs = dummy_doc 594 get_enum_docs = dummy_doc 595 get_func_docs = dummy_doc 596 get_var_docs = dummy_doc 597 get_union_docs = dummy_doc 598 get_struct_docs = dummy_doc 599 get_typedef_docs = dummy_doc 600 get_macro_docs = dummy_doc 601 get_macros = dummy_list 602 603 else: 604 import doc_builder # NOQA 605 606 doc_builder.EMIT_WARNINGS = False 607 # doc_builder.DOXYGEN_OUTPUT = False 608 609 docs = doc_builder.XMLSearch(temp_directory) 610 611 get_enum_item_docs = docs.get_enum_item 612 get_enum_docs = docs.get_enum 613 get_func_docs = docs.get_function 614 get_var_docs = docs.get_variable 615 get_union_docs = docs.get_union 616 get_struct_docs = docs.get_structure 617 get_typedef_docs = docs.get_typedef 618 get_macro_docs = docs.get_macro 619 get_macros = docs.get_macros 620 621 @property 622 def name(self): 623 return None 624 625 @property 626 def parent(self): 627 return self._parent 628 629 @parent.setter 630 def parent(self, value): 631 self._parent = value 632 633 def to_dict(self): 634 items = [] 635 636 # This code block is to handle how pycparser handles forward 637 # declarations and combining the forward declarations with the actual 638 # types so any information that is contained in the type gets properly 639 # attached to the forward declaration 640 forward_struct_decls = {} 641 642 for item in self.ext[:]: 643 if ( 644 isinstance(item, Decl) and 645 item.name is None and 646 isinstance( 647 item.type, 648 (Struct, Union) 649 ) and 650 item.type.name is not None 651 ): 652 if item.type.decls is None: 653 forward_struct_decls[item.type.name] = [item] 654 else: 655 if item.type.name in forward_struct_decls: 656 decs = forward_struct_decls[item.type.name] 657 if len(decs) == 2: 658 decl, td = decs 659 660 if FILTER_PRIVATE: 661 if ( 662 '_private.h' not in decl.coord.file and 663 '_private.h' not in td.coord.file and 664 '_private.h' not in item.coord.file 665 ): 666 continue 667 668 if decl.type.decls and '_private.h' in decl.coord.file: 669 decl.name = decl.type.name 670 self.ext.remove(item) 671 elif item.type.decls and '_private.h' in item.coord.file: 672 item.name = item.type.name 673 self.ext.remove(decl) 674 675 self.ext.remove(td) 676 else: 677 td.type.type.decls = item.type.decls[:] 678 679 self.ext.remove(decl) 680 self.ext.remove(item) 681 elif ( 682 isinstance(item, Typedef) and 683 isinstance(item.type, TypeDecl) and 684 item.name and 685 item.type.declname and 686 item.name == item.type.declname and 687 isinstance( 688 item.type.type, 689 (Struct, Union) 690 ) and 691 item.type.type.decls is None 692 ): 693 if item.type.type.name in forward_struct_decls: 694 forward_struct_decls[item.type.type.name].append(item) 695 ############################ 696 697 for item in self.ext: 698 if filter_node(item): 699 continue 700 try: 701 item.parent = self 702 items.append(item) 703 except AttributeError: 704 pass 705 706 enums = [] # NOQA 707 functions = [] # NOQA 708 structures = [] # NOQA 709 unions = [] # NOQA 710 typedefs = [] # NOQA 711 variables = [] 712 function_pointers = [] 713 forward_decl = [] 714 715 no_enum_name_count = 1 716 717 for itm in items: 718 itm.process() 719 item = itm.to_dict() 720 721 if item is None: 722 continue 723 724 if is_type(item, 'typedef'): 725 typedefs.append(item) 726 _typedefs[itm.name] = item 727 elif is_type(item, 'function_pointer'): 728 function_pointers.append(item) 729 _function_pointers[item['name']] = item 730 elif is_type(item, 'function'): 731 functions.append(item) 732 _functions[item['name']] = item 733 elif is_type(item, 'struct'): 734 structures.append(item) 735 _structures[item['name']] = item 736 elif is_type(item, 'union'): 737 unions.append(item) 738 _unions[item['name']] = item 739 elif is_type(item, 'enum'): 740 enums.append(item) 741 742 if item['name'] is None: 743 item['name'] = f'NO_NAME_{no_enum_name_count}' 744 no_enum_name_count += 1 745 746 _enums[item['name']] = item 747 elif is_type(item, 'variable'): 748 variables.append(item) 749 _variables[item['name']] = item 750 elif is_type(item, 'forward_decl'): 751 forward_decl.append(item) 752 _forward_decls[item['name']] = item 753 else: 754 print('UNKNOWN TYPE:') 755 print(item) 756 print(item.to_dict()) 757 758 for tdef_name in _typedefs.keys(): 759 if '_' + tdef_name in _enums: 760 enum_dict = _enums['_' + tdef_name] 761 for member in enum_dict['members']: 762 member['type']['name'] = tdef_name 763 member['type']['json_type'] = 'lvgl_type' 764 else: 765 if tdef_name.endswith('_t'): 766 td_name = tdef_name[:-2].upper() 767 else: 768 td_name = tdef_name.upper() 769 770 for en_name, enum_dict in _enums.items(): 771 if not en_name.startswith('NO_NAME_'): 772 continue 773 774 member_names = [ 775 member['name'] 776 for member in enum_dict['members'] 777 if not member['name'].startswith('_') 778 ] 779 780 if not member_names: 781 continue 782 783 c_name = os.path.commonprefix(member_names) 784 c_name = "_".join(c_name.split("_")[:-1]) 785 if c_name != td_name: 786 continue 787 788 for member in enum_dict['members']: 789 member['type']['name'] = tdef_name 790 member['type']['json_type'] = 'lvgl_type' 791 break 792 793 for enm in enums: 794 if enm['name'].startswith('NO_NAME_'): 795 enm['name'] = None 796 797 res = { 798 'enums': enums, 799 'functions': functions, 800 'function_pointers': function_pointers, 801 'structures': structures, 802 'unions': unions, 803 'variables': variables, 804 'typedefs': [], 805 'forward_decls': forward_decl, 806 'macros': [] 807 } 808 809 for typedef in typedefs: 810 if isinstance(typedef, list): 811 typedef, obj_dict = typedef 812 if obj_dict['json_type'] == 'struct': 813 res['structures'].append(obj_dict) 814 elif obj_dict['json_type'] == 'union': 815 res['unions'].append(obj_dict) 816 elif obj_dict['json_type'] == 'enum': 817 res['enums'].append(obj_dict) 818 819 res['typedefs'].append(typedef) 820 821 for macro in get_macros(): # NOQA 822 macro_type = OrderedDict([ 823 ('name', macro.name), 824 ('json_type', 'macro'), 825 ('docstring', macro.description), 826 ('params', macro.params), 827 ('initializer', macro.initializer) 828 ]) 829 830 res['macros'].append(macro_type) 831 832 return res 833 834 835class FuncDecl(c_ast.FuncDecl): 836 837 @property 838 def name(self): 839 type_ = self.type 840 while isinstance(type_, PtrDecl): 841 type_ = type_.type 842 843 try: 844 name = type_.name 845 except AttributeError: 846 name = None 847 parent = self.parent 848 while parent is not None and name is None: 849 try: 850 name = parent.name 851 except AttributeError: 852 pass 853 854 parent = parent.parent 855 856 return name 857 858 def process(self): 859 name = self.name 860 if name and name not in collected_types: 861 collected_types.append(name) 862 863 for arg in (self.args or []): 864 arg.process() 865 866 self.type.process() 867 868 def __init__(self, *args, **kwargs): 869 super().__init__(*args, **kwargs) 870 self._parent = None 871 872 @property 873 def parent(self): 874 return self._parent 875 876 @parent.setter 877 def parent(self, value): 878 self._parent = value 879 880 for arg in (self.args or []): 881 arg.parent = self 882 883 self.type.parent = self 884 885 def to_dict(self): 886 if filter_node(self): 887 return None 888 889 if self.name: 890 doc_search = get_func_docs(self.name) # NOQA 891 if doc_search is None: 892 docstring = '' 893 ret_docstring = '' 894 else: 895 docstring = doc_search.description 896 ret_docstring = doc_search.res_description 897 898 if docstring is None: 899 docstring = '' 900 if ret_docstring is None: 901 ret_docstring = '' 902 903 else: 904 doc_search = None 905 docstring = '' 906 ret_docstring = '' 907 908 args = [] 909 910 for arg in (self.args or []): 911 arg = arg.to_dict() 912 if arg['name'] and doc_search is not None: 913 for doc_arg in doc_search.args: 914 if doc_arg.name == arg['name']: 915 if doc_arg.description is None: 916 arg['docstring'] = '' 917 else: 918 arg['docstring'] = doc_arg.description 919 break 920 else: 921 arg['docstring'] = '' 922 else: 923 arg['docstring'] = '' 924 925 args.append(arg) 926 927 type_dict = OrderedDict([ 928 ('type', self.type.to_dict()), 929 ('json_type', 'ret_type'), 930 ('docstring', ret_docstring) 931 ]) 932 933 res = OrderedDict([ 934 ('name', self.name), 935 ('type', type_dict), 936 ('json_type', 'function'), 937 ('docstring', docstring), 938 ('args', args) 939 ]) 940 941 return res 942 943 944class FuncDef(c_ast.FuncDef): 945 946 @property 947 def name(self): 948 return None 949 950 def process(self): 951 self.decl.process() 952 953 def __init__(self, *args, **kwargs): 954 super().__init__(*args, **kwargs) 955 self._parent = None 956 957 @property 958 def parent(self): 959 return self._parent 960 961 @parent.setter 962 def parent(self, value): 963 self._parent = value 964 self.decl.parent = value 965 966 def to_dict(self): 967 if filter_node(self): 968 return None 969 970 return self.decl.to_dict() 971 972 973class IdentifierType(c_ast.IdentifierType): 974 975 def process(self): 976 pass 977 978 def __init__(self, *args, **kwargs): 979 super().__init__(*args, **kwargs) 980 self._parent = None 981 982 @property 983 def name(self): 984 return ' '.join(self.names) 985 986 @property 987 def parent(self): 988 return self._parent 989 990 @parent.setter 991 def parent(self, value): 992 self._parent = value 993 994 def to_dict(self): 995 if filter_node(self): 996 return None 997 998 name = ' '.join(self.names) 999 1000 if name in BASIC_TYPES: 1001 json_type = 'primitive_type' 1002 elif name in STDLIB_TYPES: 1003 json_type = 'stdlib_type' 1004 elif name in collected_types: 1005 json_type = 'lvgl_type' 1006 elif name.startswith('_') and name[1:] in collected_types: 1007 name = name[1:] 1008 json_type = 'lvgl_type' 1009 elif name.startswith('_lv_') or name.startswith('lv_'): 1010 json_type = 'lvgl_type' 1011 else: 1012 json_type = 'unknown_type' 1013 1014 res = OrderedDict([ 1015 ('name', name), 1016 ('json_type', json_type), 1017 ]) 1018 1019 return res 1020 1021 1022class ParamList(c_ast.ParamList): 1023 1024 def process(self): 1025 pass 1026 1027 def __init__(self, *args, **kwargs): 1028 super().__init__(*args, **kwargs) 1029 self._parent = None 1030 1031 @property 1032 def parent(self): 1033 return self._parent 1034 1035 @parent.setter 1036 def parent(self, value): 1037 self._parent = value 1038 for param in (self.params or []): 1039 param.parent = value 1040 1041 def to_dict(self): 1042 if filter_node(self): 1043 return None 1044 1045 pass 1046 1047 1048class PtrDecl(c_ast.PtrDecl): 1049 1050 @property 1051 def name(self): 1052 return None 1053 1054 def process(self): 1055 self.type.process() 1056 1057 def __init__(self, *args, **kwargs): 1058 super().__init__(*args, **kwargs) 1059 self._parent = None 1060 1061 @property 1062 def parent(self): 1063 return self._parent 1064 1065 @parent.setter 1066 def parent(self, value): 1067 self._parent = value 1068 self.type.parent = self 1069 1070 def to_dict(self): 1071 if filter_node(self): 1072 return None 1073 1074 if isinstance(self.type, FuncDecl): 1075 type_dict = self.type.to_dict() 1076 type_dict['json_type'] = 'function_pointer' 1077 res = type_dict 1078 else: 1079 res = OrderedDict([ 1080 ('type', self.type.to_dict()), 1081 ('json_type', 'pointer') 1082 ]) 1083 1084 if 'quals' in res: 1085 res['quals'].extend(self.quals) 1086 else: 1087 res['quals'] = self.quals 1088 1089 return res 1090 1091 1092class Struct(c_ast.Struct): 1093 1094 def process(self): 1095 for decl in (self.decls or []): 1096 decl.process() 1097 1098 name = self.name 1099 parent = self.parent 1100 while parent is not None and name is None: 1101 name = parent.name 1102 parent = parent.parent 1103 1104 if name and name not in collected_types: 1105 collected_types.append(name) 1106 1107 def __init__(self, *args, **kwargs): 1108 super().__init__(*args, **kwargs) 1109 self._parent = None 1110 1111 @property 1112 def parent(self): 1113 return self._parent 1114 1115 @parent.setter 1116 def parent(self, value): 1117 self._parent = value 1118 1119 for decl in (self.decls or []): 1120 decl.parent = self 1121 1122 def to_dict(self): 1123 if filter_node(self): 1124 return None 1125 1126 if not self.decls: 1127 name = self.name 1128 if not name: 1129 self.name = self.parent.name 1130 1131 if name: 1132 struct_doc = get_struct_docs(name) # NOQA 1133 if struct_doc: 1134 docstring = struct_doc.description 1135 else: 1136 docstring = '' 1137 else: 1138 docstring = '' 1139 1140 res = OrderedDict([ 1141 ('name', name), 1142 ('type', OrderedDict([ 1143 ('name', 'struct'), 1144 ('json_type', 'primitive_type') 1145 ])), 1146 ('json_type', 'forward_decl'), 1147 ('docstring', docstring), 1148 ]) 1149 1150 else: 1151 if self.name: 1152 struct_doc = get_struct_docs(self.name) # NOQA 1153 elif self.parent.name: 1154 struct_doc = get_struct_docs(self.parent.name) # NOQA 1155 else: 1156 struct_doc = None 1157 1158 if struct_doc is not None: 1159 docstring = struct_doc.description 1160 else: 1161 docstring = '' 1162 1163 fields = [] 1164 1165 for field in self.decls: 1166 field = field.to_dict() 1167 1168 if struct_doc is not None: 1169 for field_doc in struct_doc.fields: 1170 if field_doc.name == field['name']: 1171 field_docstring = field_doc.description 1172 break 1173 else: 1174 field_docstring = '' 1175 else: 1176 field_docstring = '' 1177 1178 field['docstring'] = field_docstring 1179 field['json_type'] = 'field' 1180 fields.append(field) 1181 1182 res = OrderedDict([ 1183 ('name', self.name), 1184 ('type', OrderedDict([ 1185 ('name', 'struct'), 1186 ('json_type', 'primitive_type') 1187 ])), 1188 ('json_type', 'struct'), 1189 ('docstring', docstring), 1190 ('fields', fields) 1191 ]) 1192 1193 return res 1194 1195 1196class TypeDecl(c_ast.TypeDecl): 1197 1198 @property 1199 def name(self): 1200 return self.declname 1201 1202 def process(self): 1203 self.type.process() 1204 1205 def __init__(self, *args, **kwargs): 1206 super().__init__(*args, **kwargs) 1207 self._parent = None 1208 1209 @property 1210 def parent(self): 1211 return self._parent 1212 1213 @parent.setter 1214 def parent(self, value): 1215 parent = value 1216 1217 while parent is not None: 1218 try: 1219 if parent.declname == self.declname: 1220 break 1221 except AttributeError: 1222 pass 1223 1224 try: 1225 if parent.name == self.declname: 1226 break 1227 except AttributeError: 1228 pass 1229 1230 parent = parent.parent 1231 1232 if parent is None: 1233 self._parent = value 1234 1235 self.type.parent = self 1236 else: 1237 self.type.parent = parent 1238 1239 def to_dict(self): 1240 if filter_node(self): 1241 return None 1242 1243 if self.parent is None: 1244 res = self.type.to_dict() 1245 if self.declname is not None and not self.type.name: 1246 res['name'] = self.declname 1247 1248 elif isinstance(self.type, (Union, Struct)): 1249 res = self.type.to_dict() 1250 1251 if not self.type.name and self.declname: 1252 res['name'] = self.declname 1253 else: 1254 res = OrderedDict([ 1255 ('name', self.declname), 1256 ('type', self.type.to_dict()), 1257 ('json_type', str(type(self))), 1258 ]) 1259 1260 res['quals'] = self.quals 1261 1262 return res 1263 1264 1265class Typedef(c_ast.Typedef): 1266 1267 def process(self): 1268 if self._parent is None: 1269 self.type.parent = self 1270 1271 self.type.process() 1272 1273 if self.name and self.name not in collected_types: 1274 collected_types.append(self.name) 1275 1276 def __init__(self, *args, **kwargs): 1277 super().__init__(*args, **kwargs) 1278 self._parent = None 1279 1280 @property 1281 def parent(self): 1282 if filter_node(self): 1283 return None 1284 1285 return self._parent 1286 1287 @parent.setter 1288 def parent(self, value): 1289 self._parent = value 1290 1291 self.type.parent = self 1292 1293 @property 1294 def is_struct(self): 1295 return ( 1296 isinstance(self.type, TypeDecl) and 1297 isinstance(self.type.type, Struct) 1298 ) 1299 1300 @property 1301 def is_union(self): 1302 return ( 1303 isinstance(self.type, TypeDecl) and 1304 isinstance(self.type.type, Union) 1305 ) 1306 1307 def get_struct_union(self): 1308 res = self.type.type.to_dict() 1309 if not self.type.type.name and self.type.name: 1310 res['name'] = self.type.name 1311 elif not self.type.type.name: 1312 res['name'] = self.name 1313 1314 return res 1315 1316 def to_dict(self): 1317 doc_search = get_typedef_docs(self.name) # NOQA 1318 1319 if doc_search is None: 1320 docstring = '' 1321 else: 1322 docstring = doc_search.description 1323 1324 if ( 1325 isinstance(self.type, PtrDecl) and 1326 isinstance(self.type.type, FuncDecl) 1327 ): 1328 type_dict = self.type.type.to_dict() 1329 type_dict['json_type'] = 'function_pointer' 1330 type_dict['name'] = self.name 1331 if 'quals' in type_dict: 1332 type_dict['quals'].extend(self.quals) 1333 else: 1334 type_dict['quals'] = self.quals 1335 1336 if ( 1337 'docstring' not in type_dict or 1338 not type_dict['docstring'] 1339 ): 1340 type_dict['docstring'] = docstring 1341 1342 return type_dict 1343 1344 if isinstance(self.type, TypeDecl): 1345 type_dict = self.type.type.to_dict() 1346 1347 if type_dict['name'] is None: 1348 if self.name is not None: 1349 type_dict['name'] = self.name 1350 else: 1351 raise RuntimeError(str(type_dict)) 1352 1353 if 'quals' in type_dict: 1354 type_dict['quals'].extend(self.quals) 1355 else: 1356 type_dict['quals'] = self.quals 1357 1358 type_dict['quals'].extend(self.type.quals) 1359 1360 if 'docstring' not in type_dict: 1361 type_dict['docstring'] = '' 1362 1363 if not type_dict['docstring']: 1364 type_dict['docstring'] = docstring 1365 1366 if type_dict['name'] in _structures: 1367 _structures[type_dict['name']]['name'] = self.name 1368 1369 if 'quals' in _structures[type_dict['name']]: 1370 _structures[type_dict['name']]['quals'].extend( 1371 type_dict['quals'] 1372 ) 1373 else: 1374 _structures[type_dict['name']]['quals'] = type_dict['quals'] 1375 1376 if ( 1377 type_dict['docstring'] and 1378 not _structures[type_dict['name']]['docstring'] 1379 ): 1380 _structures[type_dict['name']]['docstring'] = ( 1381 type_dict['docstring'] 1382 ) 1383 1384 return None 1385 1386 if type_dict['name'] in _unions: 1387 _unions[type_dict['name']]['name'] = self.name 1388 1389 if 'quals' in _unions[type_dict['name']]: 1390 _unions[type_dict['name']]['quals'].extend( 1391 type_dict['quals'] 1392 ) 1393 else: 1394 _unions[type_dict['name']]['quals'] = type_dict['quals'] 1395 1396 if ( 1397 type_dict['docstring'] and 1398 not _structures[type_dict['name']]['docstring'] 1399 ): 1400 _structures[type_dict['name']]['docstring'] = ( 1401 type_dict['docstring'] 1402 ) 1403 1404 return None 1405 1406 if type_dict['name'] in _enums: 1407 if self.name is not None: 1408 type_dict = self.type.to_dict() 1409 1410 res = OrderedDict( 1411 [ 1412 ('name', self.name), 1413 ('type', type_dict), 1414 ('json_type', 'typedef'), 1415 ('docstring', docstring), 1416 ('quals', self.quals) 1417 ] 1418 ) 1419 return res 1420 1421 if 'quals' in _enums[type_dict['name']]: 1422 _enums[type_dict['name']]['quals'].extend( 1423 type_dict['quals'] 1424 ) 1425 else: 1426 _enums[type_dict['name']]['quals'] = type_dict['quals'] 1427 1428 if ( 1429 type_dict['docstring'] and 1430 not _enums[type_dict['name']]['docstring'] 1431 ): 1432 _enums[type_dict['name']]['docstring'] = ( 1433 type_dict['docstring'] 1434 ) 1435 1436 return None 1437 1438 if not type_dict['name']: 1439 type_dict['name'] = self.name 1440 return type_dict 1441 1442 if type_dict['name'] and type_dict['name'][1:] == self.name: 1443 type_dict['name'] = self.name 1444 return type_dict 1445 1446 if type_dict['name'] and type_dict['name'] == self.name: 1447 return type_dict 1448 1449 if isinstance(self.type.type, (Struct, Union)): 1450 res = OrderedDict([ 1451 ('name', self.name), 1452 ('type', OrderedDict([ 1453 ('name', self.type.type.name), 1454 ('json_type', 'lvgl_type') 1455 ])), 1456 ('json_type', 'typedef'), 1457 ('docstring', docstring), 1458 ('quals', self.quals + self.type.quals) 1459 ]) 1460 1461 return [res, self.type.type.to_dict()] 1462 1463 elif isinstance(self.type.type, Enum): 1464 if self.type.type.name: 1465 type_dict = self.type.type.to_dict() 1466 1467 if not type_dict['docstring']: 1468 type_dict['docstring'] = docstring 1469 docstring = '' 1470 1471 if not type_dict['name']: 1472 if self.type.name: 1473 type_dict['name'] = self.type.name 1474 else: 1475 type_dict['name'] = self.name 1476 1477 res = OrderedDict([ 1478 ('name', self.name), 1479 ('type', OrderedDict([ 1480 ('name', type_dict['name']), 1481 ('json_type', 'lvgl_type') 1482 ])), 1483 ('json_type', 'typedef'), 1484 ('docstring', docstring), 1485 ]) 1486 1487 return [res, type_dict] 1488 1489 type_dict = self.type.to_dict() 1490 1491 if 'quals' in type_dict: 1492 type_dict['quals'].extend(self.quals) 1493 else: 1494 type_dict['quals'] = self.quals 1495 1496 if ( 1497 docstring and 1498 'docstring' in type_dict and 1499 not type_dict['docstring'] 1500 ): 1501 type_dict['docstring'] = docstring 1502 1503 if 'name' in type_dict and type_dict['name']: 1504 if type_dict['name'] == self.name: 1505 return type_dict 1506 if type_dict['name'][1:] == self.name: 1507 type_dict['name'] = self.name 1508 return type_dict 1509 1510 quals = type_dict['quals'] 1511 del type_dict['quals'] 1512 1513 res = OrderedDict([ 1514 ('name', self.name), 1515 ('type', type_dict), 1516 ('json_type', 'typedef'), 1517 ('docstring', docstring), 1518 ('quals', quals) 1519 ]) 1520 1521 return res 1522 1523 1524class Typename(c_ast.Typename): 1525 1526 def process(self): 1527 self.type.process() 1528 1529 def __init__(self, *args, **kwargs): 1530 super().__init__(*args, **kwargs) 1531 self._parent = None 1532 1533 @property 1534 def parent(self): 1535 return self._parent 1536 1537 @parent.setter 1538 def parent(self, value): 1539 self._parent = value 1540 1541 self.type.parent = self 1542 1543 def to_dict(self): 1544 if filter_node(self): 1545 return None 1546 1547 if not self.name and isinstance(self.type, IdentifierType): 1548 res = self.type.to_dict() 1549 res['quals'] = self.quals 1550 1551 elif isinstance(self.parent, FuncDecl): 1552 if self.name and self.parent.name: 1553 func_docs = get_func_docs(self.parent.name) # NOQA 1554 1555 if func_docs is not None: 1556 for arg in func_docs.args: 1557 if arg.name and arg.name == self.name: 1558 docstring = arg.description 1559 break 1560 else: 1561 docstring = '' 1562 else: 1563 docstring = '' 1564 else: 1565 docstring = '' 1566 1567 res = OrderedDict([ 1568 ('name', self.name), 1569 ('type', self.type.to_dict()), 1570 ('json_type', 'arg'), 1571 ('docstring', docstring), 1572 ('quals', self.quals) 1573 ]) 1574 else: 1575 res = OrderedDict([ 1576 ('name', self.name), 1577 ('type', self.type.to_dict()), 1578 ('json_type', str(type(self))), 1579 ('quals', self.quals) 1580 ]) 1581 1582 return res 1583 1584 1585class Union(c_ast.Union): 1586 1587 def process(self): 1588 for field in (self.decls or []): 1589 field.process() 1590 1591 name = self.name 1592 parent = self.parent 1593 while parent is not None and name is None: 1594 try: 1595 name = parent.name 1596 except AttributeError: 1597 pass 1598 1599 parent = parent.parent 1600 1601 if name and name not in collected_types: 1602 collected_types.append(name) 1603 1604 def __init__(self, *args, **kwargs): 1605 super().__init__(*args, **kwargs) 1606 self._parent = None 1607 1608 @property 1609 def parent(self): 1610 return self._parent 1611 1612 @parent.setter 1613 def parent(self, value): 1614 self._parent = value 1615 1616 for decl in (self.decls or []): 1617 decl.parent = self 1618 1619 def to_dict(self): 1620 if filter_node(self): 1621 return None 1622 1623 if not self.decls: 1624 name = self.name 1625 if not name: 1626 self.name = self.parent.name 1627 1628 if name: 1629 union_doc = get_union_docs(name) # NOQA 1630 if union_doc: 1631 docstring = union_doc.description 1632 else: 1633 docstring = '' 1634 else: 1635 docstring = '' 1636 1637 res = OrderedDict([ 1638 ('name', name), 1639 ('type', OrderedDict([ 1640 ('name', 'union'), 1641 ('json_type', 'primitive_type') 1642 ])), 1643 ('json_type', 'forward_decl'), 1644 ('docstring', docstring), 1645 ]) 1646 else: 1647 if self.name: 1648 union_doc = get_union_docs(self.name) # NOQA 1649 elif self.parent.name: 1650 union_doc = get_union_docs(self.parent.name) # NOQA 1651 else: 1652 union_doc = None 1653 1654 if union_doc is not None: 1655 docstring = union_doc.description 1656 else: 1657 docstring = '' 1658 1659 fields = [] 1660 1661 for field in self.decls: 1662 field = field.to_dict() 1663 1664 if union_doc is not None: 1665 for field_doc in union_doc.fields: 1666 if field_doc.name == field['name']: 1667 field_docstring = field_doc.description 1668 break 1669 else: 1670 field_docstring = '' 1671 else: 1672 field_docstring = '' 1673 1674 field['docstring'] = field_docstring 1675 field['json_type'] = 'field' 1676 fields.append(field) 1677 1678 res = OrderedDict([ 1679 ('name', self.name), 1680 ('type', OrderedDict([ 1681 ('name', 'union'), 1682 ('json_type', 'primitive_type') 1683 ])), 1684 ('json_type', 'union'), 1685 ('docstring', docstring), 1686 ('fields', fields) 1687 ]) 1688 1689 return res 1690 1691 1692for cls in ( 1693 ArrayDecl, 1694 Constant, 1695 Decl, 1696 EllipsisParam, 1697 Enum, 1698 Enumerator, 1699 EnumeratorList, 1700 EnumeratorList, 1701 FileAST, 1702 FuncDecl, 1703 FuncDef, 1704 IdentifierType, 1705 ParamList, 1706 PtrDecl, 1707 Struct, 1708 TypeDecl, 1709 Typedef, 1710 Typename, 1711 Union 1712): 1713 cls_name = cls.__name__ 1714 setattr(getattr(sys.modules['pycparser.c_parser'], 'c_ast'), cls_name, cls) 1715