Skip to content

Commit

Permalink
Add support for macos
Browse files Browse the repository at this point in the history
  • Loading branch information
= committed Mar 25, 2024
1 parent 3a7ac78 commit 2c41d27
Show file tree
Hide file tree
Showing 21 changed files with 10,545 additions and 1,649 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
a.out
__pycache__
.princess
venv
1 change: 0 additions & 1 deletion include/clang.h

This file was deleted.

5 changes: 5 additions & 0 deletions include/cstd.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ MUSL doesn't provide these
%EXCLUDE __isnan __iseqsig __issignaling isinf isnan gamma __isinff __finitef __isnanf __iseqsigf __issignalingf isinff isnanf gammaf
%EXCLUDE __isinfl __finitel __isnanl __iseqsigl __issignalingl isinfl finitel dreml significandl isnanl j0l j1l jnl y0l y1l ynl gammal
%EXCLUDE scalbl __assert_perror_fail __assert ssignal gsignal sigblock sigsetmask _toupper _tolower
MACOS specific
%EXCLUDE OSReadSwapInt16 OSReadSwapInt32 OSReadSwapInt64 OSWriteSwapInt16 OSWriteSwapInt32 OSWriteSwapInt64
%EXCLUDE _OSSwapInt16 _OSSwapInt32 _OSSwapInt64 __darwin_check_fd_set __darwin_fd_clr __darwin_fd_isset
%EXCLUDE __darwin_fd_set __sigbits __sputc
*/

#include <stdlib.h>
Expand Down
174 changes: 96 additions & 78 deletions include/gencstd.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
import re
import clang.cindex as clang


clang.Config.set_library_path(r"C:\Users\Vic\scoop\apps\llvm\current\bin")

class File:
def __init__(self, fp) -> None:
self.GLOBALS = {}
Expand Down Expand Up @@ -463,6 +460,9 @@ def parse_enum(name: str, inner: clang.Type, file: File) -> Type:
fields = []
child: clang.Cursor
for child in declaration.get_children():
try:
if child.kind == clang.CursorKind.UNEXPOSED_ATTR: continue
except ValueError: continue
fields.append((child.spelling, int(child.enum_value)))
file.GLOBALS[child.spelling] = ConstDecl(child.spelling, PRIMITIVES[clang.TypeKind.INT], int(child.enum_value))

Expand All @@ -471,8 +471,13 @@ def parse_enum(name: str, inner: clang.Type, file: File) -> Type:
file.TAGGED[name] = res
return res

class InvalidType(Exception):
pass

def parse_type(type: clang.Type, file: File, lookup: bool = False, is_in_struct: bool = False) -> Type:
if type.kind in PRIMITIVES:
if type.spelling == "__uint128_t":
return PRIMITIVES[clang.TypeKind.UINT128]
elif type.kind in PRIMITIVES:
return PRIMITIVES[type.kind]
elif type.kind == clang.TypeKind.POINTER:
inner = parse_type(type.get_pointee(), file, lookup, is_in_struct)
Expand Down Expand Up @@ -522,7 +527,7 @@ def parse_type(type: clang.Type, file: File, lookup: bool = False, is_in_struct:
spelling = spelling.strip()
return file.TYPEDEFS[spelling]

return IncompleteType(type.spelling)
raise InvalidType(str(type.kind) + ": " + type.spelling)

def process_module(name: str, *libs):
included = []
Expand All @@ -548,86 +553,89 @@ def process_module(name: str, *libs):
file = File(fp)

def extract(node: clang.Cursor):
if node.kind == clang.CursorKind.FUNCTION_DECL:
if node.is_static_method(): return

dllimport = False
for child in node.get_children():
if child.kind == clang.CursorKind.DLLIMPORT_ATTR:
dllimport = True

name = node.spelling
args = []

for child in node.get_arguments():
if child.kind == clang.CursorKind.PARM_DECL:
tokens = list(child.get_tokens())
spelling = escape_name(child.spelling)
args.append((spelling, parse_type(child.type, file)))

ret = parse_type(node.result_type, file)

is_variadic = False
if node.type.kind == clang.TypeKind.FUNCTIONPROTO:
is_variadic = node.type.is_function_variadic()

file.GLOBALS[name] = FunctionDecl(name, ret, args, is_variadic, dllimport)
elif node.kind == clang.CursorKind.VAR_DECL:
if node.storage_class == clang.StorageClass.EXTERN:
try:
if node.kind == clang.CursorKind.FUNCTION_DECL:
if node.is_static_method(): return

dllimport = False
for child in node.get_children():
if child.kind == clang.CursorKind.DLLIMPORT_ATTR:
dllimport = True

type = parse_type(node.type, file)
file.GLOBALS[node.spelling] = VarDecl(node.spelling, type, dllimport)
elif node.kind == clang.CursorKind.TYPEDEF_DECL:
name = node.spelling
underlying = node.underlying_typedef_type
if underlying.kind == clang.TypeKind.ELABORATED:
first_child = next(node.get_children())
if first_child.location == underlying.get_declaration().location or underlying.get_named_type().kind == clang.TypeKind.TYPEDEF:
type = parse_type(underlying, file, True)
else:
type = IncompleteType(underlying.spelling)
else:
type = parse_type(underlying, file)

file.TYPEDEFS[name] = type
elif node.kind == clang.CursorKind.STRUCT_DECL:
type = node.type
name = node.type.spelling
if name.startswith("struct") and node.location == type.get_declaration().location:
file.TAGGED[name] = parse_type(type, file, True)
elif node.kind == clang.CursorKind.UNION_DECL:
type = node.type
name = node.type.spelling
if name.startswith("union") and node.location == type.get_declaration().location:
file.TAGGED[name] = parse_type(type, file, True)
elif node.kind == clang.CursorKind.ENUM_DECL:
type = node.type
name = node.type.spelling
if name.startswith("enum") and node.location == type.get_declaration().location:
file.TAGGED[name] = parse_type(type, file, True)
elif node.kind == clang.CursorKind.MACRO_DEFINITION:
tokens = list(node.get_tokens())
if len(tokens) == 2 and tokens[1].kind == clang.TokenKind.LITERAL:
if node.spelling != "true" and node.spelling != "false":
token = tokens[1]
if token.spelling.startswith('"') and token.spelling.endswith('"'):
s = token.spelling
s = re.sub(r"(?<!\\)\\(\d{1,3})", lambda o: f"\\x{ + int(o.group(1), base = 8):02x}", s)
file.GLOBALS[node.spelling] = ConstDecl(node.spelling, string, s)
elif token.spelling.isdigit():
file.GLOBALS[node.spelling] = ConstDecl(node.spelling, PRIMITIVES[clang.TypeKind.INT], token.spelling)
name = node.spelling
args = []

for child in node.get_arguments():
if child.kind == clang.CursorKind.PARM_DECL:
tokens = list(child.get_tokens())
spelling = escape_name(child.spelling)
args.append((spelling, parse_type(child.type, file)))

ret = parse_type(node.result_type, file)

is_variadic = False
if node.type.kind == clang.TypeKind.FUNCTIONPROTO:
is_variadic = node.type.is_function_variadic()

file.GLOBALS[name] = FunctionDecl(name, ret, args, is_variadic, dllimport)
elif node.kind == clang.CursorKind.VAR_DECL:
if node.storage_class == clang.StorageClass.EXTERN:
dllimport = False
for child in node.get_children():
if child.kind == clang.CursorKind.DLLIMPORT_ATTR:
dllimport = True

type = parse_type(node.type, file)
file.GLOBALS[node.spelling] = VarDecl(node.spelling, type, dllimport)
elif node.kind == clang.CursorKind.TYPEDEF_DECL:
name = node.spelling
underlying = node.underlying_typedef_type
if underlying.kind == clang.TypeKind.ELABORATED:
first_child = next(node.get_children())
if first_child.location == underlying.get_declaration().location or underlying.get_named_type().kind == clang.TypeKind.TYPEDEF:
type = parse_type(underlying, file, True)
else:
try:
float(token.spelling)
file.GLOBALS[node.spelling] = ConstDecl(node.spelling, PRIMITIVES[clang.TypeKind.DOUBLE], token.spelling)
except ValueError: pass
type = IncompleteType(underlying.spelling)
else:
type = parse_type(underlying, file)

file.TYPEDEFS[name] = type
elif node.kind == clang.CursorKind.STRUCT_DECL:
type = node.type
name = node.type.spelling
if name.startswith("struct") and node.location == type.get_declaration().location:
file.TAGGED[name] = parse_type(type, file, True)
elif node.kind == clang.CursorKind.UNION_DECL:
type = node.type
name = node.type.spelling
if name.startswith("union") and node.location == type.get_declaration().location:
file.TAGGED[name] = parse_type(type, file, True)
elif node.kind == clang.CursorKind.ENUM_DECL:
type = node.type
name = node.type.spelling
if name.startswith("enum") and node.location == type.get_declaration().location:
file.TAGGED[name] = parse_type(type, file, True)
elif node.kind == clang.CursorKind.MACRO_DEFINITION:
tokens = list(node.get_tokens())
if len(tokens) == 2 and tokens[1].kind == clang.TokenKind.LITERAL:
if node.spelling != "true" and node.spelling != "false":
token = tokens[1]
if token.spelling.startswith('"') and token.spelling.endswith('"'):
s = token.spelling
s = re.sub(r"(?<!\\)\\(\d{1,3})", lambda o: f"\\x{ + int(o.group(1), base = 8):02x}", s)
file.GLOBALS[node.spelling] = ConstDecl(node.spelling, string, s)
elif token.spelling.isdigit():
file.GLOBALS[node.spelling] = ConstDecl(node.spelling, PRIMITIVES[clang.TypeKind.INT], token.spelling)
else:
try:
float(token.spelling)
file.GLOBALS[node.spelling] = ConstDecl(node.spelling, PRIMITIVES[clang.TypeKind.DOUBLE], token.spelling)
except ValueError: pass
except InvalidType as e:
print("Warning: Invalid type!")

index = clang.Index.create()
tu = index.parse(folder / f"{name}.h", args = ["-DMUSL"], options =
tu = index.parse(folder / f"{name}.h", args = ARGS, options =
clang.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD
| clang.TranslationUnit.PARSE_SKIP_FUNCTION_BODIES
| clang.TranslationUnit.PARSE_PRECOMPILED_PREAMBLE
Expand Down Expand Up @@ -657,14 +665,24 @@ def extract(node: clang.Cursor):

print(f"export var __SYMBOLS: [{num_decls}; symbol::Symbol]", file = fp2)

if sys.platform == "darwin":
ARGS = ["-I/opt/homebrew/include", "-I/opt/homebrew/opt/libffi/include", "-I/opt/homebrew/opt/binutils/include"]
else:
ARGS = []

def main():
if sys.platform == "darwin":
clang.Config.set_library_file("/opt/homebrew/Cellar/llvm/17.0.6_1/lib/libclang.dylib")

if sys.platform != "win32":
process_module("linux")
if sys.platform == "darwin":
process_module("macos")

process_module("bfd")
process_module("cstd")
process_module("ffi")
process_module("clang")
#process_module("clang")

if sys.platform == "win32":
process_module("windows", "User32.lib", "Kernel32.lib", "Dbghelp.lib")
Expand Down
5 changes: 5 additions & 0 deletions include/linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ MUSL Doesn't provide these
%EXCLUDE gsignal sigblock sigsetmask __getpgid ttyslot sethostid strtoq strtouq random_r srandom_r initstate_r
%EXCLUDE setstate_r drand48_r erand48_r lrand48_r nrand48_r mrand48_r jrand48_r srand48_r seed48_r lcong48_r
%EXCLUDE on_exit qecvt qfcvt qgcvt ecvt_r fcvt_r qecvt_r qfcvt_r rpmatch getdirentries ssignal
MACOS specific
%EXCLUDE OSReadSwapInt16 OSReadSwapInt32 OSReadSwapInt64 OSWriteSwapInt16 OSWriteSwapInt32 OSWriteSwapInt64
%EXCLUDE _OSSwapInt16 _OSSwapInt32 _OSSwapInt64 __darwin_check_fd_set __darwin_fd_clr __darwin_fd_isset
%EXCLUDE __darwin_fd_set __sigbits __sputc
*/

#ifndef _WIN32
Expand Down
16 changes: 16 additions & 0 deletions include/macos.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// TODO Add more stuff here
/*
%EXCLUDE KERNEL_AUDIT_TOKEN KERNEL_SECURITY_TOKEN
%EXCLUDE NXConvertHostDoubleToSwapped NXConvertHostFloatToSwapped NXConvertSwappedDoubleToHost NXConvertSwappedFloatToHost NXHostByteOrder
%EXCLUDE NXSwapBigDoubleToHost NXSwapBigFloatToHost NXSwapBigIntToHost NXSwapBigLongLongToHost NXSwapBigLongToHost NXSwapBigShortToHost
%EXCLUDE NXSwapDouble NXSwapFloat NXSwapHostDoubleToBig NXSwapHostDoubleToLittle NXSwapHostFloatToBig NXSwapHostFloatToLittle NXSwapHostIntToBig
%EXCLUDE NXSwapHostIntToLittle NXSwapHostLongLongToBig NXSwapHostLongLongToLittle NXSwapHostLongToBig NXSwapHostLongToLittle NXSwapHostShortToBig
%EXCLUDE NXSwapHostShortToLittle NXSwapInt NXSwapLittleDoubleToHost NXSwapLittleFloatToHost NXSwapLittleIntToHost NXSwapLittleLongLongToHost
%EXCLUDE NXSwapLittleLongToHost NXSwapLittleShortToHost NXSwapLong NXSwapLongLong NXSwapShort OSHostByteOrder OSReadSwapInt16 OSReadSwapInt32
%EXCLUDE OSReadSwapInt64 OSWriteSwapInt16 OSWriteSwapInt32 OSWriteSwapInt64 _OSReadInt16 _OSReadInt32 _OSReadInt64 _OSSwapInt16 _OSSwapInt32
%EXCLUDE _OSSwapInt64 _OSWriteInt16 _OSWriteInt32 _OSWriteInt64
*/

#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
Loading

0 comments on commit 2c41d27

Please sign in to comment.