c-scripting/symbol_set.h

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 */