@@ -88,7 +88,8 @@ def print_references(self, file: File):
8888 if self .displayname in file .has_declared or self .displayname in file .has_printed : return
8989 else : file .has_declared .add (self .displayname )
9090
91- print (f"export type { self .displayname } " , file = file .fp )
91+ if self .displayname and "()" not in self .displayname :
92+ print (f"export type { self .displayname } " , file = file .fp )
9293
9394class IncompleteTypedef (Type ):
9495 def __init__ (self , name : str ):
@@ -192,14 +193,15 @@ def print_references(self, file: File):
192193 self = file .TAGGED [self .name ]
193194
194195 for f in self .fields :
195- f .type .print_references (file )
196+ if f .type :
197+ f .type .print_references (file )
196198
197199 if not self .fields : return
198200 if not self .displayname in file .has_printed :
199201 file .has_printed .add (self .displayname )
200202 else : return
201203
202- if self .name :
204+ if self .displayname :
203205 print (f"export type { self .displayname } " , file = file .fp , end = "" )
204206 if self .fields :
205207 print (f" = { self .to_definition (file )} " , file = file .fp )
@@ -215,7 +217,7 @@ def to_definition(self, file: File) -> str:
215217 if self .fields :
216218 res = "struct { "
217219 for field in self .fields :
218- res += field .to_definition (file ) + "; "
220+ if field . type : res += field .to_definition (file ) + "; "
219221 res += "}"
220222 return res
221223
@@ -229,7 +231,7 @@ def to_definition(self, file: File) -> str:
229231 if self .fields :
230232 res = "struct #union { "
231233 for field in self .fields :
232- res += field .to_definition (file ) + "; "
234+ if field . type : res += field .to_definition (file ) + "; "
233235 res += "}"
234236 return res
235237
@@ -265,7 +267,7 @@ def print_references(self, file: File):
265267 file .has_printed .add (self .displayname )
266268 else : return
267269
268- if self .name and not is_anonymous (self .name ):
270+ if self .displayname and not is_anonymous (self .name ):
269271 print (f"export type { self .displayname } " , file = file .fp , end = "" )
270272 if self .fields :
271273 print (f" = { self .to_definition (file )} " , file = file .fp )
@@ -418,10 +420,22 @@ def parse_struct(name: str, inner: clang.Type, file: File, lookup: bool = False)
418420
419421 fields = []
420422 field : clang .Cursor
423+ index = 0
421424 for field in children :
422425 if field .kind == clang .CursorKind .STRUCT_DECL :
423426 if len (list (field .get_children ())) == 0 : continue
424- fields .append (Field (parse_type (field .type , file , is_in_struct = True ), field .spelling , field .is_bitfield (), field .get_bitfield_width ()))
427+ field_type = parse_type (field .type , file , is_in_struct = True )
428+ if not field_type : return None
429+
430+ exists = True
431+ spelling = field .spelling
432+ if not spelling :
433+ spelling = "_" + str (index )
434+ if type (field_type ) == IncompleteType :
435+ field_type = None
436+
437+ fields .append (Field (field_type , spelling , field .is_bitfield (), field .get_bitfield_width ()))
438+ index += 1
425439
426440 res = None
427441 if declaration .kind == clang .CursorKind .STRUCT_DECL :
@@ -486,9 +500,24 @@ def parse_type(type: clang.Type, file: File, lookup: bool = False, is_in_struct:
486500 elif type .kind == clang .TypeKind .INCOMPLETEARRAY :
487501 return Pointer (parse_type (type .get_array_element_type (), file , lookup , is_in_struct ))
488502 elif type .kind == clang .TypeKind .TYPEDEF :
489- return file .TYPEDEFS [type .spelling ]
503+ spelling = type .spelling
504+ # TODO This doesn't work properly
505+ if spelling .startswith ("const" ):
506+ spelling = spelling .replace ("const" , "" , 1 )
507+ spelling = spelling .strip ()
508+ if spelling .startswith ("__unaligned" ):
509+ spelling = spelling .replace ("__unaligned" , "" , 1 )
510+ spelling = spelling .strip ()
511+ if spelling .startswith ("volatile" ):
512+ spelling = spelling .replace ("volatile" , "" , 1 )
513+ spelling = spelling .strip ()
514+
515+ spelling = spelling .strip ()
516+ return file .TYPEDEFS [spelling ]
517+
518+ return IncompleteType (type .spelling )
490519
491- assert False , f"Invalid type! { type . kind } "
520+ ALL_DEFINITIONS = {}
492521
493522def process_module (name : str , * libs ):
494523 included = []
@@ -516,39 +545,45 @@ def process_module(name: str, *libs):
516545 def extract (node : clang .Cursor ):
517546 if node .kind == clang .CursorKind .FUNCTION_DECL :
518547 if node .is_static_method (): return
519-
520- for token in node .get_tokens ():
521- if token .spelling == "__inline" or token .spelling == "inline" :
522- return
523548
524- dllimport = False #TODO
549+ dllimport = False
550+ for child in node .get_children ():
551+ if child .kind == clang .CursorKind .DLLIMPORT_ATTR :
552+ dllimport = True
553+
525554 name = node .spelling
526555 args = []
527556
528557 for child in node .get_arguments ():
529558 if child .kind == clang .CursorKind .PARM_DECL :
530559 tokens = list (child .get_tokens ())
531- if len (tokens ) == 2 and tokens [0 ].spelling == "size_t" : #FIXME This is a hack, see https://github.com/sighingnow/libclang/issues/53
532- args .append ((child .spelling , PRIMITIVES [clang .TypeKind .ULONG ]))
560+ spelling = escape_name (child .spelling )
561+ if sys .platform == "linux" and len (tokens ) == 2 and tokens [0 ].spelling == "size_t" : #FIXME This is a hack, see https://github.com/sighingnow/libclang/issues/53
562+ args .append ((spelling , PRIMITIVES [clang .TypeKind .ULONG ]))
533563 else :
534- args .append ((child . spelling , parse_type (child .type , file )))
564+ args .append ((spelling , parse_type (child .type , file )))
535565
536566 is_size_t = False #FIXME Same hack
537567 for token in node .get_tokens ():
538568 if token .kind == clang .TokenKind .KEYWORD and token .spelling == "extern" : continue
539569 if token .spelling == "size_t" : is_size_t = True
540570 if token .spelling == "(" : break
541571
542- if is_size_t :
572+ if is_size_t and sys . platform == "linux" :
543573 ret = PRIMITIVES [clang .TypeKind .ULONG ]
544574 else :
545575 ret = parse_type (node .result_type , file )
546576
547577 file .GLOBALS [name ] = FunctionDecl (name , ret , args , node .type .is_function_variadic (), dllimport )
548578 elif node .kind == clang .CursorKind .VAR_DECL :
549579 if node .storage_class == clang .StorageClass .EXTERN :
580+ dllimport = False
581+ for child in node .get_children ():
582+ if child .kind == clang .CursorKind .DLLIMPORT_ATTR :
583+ dllimport = True
584+
550585 type = parse_type (node .type , file )
551- file .GLOBALS [node .spelling ] = VarDecl (node .spelling , type , False )
586+ file .GLOBALS [node .spelling ] = VarDecl (node .spelling , type , dllimport )
552587 elif node .kind == clang .CursorKind .TYPEDEF_DECL :
553588 name = node .spelling
554589 underlying = node .underlying_typedef_type
@@ -580,18 +615,19 @@ def extract(node: clang.Cursor):
580615 elif node .kind == clang .CursorKind .MACRO_DEFINITION :
581616 tokens = list (node .get_tokens ())
582617 if len (tokens ) == 2 and tokens [1 ].kind == clang .TokenKind .LITERAL :
583- token = tokens [1 ]
584- if token .spelling .startswith ('"' ) and token .spelling .endswith ('"' ):
585- s = token .spelling
586- s = re .sub (r"(?<!\\)\\(\d{1,3})" , lambda o : f"\\ x{ + int (o .group (1 ), base = 8 ):02x} " , s )
587- file .GLOBALS [node .spelling ] = ConstDecl (node .spelling , string , s )
588- elif token .spelling .isdigit ():
589- file .GLOBALS [node .spelling ] = ConstDecl (node .spelling , PRIMITIVES [clang .TypeKind .INT ], token .spelling )
590- else :
591- try :
592- float (token .spelling )
593- file .GLOBALS [node .spelling ] = ConstDecl (node .spelling , PRIMITIVES [clang .TypeKind .DOUBLE ], token .spelling )
594- except ValueError : pass
618+ if node .spelling != "true" and node .spelling != "false" :
619+ token = tokens [1 ]
620+ if token .spelling .startswith ('"' ) and token .spelling .endswith ('"' ):
621+ s = token .spelling
622+ s = re .sub (r"(?<!\\)\\(\d{1,3})" , lambda o : f"\\ x{ + int (o .group (1 ), base = 8 ):02x} " , s )
623+ file .GLOBALS [node .spelling ] = ConstDecl (node .spelling , string , s )
624+ elif token .spelling .isdigit ():
625+ file .GLOBALS [node .spelling ] = ConstDecl (node .spelling , PRIMITIVES [clang .TypeKind .INT ], token .spelling )
626+ else :
627+ try :
628+ float (token .spelling )
629+ file .GLOBALS [node .spelling ] = ConstDecl (node .spelling , PRIMITIVES [clang .TypeKind .DOUBLE ], token .spelling )
630+ except ValueError : pass
595631
596632 index = clang .Index .create ()
597633 tu = index .parse (folder / f"{ name } .h" , options =
@@ -603,7 +639,8 @@ def extract(node: clang.Cursor):
603639 extract (node )
604640
605641
606- file .GLOBALS = {k :v for k ,v in file .GLOBALS .items () if k not in excluded }
642+ file .GLOBALS = {k :v for k ,v in file .GLOBALS .items () if k not in excluded and k not in ALL_DEFINITIONS }
643+ ALL_DEFINITIONS .update (file .GLOBALS )
607644
608645 for type in file .TYPEDEFS .values ():
609646 type .print_references (file )
@@ -625,6 +662,7 @@ def extract(node: clang.Cursor):
625662 print (f"export var __SYMBOLS: [{ num_decls } ; symbol::Symbol]" , file = fp2 )
626663
627664def main ():
665+ clang .Config .set_library_file (r"C:\Users\Vic\Programming\llvm-project\build\Release\bin\libclang.dll" )
628666 if sys .platform != "win32" :
629667 process_module ("linux" )
630668 process_module ("bfd" )
0 commit comments