diff --git a/cli/all.c b/cli/all.c index d5b35cd..22e0d50 100644 --- a/cli/all.c +++ b/cli/all.c @@ -35,15 +35,3 @@ // Source : https://github.com/cofyc/argparse/ // About : Command-line arguments parsing library. #include "thirdparty/argparse/argparse.c" - -// Library : dlfcn-win32 -// License : MIT -// Source : https://github.com/dlfcn-win32/dlfcn-win32/ -// About : An implementation of dlfcn for Windows. -#ifdef _WIN32 -// FIXME: -// This library redefine the malloc family macro, which cause a compile -// time warning. -// -// #include "modules/thirdparty/dlfcn-win32/dlfcn.c" -#endif diff --git a/cli/modules/thirdparty/dlfcn-win32/COPYING b/cli/modules/thirdparty/dlfcn-win32/COPYING deleted file mode 100644 index 30e8e2e..0000000 --- a/cli/modules/thirdparty/dlfcn-win32/COPYING +++ /dev/null @@ -1,17 +0,0 @@ -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/cli/modules/thirdparty/dlfcn-win32/dlfcn.c b/cli/modules/thirdparty/dlfcn-win32/dlfcn.c deleted file mode 100644 index 7277f0e..0000000 --- a/cli/modules/thirdparty/dlfcn-win32/dlfcn.c +++ /dev/null @@ -1,785 +0,0 @@ -/* - * dlfcn-win32 - * Copyright (c) 2007 Ramiro Polla - * Copyright (c) 2015 Tiancheng "Timothy" Gu - * Copyright (c) 2019 Pali Rohár - * Copyright (c) 2020 Ralf Habacker - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifdef _DEBUG -#define _CRTDBG_MAP_ALLOC -#include -#include -#endif -#include -#include -#include - -/* Older versions do not have this type */ -#if _WIN32_WINNT < 0x0500 -typedef ULONG ULONG_PTR; -#endif - -/* Older SDK versions do not have these macros */ -#ifndef GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS -#define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS 0x4 -#endif -#ifndef GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT -#define GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT 0x2 -#endif - -#ifdef _MSC_VER -/* https://docs.microsoft.com/en-us/cpp/intrinsics/returnaddress */ -#pragma intrinsic( _ReturnAddress ) -#else -/* https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html */ -#ifndef _ReturnAddress -#define _ReturnAddress( ) ( __builtin_extract_return_addr( __builtin_return_address( 0 ) ) ) -#endif -#endif - -#ifdef DLFCN_WIN32_SHARED -#define DLFCN_WIN32_EXPORTS -#endif -#include "dlfcn.h" - -#if defined( _MSC_VER ) && _MSC_VER >= 1300 -/* https://docs.microsoft.com/en-us/cpp/cpp/noinline */ -#define DLFCN_NOINLINE __declspec( noinline ) -#elif defined( __GNUC__ ) && ( ( __GNUC__ > 3 ) || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 1 ) ) -/* https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html */ -#define DLFCN_NOINLINE __attribute__(( noinline )) -#else -#define DLFCN_NOINLINE -#endif - -/* Note: - * MSDN says these functions are not thread-safe. We make no efforts to have - * any kind of thread safety. - */ - -typedef struct local_object { - HMODULE hModule; - struct local_object *previous; - struct local_object *next; -} local_object; - -static local_object first_object; - -/* These functions implement a double linked list for the local objects. */ -static local_object *local_search( HMODULE hModule ) -{ - local_object *pobject; - - if( hModule == NULL ) - return NULL; - - for( pobject = &first_object; pobject; pobject = pobject->next ) - if( pobject->hModule == hModule ) - return pobject; - - return NULL; -} - -static BOOL local_add( HMODULE hModule ) -{ - local_object *pobject; - local_object *nobject; - - if( hModule == NULL ) - return TRUE; - - pobject = local_search( hModule ); - - /* Do not add object again if it's already on the list */ - if( pobject != NULL ) - return TRUE; - - for( pobject = &first_object; pobject->next; pobject = pobject->next ); - - nobject = (local_object *) malloc( sizeof( local_object ) ); - - if( !nobject ) - return FALSE; - - pobject->next = nobject; - nobject->next = NULL; - nobject->previous = pobject; - nobject->hModule = hModule; - - return TRUE; -} - -static void local_rem( HMODULE hModule ) -{ - local_object *pobject; - - if( hModule == NULL ) - return; - - pobject = local_search( hModule ); - - if( pobject == NULL ) - return; - - if( pobject->next ) - pobject->next->previous = pobject->previous; - if( pobject->previous ) - pobject->previous->next = pobject->next; - - free( pobject ); -} - -/* POSIX says dlerror( ) doesn't have to be thread-safe, so we use one - * static buffer. - * MSDN says the buffer cannot be larger than 64K bytes, so we set it to - * the limit. - */ -static char error_buffer[65535]; -static BOOL error_occurred; - -static void save_err_str( const char *str, DWORD dwMessageId ) -{ - DWORD ret; - size_t pos, len; - - len = strlen( str ); - if( len > sizeof( error_buffer ) - 5 ) - len = sizeof( error_buffer ) - 5; - - /* Format error message to: - * "": - */ - pos = 0; - error_buffer[pos++] = '"'; - memcpy( error_buffer + pos, str, len ); - pos += len; - error_buffer[pos++] = '"'; - error_buffer[pos++] = ':'; - error_buffer[pos++] = ' '; - - ret = FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwMessageId, - MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), - error_buffer + pos, (DWORD) ( sizeof( error_buffer ) - pos ), NULL ); - pos += ret; - - /* When FormatMessageA() fails it returns zero and does not touch buffer - * so add trailing null byte */ - if( ret == 0 ) - error_buffer[pos] = '\0'; - - if( pos > 1 ) - { - /* POSIX says the string must not have trailing */ - if( error_buffer[pos-2] == '\r' && error_buffer[pos-1] == '\n' ) - error_buffer[pos-2] = '\0'; - } - - error_occurred = TRUE; -} - -static void save_err_ptr_str( const void *ptr, DWORD dwMessageId ) -{ - char ptr_buf[2 + 2 * sizeof( ptr ) + 1]; - char num; - size_t i; - - ptr_buf[0] = '0'; - ptr_buf[1] = 'x'; - - for( i = 0; i < 2 * sizeof( ptr ); i++ ) - { - num = (char) ( ( ( (ULONG_PTR) ptr ) >> ( 8 * sizeof( ptr ) - 4 * ( i + 1 ) ) ) & 0xF ); - ptr_buf[2 + i] = num + ( ( num < 0xA ) ? '0' : ( 'A' - 0xA ) ); - } - - ptr_buf[2 + 2 * sizeof( ptr )] = 0; - - save_err_str( ptr_buf, dwMessageId ); -} - -static HMODULE MyGetModuleHandleFromAddress( void *addr ) -{ - static BOOL (WINAPI *GetModuleHandleExAPtr)(DWORD, LPCSTR, HMODULE *) = NULL; - static BOOL failed = FALSE; - HMODULE kernel32; - HMODULE hModule; - MEMORY_BASIC_INFORMATION info; - SIZE_T sLen; - - if( !failed && GetModuleHandleExAPtr == NULL ) - { - kernel32 = GetModuleHandleA( "Kernel32.dll" ); - if( kernel32 != NULL ) - GetModuleHandleExAPtr = (BOOL (WINAPI *)(DWORD, LPCSTR, HMODULE *)) GetProcAddress( kernel32, "GetModuleHandleExA" ); - if( GetModuleHandleExAPtr == NULL ) - failed = TRUE; - } - - if( !failed ) - { - /* If GetModuleHandleExA is available use it with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS */ - if( !GetModuleHandleExAPtr( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) addr, &hModule ) ) - return NULL; - } - else - { - /* To get HMODULE from address use undocumented hack from https://stackoverflow.com/a/2396380 - * The HMODULE of a DLL is the same value as the module's base address. - */ - sLen = VirtualQuery( addr, &info, sizeof( info ) ); - if( sLen != sizeof( info ) ) - return NULL; - hModule = (HMODULE) info.AllocationBase; - } - - return hModule; -} - -/* Load Psapi.dll at runtime, this avoids linking caveat */ -static BOOL MyEnumProcessModules( HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded ) -{ - static BOOL (WINAPI *EnumProcessModulesPtr)(HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; - static BOOL failed = FALSE; - UINT uMode; - HMODULE psapi; - - if( failed ) - return FALSE; - - if( EnumProcessModulesPtr == NULL ) - { - /* Windows 7 and newer versions have K32EnumProcessModules in Kernel32.dll which is always pre-loaded */ - psapi = GetModuleHandleA( "Kernel32.dll" ); - if( psapi != NULL ) - EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( psapi, "K32EnumProcessModules" ); - - /* Windows Vista and older version have EnumProcessModules in Psapi.dll which needs to be loaded */ - if( EnumProcessModulesPtr == NULL ) - { - /* Do not let Windows display the critical-error-handler message box */ - uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); - psapi = LoadLibraryA( "Psapi.dll" ); - if( psapi != NULL ) - { - EnumProcessModulesPtr = (BOOL (WINAPI *)(HANDLE, HMODULE *, DWORD, LPDWORD)) GetProcAddress( psapi, "EnumProcessModules" ); - if( EnumProcessModulesPtr == NULL ) - FreeLibrary( psapi ); - } - SetErrorMode( uMode ); - } - - if( EnumProcessModulesPtr == NULL ) - { - failed = TRUE; - return FALSE; - } - } - - return EnumProcessModulesPtr( hProcess, lphModule, cb, lpcbNeeded ); -} - -DLFCN_EXPORT -void *dlopen( const char *file, int mode ) -{ - HMODULE hModule; - UINT uMode; - - error_occurred = FALSE; - - /* Do not let Windows display the critical-error-handler message box */ - uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); - - if( file == NULL ) - { - /* POSIX says that if the value of file is NULL, a handle on a global - * symbol object must be provided. That object must be able to access - * all symbols from the original program file, and any objects loaded - * with the RTLD_GLOBAL flag. - * The return value from GetModuleHandle( ) allows us to retrieve - * symbols only from the original program file. EnumProcessModules() is - * used to access symbols from other libraries. For objects loaded - * with the RTLD_LOCAL flag, we create our own list later on. They are - * excluded from EnumProcessModules() iteration. - */ - hModule = GetModuleHandle( NULL ); - - if( !hModule ) - save_err_str( "(null)", GetLastError( ) ); - } - else - { - HANDLE hCurrentProc; - DWORD dwProcModsBefore, dwProcModsAfter; - char lpFileName[MAX_PATH]; - size_t i, len; - - len = strlen( file ); - - if( len >= sizeof( lpFileName ) ) - { - save_err_str( file, ERROR_FILENAME_EXCED_RANGE ); - hModule = NULL; - } - else - { - /* MSDN says backslashes *must* be used instead of forward slashes. */ - for( i = 0; i < len; i++ ) - { - if( file[i] == '/' ) - lpFileName[i] = '\\'; - else - lpFileName[i] = file[i]; - } - lpFileName[len] = '\0'; - - hCurrentProc = GetCurrentProcess( ); - - if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsBefore ) == 0 ) - dwProcModsBefore = 0; - - /* POSIX says the search path is implementation-defined. - * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely - * to UNIX's search paths (start with system folders instead of current - * folder). - */ - hModule = LoadLibraryExA( lpFileName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH ); - - if( !hModule ) - { - save_err_str( lpFileName, GetLastError( ) ); - } - else - { - if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwProcModsAfter ) == 0 ) - dwProcModsAfter = 0; - - /* If the object was loaded with RTLD_LOCAL, add it to list of local - * objects, so that its symbols cannot be retrieved even if the handle for - * the original program file is passed. POSIX says that if the same - * file is specified in multiple invocations, and any of them are - * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the - * symbols will remain global. If number of loaded modules was not - * changed after calling LoadLibraryEx(), it means that library was - * already loaded. - */ - if( (mode & RTLD_LOCAL) && dwProcModsBefore != dwProcModsAfter ) - { - if( !local_add( hModule ) ) - { - save_err_str( lpFileName, ERROR_NOT_ENOUGH_MEMORY ); - FreeLibrary( hModule ); - hModule = NULL; - } - } - else if( !(mode & RTLD_LOCAL) && dwProcModsBefore == dwProcModsAfter ) - { - local_rem( hModule ); - } - } - } - } - - /* Return to previous state of the error-mode bit flags. */ - SetErrorMode( uMode ); - - return (void *) hModule; -} - -DLFCN_EXPORT -int dlclose( void *handle ) -{ - HMODULE hModule = (HMODULE) handle; - BOOL ret; - - error_occurred = FALSE; - - ret = FreeLibrary( hModule ); - - /* If the object was loaded with RTLD_LOCAL, remove it from list of local - * objects. - */ - if( ret ) - local_rem( hModule ); - else - save_err_ptr_str( handle, GetLastError( ) ); - - /* dlclose's return value in inverted in relation to FreeLibrary's. */ - ret = !ret; - - return (int) ret; -} - -DLFCN_NOINLINE /* Needed for _ReturnAddress() */ -DLFCN_EXPORT -void *dlsym( void *handle, const char *name ) -{ - FARPROC symbol; - HMODULE hCaller; - HMODULE hModule; - DWORD dwMessageId; - - error_occurred = FALSE; - - symbol = NULL; - hCaller = NULL; - hModule = GetModuleHandle( NULL ); - dwMessageId = 0; - - if( handle == RTLD_DEFAULT ) - { - /* The symbol lookup happens in the normal global scope; that is, - * a search for a symbol using this handle would find the same - * definition as a direct use of this symbol in the program code. - * So use same lookup procedure as when filename is NULL. - */ - handle = hModule; - } - else if( handle == RTLD_NEXT ) - { - /* Specifies the next object after this one that defines name. - * This one refers to the object containing the invocation of dlsym(). - * The next object is the one found upon the application of a load - * order symbol resolution algorithm. To get caller function of dlsym() - * use _ReturnAddress() intrinsic. To get HMODULE of caller function - * use MyGetModuleHandleFromAddress() which calls either standard - * GetModuleHandleExA() function or hack via VirtualQuery(). - */ - hCaller = MyGetModuleHandleFromAddress( _ReturnAddress( ) ); - - if( hCaller == NULL ) - { - dwMessageId = ERROR_INVALID_PARAMETER; - goto end; - } - } - - if( handle != RTLD_NEXT ) - { - symbol = GetProcAddress( (HMODULE) handle, name ); - - if( symbol != NULL ) - goto end; - } - - /* If the handle for the original program file is passed, also search - * in all globally loaded objects. - */ - - if( hModule == handle || handle == RTLD_NEXT ) - { - HANDLE hCurrentProc; - HMODULE *modules; - DWORD cbNeeded; - DWORD dwSize; - size_t i; - - hCurrentProc = GetCurrentProcess( ); - - /* GetModuleHandle( NULL ) only returns the current program file. So - * if we want to get ALL loaded module including those in linked DLLs, - * we have to use EnumProcessModules( ). - */ - if( MyEnumProcessModules( hCurrentProc, NULL, 0, &dwSize ) != 0 ) - { - modules = malloc( dwSize ); - if( modules ) - { - if( MyEnumProcessModules( hCurrentProc, modules, dwSize, &cbNeeded ) != 0 && dwSize == cbNeeded ) - { - for( i = 0; i < dwSize / sizeof( HMODULE ); i++ ) - { - if( handle == RTLD_NEXT && hCaller ) - { - /* Next modules can be used for RTLD_NEXT */ - if( hCaller == modules[i] ) - hCaller = NULL; - continue; - } - if( local_search( modules[i] ) ) - continue; - symbol = GetProcAddress( modules[i], name ); - if( symbol != NULL ) - { - free( modules ); - goto end; - } - } - - } - free( modules ); - } - else - { - dwMessageId = ERROR_NOT_ENOUGH_MEMORY; - goto end; - } - } - } - -end: - if( symbol == NULL ) - { - if( !dwMessageId ) - dwMessageId = ERROR_PROC_NOT_FOUND; - save_err_str( name, dwMessageId ); - } - - return *(void **) (&symbol); -} - -DLFCN_EXPORT -char *dlerror( void ) -{ - /* If this is the second consecutive call to dlerror, return NULL */ - if( !error_occurred ) - return NULL; - - /* POSIX says that invoking dlerror( ) a second time, immediately following - * a prior invocation, shall result in NULL being returned. - */ - error_occurred = FALSE; - - return error_buffer; -} - -/* See https://docs.microsoft.com/en-us/archive/msdn-magazine/2002/march/inside-windows-an-in-depth-look-into-the-win32-portable-executable-file-format-part-2 - * for details */ - -/* Get specific image section */ -static BOOL get_image_section( HMODULE module, int index, void **ptr, DWORD *size ) -{ - IMAGE_DOS_HEADER *dosHeader; - IMAGE_OPTIONAL_HEADER *optionalHeader; - - dosHeader = (IMAGE_DOS_HEADER *) module; - - if( dosHeader->e_magic != 0x5A4D ) - return FALSE; - - optionalHeader = (IMAGE_OPTIONAL_HEADER *) ( (BYTE *) module + dosHeader->e_lfanew + 24 ); - - if( optionalHeader->Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC ) - return FALSE; - - if( index < 0 || index > IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR ) - return FALSE; - - if( optionalHeader->DataDirectory[index].Size == 0 || optionalHeader->DataDirectory[index].VirtualAddress == 0 ) - return FALSE; - - if( size != NULL ) - *size = optionalHeader->DataDirectory[index].Size; - - *ptr = (void *)( (BYTE *) module + optionalHeader->DataDirectory[index].VirtualAddress ); - - return TRUE; -} - -/* Return symbol name for a given address from export table */ -static const char *get_export_symbol_name( HMODULE module, IMAGE_EXPORT_DIRECTORY *ied, void *addr, void **func_address ) -{ - DWORD i; - void *candidateAddr = NULL; - int candidateIndex = -1; - BYTE *base = (BYTE *) module; - DWORD *functionAddressesOffsets = (DWORD *) (base + ied->AddressOfFunctions); - DWORD *functionNamesOffsets = (DWORD *) (base + ied->AddressOfNames); - USHORT *functionNameOrdinalsIndexes = (USHORT *) (base + ied->AddressOfNameOrdinals); - - for( i = 0; i < ied->NumberOfFunctions; i++ ) - { - if( (void *) ( base + functionAddressesOffsets[i] ) > addr || candidateAddr >= (void *) ( base + functionAddressesOffsets[i] ) ) - continue; - - candidateAddr = (void *) ( base + functionAddressesOffsets[i] ); - candidateIndex = i; - } - - if( candidateIndex == -1 ) - return NULL; - - *func_address = candidateAddr; - - for( i = 0; i < ied->NumberOfNames; i++ ) - { - if( functionNameOrdinalsIndexes[i] == candidateIndex ) - return (const char *) ( base + functionNamesOffsets[i] ); - } - - return NULL; -} - -static BOOL is_valid_address( void *addr ) -{ - MEMORY_BASIC_INFORMATION info; - SIZE_T result; - - if( addr == NULL ) - return FALSE; - - /* check valid pointer */ - result = VirtualQuery( addr, &info, sizeof( info ) ); - - if( result == 0 || info.AllocationBase == NULL || info.AllocationProtect == 0 || info.AllocationProtect == PAGE_NOACCESS ) - return FALSE; - - return TRUE; -} - -/* Return state if address points to an import thunk - * - * An import thunk is setup with a 'jmp' instruction followed by an - * absolute address (32bit) or relative offset (64bit) pointing into - * the import address table (iat), which is partially maintained by - * the runtime linker. - */ -static BOOL is_import_thunk( void *addr ) -{ - return *(short *) addr == 0x25ff ? TRUE : FALSE; -} - -/* Return adress from the import address table (iat), - * if the original address points to a thunk table entry. - */ -static void *get_address_from_import_address_table( void *iat, DWORD iat_size, void *addr ) -{ - BYTE *thkp = (BYTE *) addr; - /* Get offset from thunk table (after instruction 0xff 0x25) - * 4018c8 <_VirtualQuery>: ff 25 4a 8a 00 00 - */ - ULONG offset = *(ULONG *)( thkp + 2 ); -#ifdef _WIN64 - /* On 64 bit the offset is relative - * 4018c8: ff 25 4a 8a 00 00 jmpq *0x8a4a(%rip) # 40a318 <__imp_VirtualQuery> - * And can be also negative (MSVC in WDK) - * 100002f20: ff 25 3a e1 ff ff jmpq *-0x1ec6(%rip) # 0x100001060 - * So cast to signed LONG type - */ - BYTE *ptr = (BYTE *)( thkp + 6 + (LONG) offset ); -#else - /* On 32 bit the offset is absolute - * 4019b4: ff 25 90 71 40 00 jmp *0x40719 - */ - BYTE *ptr = (BYTE *) offset; -#endif - - if( !is_valid_address( ptr ) || ptr < (BYTE *) iat || ptr > (BYTE *) iat + iat_size ) - return NULL; - - return *(void **) ptr; -} - -/* Holds module filename */ -static char module_filename[2*MAX_PATH]; - -static BOOL fill_info( void *addr, Dl_info *info ) -{ - HMODULE hModule; - DWORD dwSize; - IMAGE_EXPORT_DIRECTORY *ied; - void *funcAddress = NULL; - - /* Get module of the specified address */ - hModule = MyGetModuleHandleFromAddress( addr ); - - if( hModule == NULL ) - return FALSE; - - dwSize = GetModuleFileNameA( hModule, module_filename, sizeof( module_filename ) ); - - if( dwSize == 0 || dwSize == sizeof( module_filename ) ) - return FALSE; - - info->dli_fname = module_filename; - info->dli_fbase = (void *) hModule; - - /* Find function name and function address in module's export table */ - if( get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_EXPORT, (void **) &ied, NULL ) ) - info->dli_sname = get_export_symbol_name( hModule, ied, addr, &funcAddress ); - else - info->dli_sname = NULL; - - info->dli_saddr = info->dli_sname == NULL ? NULL : funcAddress != NULL ? funcAddress : addr; - - return TRUE; -} - -DLFCN_EXPORT -int dladdr( void *addr, Dl_info *info ) -{ - if( info == NULL ) - return 0; - - if( !is_valid_address( addr ) ) - return 0; - - if( is_import_thunk( addr ) ) - { - void *iat; - DWORD iatSize; - HMODULE hModule; - - /* Get module of the import thunk address */ - hModule = MyGetModuleHandleFromAddress( addr ); - - if( hModule == NULL ) - return 0; - - if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IAT, &iat, &iatSize ) ) - { - /* Fallback for cases where the iat is not defined, - * for example i586-mingw32msvc-gcc */ - IMAGE_IMPORT_DESCRIPTOR *iid; - DWORD iidSize; - - if( !get_image_section( hModule, IMAGE_DIRECTORY_ENTRY_IMPORT, (void **) &iid, &iidSize ) ) - return 0; - - if( iid == NULL || iid->Characteristics == 0 || iid->FirstThunk == 0 ) - return 0; - - iat = (void *)( (BYTE *) hModule + iid->FirstThunk ); - /* We assume that in this case iid and iat's are in linear order */ - iatSize = iidSize - (DWORD) ( (BYTE *) iat - (BYTE *) iid ); - } - - addr = get_address_from_import_address_table( iat, iatSize, addr ); - - if( !is_valid_address( addr ) ) - return 0; - } - - if( !fill_info( addr, info ) ) - return 0; - - return 1; -} - -#ifdef DLFCN_WIN32_SHARED -BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) -{ - (void) hinstDLL; - (void) fdwReason; - (void) lpvReserved; - return TRUE; -} -#endif diff --git a/cli/modules/thirdparty/dlfcn-win32/dlfcn.h b/cli/modules/thirdparty/dlfcn-win32/dlfcn.h deleted file mode 100644 index 04188ca..0000000 --- a/cli/modules/thirdparty/dlfcn-win32/dlfcn.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * dlfcn-win32 - * Copyright (c) 2007 Ramiro Polla - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef DLFCN_H -#define DLFCN_H - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(DLFCN_WIN32_SHARED) -#if defined(DLFCN_WIN32_EXPORTS) -# define DLFCN_EXPORT __declspec(dllexport) -#else -# define DLFCN_EXPORT __declspec(dllimport) -#endif -#else -# define DLFCN_EXPORT -#endif - -/* Relocations are performed when the object is loaded. */ -#define RTLD_NOW 0 - -/* Relocations are performed at an implementation-defined time. - * Windows API does not support lazy symbol resolving (when first reference - * to a given symbol occurs). So RTLD_LAZY implementation is same as RTLD_NOW. - */ -#define RTLD_LAZY RTLD_NOW - -/* All symbols are available for relocation processing of other modules. */ -#define RTLD_GLOBAL (1 << 1) - -/* All symbols are not made available for relocation processing by other modules. */ -#define RTLD_LOCAL (1 << 2) - -/* These two were added in The Open Group Base Specifications Issue 6. - * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. - */ - -/* The symbol lookup happens in the normal global scope. */ -#define RTLD_DEFAULT ((void *)0) - -/* Specifies the next object after this one that defines name. */ -#define RTLD_NEXT ((void *)-1) - -/* Structure filled in by dladdr() */ -typedef struct dl_info -{ - const char *dli_fname; /* Filename of defining object (thread unsafe and reused on every call to dladdr) */ - void *dli_fbase; /* Load address of that object */ - const char *dli_sname; /* Name of nearest lower symbol */ - void *dli_saddr; /* Exact value of nearest symbol */ -} Dl_info; - -/* Open a symbol table handle. */ -DLFCN_EXPORT void *dlopen(const char *file, int mode); - -/* Close a symbol table handle. */ -DLFCN_EXPORT int dlclose(void *handle); - -/* Get the address of a symbol from a symbol table handle. */ -DLFCN_EXPORT void *dlsym(void *handle, const char *name); - -/* Get diagnostic information. */ -DLFCN_EXPORT char *dlerror(void); - -/* Translate address to symbolic information (no POSIX standard) */ -DLFCN_EXPORT int dladdr(void *addr, Dl_info *info); - -#ifdef __cplusplus -} -#endif - -#endif /* DLFCN_H */ diff --git a/cli/native.py b/cli/native.py index 837b7c7..cb4631a 100644 --- a/cli/native.py +++ b/cli/native.py @@ -12,7 +12,8 @@ from os.path import (join, exists, abspath, THIS_PATH = abspath(dirname(__file__)) POCKET_HEADER = join(THIS_PATH, "../src/include/pocketlang.h") -TARGET = join(THIS_PATH, "./modules/pknative.gen.c") +TARGET_NATIVE = join(THIS_PATH, "./modules/pknative.gen.c") +TARGET_DL = join(THIS_PATH, "./modules/std_dl_api.gen.h") PK_API = "pk_api" PK_API_TYPE = "PkNativeApi" @@ -109,15 +110,37 @@ def init_api(api_functions): assign += f"\n {PK_API}.{fn}_ptr = api->{fn}_ptr;" return API_DEF % assign + '\n' +def make_api(api_functions): + source = "#if defined(NATIVE_API_IMPLEMENT)\n\n" + source += f"{PK_API_TYPE} dlMakeApi() {{\n\n" + source += f" {PK_API_TYPE} api;\n\n" + for fn, params, ret in api_functions: + source += f" api.{fn}_ptr = {fn};\n" + source += "\n" + source += " return api;\n" + source += "}\n\n" + source += "#endif // NATIVE_API_IMPLEMENT\n\n" + return source + def generate(): api_functions = get_api_functions() - with open(TARGET, 'w') as fp: + + ## Generate pocket native api. + with open(TARGET_NATIVE, 'w') as fp: fp.write(SOURCE_GEN) fp.write(fn_typedefs(api_functions)) fp.write(api_typedef(api_functions)) fp.write(init_api(api_functions)) fp.write(define_functions(api_functions)) + ## Generate dl module api definition. + with open(TARGET_DL, 'w') as fp: + fp.write(SOURCE_GEN) + fp.write(fn_typedefs(api_functions)) + fp.write(api_typedef(api_functions)) + fp.write(make_api(api_functions)) + if __name__ == "__main__": generate() - print("Generated:", relpath(TARGET, os.getcwd())) + print("Generated:", relpath(TARGET_NATIVE, os.getcwd())) + print("Generated:", relpath(TARGET_DL, os.getcwd())) diff --git a/cli/repl.c b/cli/repl.c index a74ee34..1ba8ad6 100644 --- a/cli/repl.c +++ b/cli/repl.c @@ -133,7 +133,7 @@ int repl(PKVM* vm, const PkCompileOptions* options) { if (result != PK_RESULT_SUCCESS) continue; // Compiled source would be the "main" function of the module. Run it. - PkHandle* _main = pkGetMainFunction(vm, module); + PkHandle* _main = pkModuleGetMainFunction(vm, module); PkHandle* fiber = pkNewFiber(vm, _main); ASSERT((_main != NULL) && (fiber != NULL), OOPS); diff --git a/src/include/pocketlang.h b/src/include/pocketlang.h index fe50b25..da92a03 100644 --- a/src/include/pocketlang.h +++ b/src/include/pocketlang.h @@ -74,9 +74,11 @@ typedef struct PkHandle PkHandle; // alive use `pkNewHandle()`. typedef void* PkVar; -// Type enum of the pocketlang variables, this can be used to get the type -// from a PkVar in the method pkGetVarType(). +// Type enum of the pocketlang's first class types. Note that Object isn't +// instanciable (as of now) but they're considered first calss. typedef enum { + PK_OBJECT = 0, + PK_NULL, PK_BOOL, PK_NUMBER, @@ -85,10 +87,10 @@ typedef enum { PK_MAP, PK_RANGE, PK_MODULE, - PK_FUNCTION, + PK_CLOSURE, PK_FIBER, PK_CLASS, - PK_INST, + PK_INSTANCE, } PkVarType; typedef struct PkStringPtr PkStringPtr; @@ -257,7 +259,7 @@ PK_PUBLIC void pkModuleAddFunction(PKVM* vm, PkHandle* module, // Returns the main function of the [module]. When a module is compiled all of // it's statements are wrapped around an implicit main function. -PK_PUBLIC PkHandle* pkGetMainFunction(PKVM* vm, PkHandle* module); +PK_PUBLIC PkHandle* pkModuleGetMainFunction(PKVM* vm, PkHandle* module); // Compile the [module] with the provided [source]. Set the compiler options // with the the [options] argument or set to NULL for default options. diff --git a/src/pk_compiler.c b/src/pk_compiler.c index 19d1548..064ad5c 100644 --- a/src/pk_compiler.c +++ b/src/pk_compiler.c @@ -237,7 +237,6 @@ typedef struct { } GrammarRule; typedef enum { - DEPTH_MODULE = -2, //< Only used for module body function's depth. DEPTH_GLOBAL = -1, //< Global variables. DEPTH_LOCAL, //< Local scope. Increase with inner scope. } Depth; @@ -1249,9 +1248,9 @@ static bool matchAssignment(Compiler* compiler) { static int findBuiltinFunction(const PKVM* vm, const char* name, uint32_t length) { for (int i = 0; i < vm->builtins_count; i++) { - uint32_t bfn_length = (uint32_t)strlen(vm->builtins[i]->fn->name); + uint32_t bfn_length = (uint32_t)strlen(vm->builtins_funcs[i]->fn->name); if (bfn_length != length) continue; - if (strncmp(name, vm->builtins[i]->fn->name, length) == 0) { + if (strncmp(name, vm->builtins_funcs[i]->fn->name, length) == 0) { return i; } } @@ -3142,10 +3141,6 @@ PkResult compile(PKVM* vm, Module* module, const char* source, Func curr_fn; compilerPushFunc(compiler, &curr_fn, module->body->fn); - // At the begining the compiler's scope will be DEPTH_GLOBAL and that'll be - // set to to the current functions depth. Override for the body function. - curr_fn.depth = DEPTH_MODULE; - // Lex initial tokens. current <-- next. lexToken(&(compiler->parser)); lexToken(&(compiler->parser)); diff --git a/src/pk_core.c b/src/pk_core.c index d5387cc..b10b7e6 100644 --- a/src/pk_core.c +++ b/src/pk_core.c @@ -46,35 +46,41 @@ static void moduleAddFunctionInternal(PKVM* vm, Module* module, /* CORE PUBLIC API */ /*****************************************************************************/ +#define CHECK_NULL(name) \ + ASSERT(name != NULL, "Argument " #name " was NULL."); + +#define CHECK_TYPE(handle, type) \ + do { \ + CHECK_NULL(handle); \ + ASSERT(IS_OBJ_TYPE(handle->value, type), \ + "Given handle is not of type " #type "."); \ + } while (false) + PkHandle* pkNewModule(PKVM* vm, const char* name) { + CHECK_NULL(name); Module* module = newModuleInternal(vm, name); return vmNewHandle(vm, VAR_OBJ(module)); } void pkRegisterModule(PKVM* vm, PkHandle* module) { - ASSERT(module != NULL, "Argument module was NULL."); - ASSERT(IS_OBJ_TYPE(module->value, OBJ_MODULE), - "Given handle is not a module."); + CHECK_TYPE(module, OBJ_MODULE); + Module* module_ = (Module*)AS_OBJ(module->value); vmRegisterModule(vm, module_, module_->name); } void pkModuleAddGlobal(PKVM* vm, PkHandle* module, const char* name, PkHandle* value) { - ASSERT(module != NULL, "Argument module was NULL."); - ASSERT(value != NULL, "Argument value was NULL."); - ASSERT(IS_OBJ_TYPE(module->value, OBJ_MODULE), - "Given handle is not a module."); + CHECK_TYPE(module, OBJ_MODULE); + CHECK_NULL(value); moduleAddGlobal(vm, (Module*)AS_OBJ(module->value), name, (uint32_t)strlen(name), value->value); } PkHandle* pkModuleGetGlobal(PKVM* vm, PkHandle* module, const char* name) { - ASSERT(module != NULL, "Argument module was NULL."); - ASSERT(name != NULL, "Argument name was NULL."); - ASSERT(IS_OBJ_TYPE(module->value, OBJ_MODULE), - "Given handle is not a module."); + CHECK_TYPE(module, OBJ_MODULE); + CHECK_NULL(name); Module* module_ = (Module*)AS_OBJ(module->value); int index = moduleGetGlobalIndex(module_, name, (uint32_t)strlen(name)); @@ -84,18 +90,17 @@ PkHandle* pkModuleGetGlobal(PKVM* vm, PkHandle* module, const char* name) { void pkModuleAddFunction(PKVM* vm, PkHandle* module, const char* name, pkNativeFn fptr, int arity) { - ASSERT(module != NULL, "Argument module was NULL."); - ASSERT(IS_OBJ_TYPE(module->value, OBJ_MODULE), - "Given handle is not a module."); + CHECK_TYPE(module, OBJ_MODULE); + CHECK_NULL(fptr); + moduleAddFunctionInternal(vm, (Module*)AS_OBJ(module->value), name, fptr, arity, NULL /*TODO: Public API for function docstring.*/); } -PkHandle* pkGetMainFunction(PKVM* vm, PkHandle* module) { - ASSERT(module != NULL, "Argument module was NULL."); - ASSERT(IS_OBJ_TYPE(module->value, OBJ_MODULE), - "Given handle is not a module."); +PkHandle* pkModuleGetMainFunction(PKVM* vm, PkHandle* module) { + CHECK_TYPE(module, OBJ_MODULE); + Module* _module = (Module*)AS_OBJ(module->value); int main_index = moduleGetGlobalIndex(_module, IMPLICIT_MAIN_NAME, @@ -321,6 +326,9 @@ bool pkFiberIsDone(const PkHandle* fiber) { return _fiber->state == FIBER_DONE; } +#undef CHECK_NULL +#undef CHECK_TYPE + /*****************************************************************************/ /* VALIDATORS */ /*****************************************************************************/ @@ -766,8 +774,8 @@ static void initializeBuiltinFN(PKVM* vm, Closure** bfn, const char* name, } static void initializeBuiltinFunctions(PKVM* vm) { -#define INITIALIZE_BUILTIN_FN(name, fn, argc) \ - initializeBuiltinFN(vm, &vm->builtins[vm->builtins_count++], name, \ +#define INITIALIZE_BUILTIN_FN(name, fn, argc) \ + initializeBuiltinFN(vm, &vm->builtins_funcs[vm->builtins_count++], name, \ (int)strlen(name), argc, fn, DOCSTRING(fn)); // General functions. INITIALIZE_BUILTIN_FN("type_name", coreTypeName, 1); @@ -1467,8 +1475,8 @@ bool varContains(PKVM* vm, Var elem, Var container) { Var varGetAttrib(PKVM* vm, Var on, String* attrib) { -#define ERR_NO_ATTRIB(vm, on, attrib) \ - VM_SET_ERROR(vm, stringFormat(vm, "'$' object has no attribute named '$'", \ +#define ERR_NO_ATTRIB(vm, on, attrib) \ + VM_SET_ERROR(vm, stringFormat(vm, "'$' object has no attribute named '$'.", \ varTypeName(on), attrib->data)) if (!IS_OBJ(on)) { diff --git a/src/pk_debug.c b/src/pk_debug.c index 864cc98..3fb0088 100644 --- a/src/pk_debug.c +++ b/src/pk_debug.c @@ -227,7 +227,7 @@ void dumpFunctionCode(PKVM* vm, Function* func) { { int index = READ_BYTE(); ASSERT_INDEX(index, vm->builtins_count); - const char* name = vm->builtins[index]->fn->name; + const char* name = vm->builtins_funcs[index]->fn->name; // Prints: %5d [Fn:%s]\n PRINT_INT(index); PRINT(" [Fn:"); diff --git a/src/pk_value.c b/src/pk_value.c index ceb4c36..9a4c3d6 100644 --- a/src/pk_value.c +++ b/src/pk_value.c @@ -18,29 +18,18 @@ PkVarType pkGetValueType(const PkVar value) { __ASSERT(value != NULL, "Given value was NULL."); + const Var value_ = *(const Var*)(value); - if (IS_NULL(*(const Var*)(value))) return PK_NULL; - if (IS_BOOL(*(const Var*)(value))) return PK_BOOL; - if (IS_NUM(*(const Var*)(value))) return PK_NUMBER; + if (IS_NULL(value_)) return PK_NULL; + if (IS_BOOL(value_)) return PK_BOOL; + if (IS_NUM(value_)) return PK_NUMBER; - __ASSERT(IS_OBJ(*(const Var*)(value)), - "Invalid var pointer. Might be a dangling pointer"); + ASSERT(IS_OBJ(*(const Var*)(value)), + "Invalid var pointer (Might be a dangling pointer)."); - const Object* obj = AS_OBJ(*(const Var*)(value)); - switch (obj->type) { - case OBJ_STRING: return PK_STRING; - case OBJ_LIST: return PK_LIST; - case OBJ_MAP: return PK_MAP; - case OBJ_RANGE: return PK_RANGE; - case OBJ_MODULE: return PK_MODULE; - case OBJ_FUNC: return PK_FUNCTION; - case OBJ_FIBER: return PK_FIBER; - case OBJ_CLASS: return PK_CLASS; - case OBJ_INST: return PK_INST; - } + const Object* obj = AS_OBJ(value_); + return getObjPkVarType(obj->type); - UNREACHABLE(); - return PK_NULL; } PkHandle* pkNewString(PKVM* vm, const char* value) { @@ -525,6 +514,7 @@ Class* newClass(PKVM* vm, Module* module, const char* name, uint32_t length, pkUintBufferInit(&cls->field_names); cls->owner = module; + cls->docstring = NULL; cls->name = moduleAddString(module, vm, name, length, NULL); // Since characters '@' and '$' are special in stringFormat, and they @@ -1333,24 +1323,56 @@ bool instSetAttrib(PKVM* vm, Instance* inst, String* attrib, Var value) { /* UTILITY FUNCTIONS */ /*****************************************************************************/ +PkVarType getObjPkVarType(ObjectType type) { + switch (type) { + case OBJ_STRING: return PK_STRING; + case OBJ_LIST: return PK_LIST; + case OBJ_MAP: return PK_MAP; + case OBJ_RANGE: return PK_RANGE; + case OBJ_MODULE: return PK_MODULE; + case OBJ_FUNC: UNREACHABLE(); + case OBJ_CLOSURE: return PK_CLOSURE; + case OBJ_UPVALUE: UNREACHABLE(); + case OBJ_FIBER: return PK_FIBER; + case OBJ_CLASS: return PK_CLASS; + case OBJ_INST: return PK_INSTANCE; + } + + UNREACHABLE(); + return (PkVarType) -1; +} + +ObjectType getPkVarObjType(PkVarType type) { + switch (type) { + case PK_OBJECT: + case PK_NULL: + case PK_BOOL: + case PK_NUMBER: + UNREACHABLE(); + + case PK_STRING: return OBJ_STRING; + case PK_LIST: return OBJ_LIST; + case PK_MAP: return OBJ_MAP; + case PK_RANGE: return OBJ_RANGE; + case PK_MODULE: return OBJ_MODULE; + case PK_CLOSURE: return OBJ_CLOSURE; + case PK_FIBER: return OBJ_FIBER; + case PK_CLASS: return OBJ_CLASS; + case PK_INSTANCE: return OBJ_INST; + } + + UNREACHABLE(); + return (ObjectType) -1; +} + const char* getPkVarTypeName(PkVarType type) { switch (type) { + case PK_OBJECT: return "Object"; case PK_NULL: return "Null"; case PK_BOOL: return "Bool"; case PK_NUMBER: return "Number"; - case PK_STRING: return "String"; - case PK_LIST: return "List"; - case PK_MAP: return "Map"; - case PK_RANGE: return "Range"; - case PK_MODULE: return "Module"; - - // TODO: since functions are not first class citizens anymore, remove it - // and add closure (maybe with the same name PK_FUNCTION). - case PK_FUNCTION: return "Function"; - - case PK_FIBER: return "Fiber"; - case PK_CLASS: return "Class"; - case PK_INST: return "Inst"; + default: + return getObjectTypeName(getPkVarObjType(type)); } UNREACHABLE(); diff --git a/src/pk_value.h b/src/pk_value.h index 498f77e..ba2d24c 100644 --- a/src/pk_value.h +++ b/src/pk_value.h @@ -344,9 +344,8 @@ struct Function { // is prevent checking is_native everytime (which might be a bit faster). int upvalue_count; - // Docstring of the function, currently it's just the C string literal - // pointer, refactor this into String* so that we can support public - // native functions to provide a docstring. + // Docstring of the function. Could be either a C string literal or a string + // entry in it's owner module's constant pool. const char* docstring; // Function can be either native C function pointers or compiled pocket @@ -486,6 +485,10 @@ struct Class { // Name of the class. String* name; + // Docstring of the class. Could be either a C string literal or a string + // entry in it's owner module's constant pool. + const char* docstring; + Closure* ctor; //< The constructor function. pkUintBuffer field_names; //< Buffer of field names. // TODO: ordered names buffer for binary search. @@ -592,10 +595,6 @@ void markValue(PKVM* vm, Var self); // the garbage collection. void markVarBuffer(PKVM* vm, pkVarBuffer* self); -// Mark the elements of the buffer as reachable at the mark-and-sweep phase of -// the garbage collection. -void markStringBuffer(PKVM* vm, pkStringBuffer* self); - // Pop the marked objects from the working set of the VM and add it's // referenced objects to the working set, continue traversing and mark // all the reachable objects. @@ -724,6 +723,12 @@ Var doubleToVar(double value); // Internal method behind AS_NUM(value) don't use it directly. double varToDouble(Var value); +// Returns the PkVarType of the object type. +PkVarType getObjPkVarType(ObjectType type); + +// Returns the ObjectType of the PkVar type. +ObjectType getPkVarObjType(PkVarType type); + // Returns the type name of the PkVarType enum value. const char* getPkVarTypeName(PkVarType type); diff --git a/src/pk_vm.c b/src/pk_vm.c index c21b0b5..f92cd52 100644 --- a/src/pk_vm.c +++ b/src/pk_vm.c @@ -73,8 +73,8 @@ PKVM* pkNewVM(PkConfiguration* config) { // This is necessary to prevent garbage collection skip the entry in this // array while we're building it. - for (int i = 0; i < OBJ_INST; i++) { - vm->primitives[i] = NULL; + for (int i = 0; i < PK_INSTANCE; i++) { + vm->builtin_classes[i] = NULL; } initializeCore(vm); @@ -272,20 +272,16 @@ void vmCollectGarbage(PKVM* vm) { // Mark builtin functions. for (int i = 0; i < vm->builtins_count; i++) { - markObject(vm, &vm->builtins[i]->_super); + markObject(vm, &vm->builtins_funcs[i]->_super); } // Mark primitive types' classes. - for (int i = 0; i < (int)OBJ_INST; i++) { - // Upvalue and functions aren't first class objects and they doesn't - // require classes. - if (i == OBJ_UPVALUE || i == OBJ_FUNC) continue; - + for (int i = 0; i < PK_INSTANCE; i++) { // It's possible that a garbage collection could be triggered while we're // building the primitives and the class could be NULL. - if (vm->primitives[i] == NULL) continue; + if (vm->builtin_classes[i] == NULL) continue; - markObject(vm, &vm->primitives[i]->_super); + markObject(vm, &vm->builtin_classes[i]->_super); } // Mark the modules. @@ -970,7 +966,7 @@ L_vm_main_loop: { uint8_t index = READ_BYTE(); ASSERT_INDEX(index, vm->builtins_count); - Closure* closure = vm->builtins[index]; + Closure* closure = vm->builtins_funcs[index]; PUSH(VAR_OBJ(closure)); DISPATCH(); } diff --git a/src/pk_vm.h b/src/pk_vm.h index 4579b75..8b5bc4f 100644 --- a/src/pk_vm.h +++ b/src/pk_vm.h @@ -114,13 +114,13 @@ struct PKVM { Map* modules; // Array of all builtin functions. - Closure* builtins[BUILTIN_FN_CAPACITY]; + Closure* builtins_funcs[BUILTIN_FN_CAPACITY]; int builtins_count; // An array of all the primitive types' class except for OBJ_INST. Since the // type of the objects are enums starting from 0 we can directly get the // class by using their enum (ex: primitives[OBJ_LIST]). - Class* primitives[(int)OBJ_INST]; + Class* builtin_classes[PK_INSTANCE]; // Current fiber. Fiber* fiber;