309 lines
7.6 KiB
C
309 lines
7.6 KiB
C
/***********************************************************
|
|
** symbol_set - A public domain C modifier library
|
|
** by Allen Webster, "Mr. 4th", allenw@mr4th.com
|
|
**
|
|
** No warranty implied; use at your own risk
|
|
**
|
|
** Read README to get started.
|
|
*/
|
|
|
|
#ifndef SYMBOL_SET_H
|
|
#define SYMBOL_SET_H
|
|
|
|
/*********************
|
|
** Context Cracking **
|
|
*********************/
|
|
|
|
/* untangle compiler, os, & architecture */
|
|
#if defined(__clang__)
|
|
# define SY__COMPILER_CLANG 1
|
|
|
|
# if defined(_WIN32)
|
|
# define SY__OS_WINDOWS 1
|
|
# elif defined(__gnu_linux__)
|
|
# define SY__OS_LINUX 1
|
|
# elif defined(__APPLE__) && defined(__MACH__)
|
|
# define SY__OS_MAC 1
|
|
# else
|
|
# error missing OS detection
|
|
# endif
|
|
|
|
# if defined(__amd64__)
|
|
# define SY__ARCH_X64 1
|
|
# elif defined(__i386__)
|
|
# define SY__ARCH_X86 1
|
|
# elif defined(__arm__)
|
|
# define SY__ARCH_ARM 1
|
|
# elif defined(__aarch64__)
|
|
# define SY__ARCH_ARM64 1
|
|
# else
|
|
# error missing ARCH detection
|
|
# endif
|
|
|
|
#elif defined(_MSC_VER)
|
|
# define SY__COMPILER_CL 1
|
|
|
|
# if defined(_WIN32)
|
|
# define SY__OS_WINDOWS 1
|
|
# else
|
|
# error missing OS detection
|
|
# endif
|
|
|
|
# if defined(_M_AMD64)
|
|
# define SY__ARCH_X64 1
|
|
# elif defined(_M_I86)
|
|
# define SY__ARCH_X86 1
|
|
# elif defined(_M_ARM)
|
|
# define SY__ARCH_ARM 1
|
|
# else
|
|
# error missing ARCH detection
|
|
# endif
|
|
|
|
#elif defined(__GNUC__)
|
|
# define SY__COMPILER_GCC 1
|
|
|
|
# if defined(_WIN32)
|
|
# define SY__OS_WINDOWS 1
|
|
# elif defined(__gnu_linux__)
|
|
# define SY__OS_LINUX 1
|
|
# elif defined(__APPLE__) && defined(__MACH__)
|
|
# define SY__OS_MAC 1
|
|
# else
|
|
# error missing OS detection
|
|
# endif
|
|
|
|
# if defined(__amd64__)
|
|
# define SY__ARCH_X64 1
|
|
# elif defined(__i386__)
|
|
# define SY__ARCH_X86 1
|
|
# elif defined(__arm__)
|
|
# define SY__ARCH_ARM 1
|
|
# elif defined(__aarch64__)
|
|
# define SY__ARCH_ARM64 1
|
|
# else
|
|
# error missing ARCH detection
|
|
# endif
|
|
|
|
#else
|
|
# error no context cracking for this compiler
|
|
#endif
|
|
|
|
#if !defined(SY__COMPILER_CL)
|
|
# define SY__COMPILER_CL 0
|
|
#endif
|
|
#if !defined(SY__COMPILER_CLANG)
|
|
# define SY__COMPILER_CLANG 0
|
|
#endif
|
|
#if !defined(SY__COMPILER_GCC)
|
|
# define SY__COMPILER_GCC 0
|
|
#endif
|
|
#if !defined(SY__OS_WINDOWS)
|
|
# define SY__OS_WINDOWS 0
|
|
#endif
|
|
#if !defined(SY__OS_LINUX)
|
|
# define SY__OS_LINUX 0
|
|
#endif
|
|
#if !defined(SY__OS_MAC)
|
|
# define SY__OS_MAC 0
|
|
#endif
|
|
#if !defined(SY__ARCH_X64)
|
|
# define SY__ARCH_X64 0
|
|
#endif
|
|
#if !defined(SY__ARCH_X86)
|
|
# define SY__ARCH_X86 0
|
|
#endif
|
|
#if !defined(SY__ARCH_ARM)
|
|
# define SY__ARCH_ARM 0
|
|
#endif
|
|
#if !defined(SY__ARCH_ARM64)
|
|
# define SY__ARCH_ARM64 0
|
|
#endif
|
|
|
|
/* language */
|
|
#if defined(__cplusplus)
|
|
# define SY__LANG_CXX 1
|
|
#else
|
|
# define SY__LANG_C 1
|
|
#endif
|
|
|
|
#if !defined(SY__LANG_CXX)
|
|
# define SY__LANG_CXX 0
|
|
#endif
|
|
#if !defined(SY__LANG_C)
|
|
# define SY__LANG_C 0
|
|
#endif
|
|
|
|
/**********
|
|
** Types **
|
|
**********/
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef uint8_t Sy_U8;
|
|
typedef uint16_t Sy_U16;
|
|
typedef uint32_t Sy_U32;
|
|
typedef uint64_t Sy_U64;
|
|
|
|
#if SY__ARCH_X64 || SY__ARCH_ARM64
|
|
typedef Sy_U64 Sy_UAddress;
|
|
#else
|
|
typedef Sy_U32 Sy_UAddress;
|
|
#endif
|
|
|
|
/******************
|
|
** Macro Helpers **
|
|
******************/
|
|
|
|
#define SY__GLUE_(a,b) a##b
|
|
#define SY__GLUE(a,b) SY__GLUE_(a,b)
|
|
|
|
#define SY__STRIFY_(s) #s
|
|
#define SY__STRIFY(s) SY__STRIFY_(s)
|
|
|
|
/*****************
|
|
** Align Helper **
|
|
*****************/
|
|
|
|
#define SY__ALIGN_TO_POW2(x,a) (((x) + (a) - 1)&~((a) - 1))
|
|
|
|
/*******************
|
|
** Section Macros **
|
|
*******************/
|
|
|
|
/* IMPORTANT! On CL compiler add: #pragma section(<section>,read,write) */
|
|
|
|
#if SY__COMPILER_CLANG || SY__COMPILER_GCC
|
|
# if SY__OS_MAC
|
|
# define SY__SECTION_READONLY(N) __attribute__((__section__("__TEXT,"N))) const
|
|
# define SY__SECTION_READWRITE(N) __attribute__((__section__("__READ,"N)))
|
|
# else
|
|
# define SY__SECTION_READONLY(N) __attribute__((__section__(N))) const
|
|
# define SY__SECTION_READWRITE(N) __attribute__((__section__(N)))
|
|
# endif
|
|
#elif COMPILER_CL
|
|
# define SY__SECTION_READONLY(N) __declspec(allocate(N)) const
|
|
# define SY__SECTION_READWRITE(N) __declspec(allocate(N))
|
|
#else
|
|
# error SY__SECTION_* not defined for this compiler/OS
|
|
#endif
|
|
|
|
/****************************
|
|
** Do Not Mangle Qualifier **
|
|
****************************/
|
|
|
|
#if SY__LANG_CXX
|
|
# define SY__DO_NOT_MANGLE extern "C"
|
|
#else
|
|
# define SY__DO_NOT_MANGLE
|
|
#endif
|
|
|
|
/*******************************
|
|
** Do Not Eliminate Qualifier **
|
|
*******************************/
|
|
|
|
#if SY__OS_WINDOWS
|
|
# define SY__DO_NOT_ELIMINATE__S0(N) __pragma(comment(linker,"/include:" #N))
|
|
# define SY__DO_NOT_ELIMINATE__S1(N) DO_NOT_ELIMINATE__S0(N)
|
|
# define SY__DO_NOT_ELIMINATE(N) DO_NOT_ELIMINATE__S1(N)
|
|
#else
|
|
# define SY__DO_NOT_ELIMINATE(N)
|
|
#endif
|
|
|
|
/********************
|
|
** Align Qualifier **
|
|
********************/
|
|
|
|
#if SY__COMPILER_CL
|
|
# define SY__ALIGN_VAR(z) __declspec(align(z))
|
|
#elif SY__COMPILER_CLANG || SY__COMPILER_GCC
|
|
# define SY__ALIGN_VAR(z) __attribute__((__aligned__(z)))
|
|
#else
|
|
# error SY__ALIGN not defined for this compiler
|
|
#endif
|
|
|
|
/*****************
|
|
** Before Mains **
|
|
*****************/
|
|
|
|
#if SY__OS_WINDOWS
|
|
# pragma section(".CRT$XCU", read)
|
|
# define SY__BEFORE_MAIN__(n) \
|
|
static void n(void); \
|
|
SY__SECTIONREADWRITE(".CRT$XCU") \
|
|
SY__DO_NOT_ELIMINATE(n##__) \
|
|
SY__DO_NOT_MANGLE void (*n##__)(void); \
|
|
void (*n##__)(void) = n; \
|
|
static void n(void)
|
|
#elif SY__OS_LINUX
|
|
# define SY__BEFORE_MAIN__(n) __attribute__((constructor)) static void n(void)
|
|
#else
|
|
# error SY__BEFORE_MAIN__ missing for this OS
|
|
#endif
|
|
|
|
#define SY__BEFORE_MAIN_(n) SY__BEFORE_MAIN__(n)
|
|
#define SY__BEFORE_MAIN(n) SY__BEFORE_MAIN_(n)
|
|
|
|
/*************************************
|
|
** Symbol Set Programming Interface **
|
|
*************************************/
|
|
|
|
#define SyType(S) SY__GLUE(S,_Type)
|
|
|
|
#define SyDeclare(S,N) SY__ALIGN_VAR(8) SY__SECTION_READWRITE(S##_section) SyType(S) SY__SYMBOL(S,N)
|
|
#define SyDefine(S,N) SY__DO_NOT_ELIMINATE(SY__SYMBOL(S,N)) SyDeclare(S,N)
|
|
#define SyDefineUnnamed(S) SyDefine(S,SY__GLUE(unnamed,__COUNTER__))
|
|
|
|
#define SyAddress(S,N) (&SY__SYMBOL(S,N))
|
|
#define SyID(S,N) SyIDFromAddress_Unchecked(S,SyAddress(S,N))
|
|
#define SyFlag(S,N) (1llu << SyID(S,N))
|
|
|
|
#define SyStride(S) SY__ALIGN_TO_POW2(sizeof(SyType(S)), 8)
|
|
|
|
#if SY__OS_WINDOWS
|
|
# define SyFirst(S) SY__FIRST(S)
|
|
# define SyOpl(S) SY__OPL(S)
|
|
#elif SY__OS_LINUX
|
|
# define SyFirst(S) (&SY__FIRST(S))
|
|
# define SyOpl(S) (&SY__OPL(S))
|
|
#else
|
|
# error missing implementation set locator for this OS
|
|
#endif
|
|
|
|
#define SyCount(S) (((Sy_U8*)SyOpl(S) - (Sy_U8*)SyFirst(S))/SyStride(S))
|
|
#define SyNext(S,addr) (SyType(S)*)((Sy_U8*)addr + SyStride(S))
|
|
|
|
#define SyEach(S,var) SyType(S)*var=SyFirst(S); var<SyOpl(S); var=SyNext(S,var)
|
|
|
|
#define SyIDFromAddress(S,addr) (SyAddressCheck(S,addr)?SyIDFromAddress_Unchecked(S,addr):0)
|
|
#define SyAddressFromID(S,id) (SyIDCheck(S,id)?SyAddressFromID_Unchecked(S,id):0)
|
|
|
|
#define SyAddressCheck(S,addr) (SyFirst(S) <= (addr) && (addr) <= SyOpl(S))
|
|
#define SyIDCheck(S,id) (1 <= (id) && (id) <= SyCount(S))
|
|
|
|
#define SyIDFromAddress_Unchecked(S,addr) ((Sy_U32)(1 + ((Sy_U8*)(addr) - (Sy_U8*)SyFirst(S))/SyStride(S)))
|
|
#define SyAddressFromID_Unchecked(S,id) ((SyType(S)*)((Sy_U8*)SyFirst(S) + ((id) - 1)*SyStride(S)))
|
|
|
|
#define SyRaw(S,N) (Sy_UAddress)(SyAddress(S,N))
|
|
#define SyIDFromRaw(S,raw) SyIDFromAddress(S,(SyType(S)*)(raw))
|
|
#define SyIDFromRaw_Unchecked(S,raw) SyIDFromAddress_Unchecked(S,(SyType(S)*)(raw))
|
|
|
|
|
|
/*************
|
|
** Internal **
|
|
*************/
|
|
|
|
#define SY__SYMBOL(S,N) SY__GLUE(S,SY__GLUE(__,N))
|
|
|
|
#define SY__FIRST_(S) SY__GLUE(syfirst__, S##_marker)
|
|
#define SY__OPL_(S) SY__GLUE(syopl__, S##_marker)
|
|
|
|
#define SY__FIRST(S) SY__FIRST_(S)
|
|
#define SY__OPL(S) SY__OPL_(S)
|
|
|
|
#if SY__OS_WINDOWS
|
|
void sy__section_init(char *name, Sy_U32 name_size, void **first_out, void **opl_out);
|
|
#endif
|
|
|
|
#endif /* SYMBOL_SET_H */
|
|
|