c-scripting/symbol_set/symbol_set.h

213 lines
6.3 KiB
C

#if !defined(SY__H)
#define SY__H
#include "symbol_set.base.h"
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~ Copy-Pastable Setup ~~~~~~~~~~~~~~~~~~~~~~~~~
~~ To define a Symbol Set:
~~ copy the code below
~~ replace ZZZ: to name the symbol set
~~ replace Typezz: to set the type of the symbol set
~~ replace secz: to name of the data section of the symbol set
~~ pick and complete the sections with "..."s
*/
#if 0
#define SYMBOL_SET_DEFINE ZZZ
#define ZZZ_Type Typezz
#define ZZZ_section ".sy.secz"
#define ZZZ_marker secz
#include "symbol_set.define.h"
// basic struct def with a name
#define ZZZ_DEF(N,...) SyDefine(ZZZ, N) = { ... }
// def with attached function body
// replace funczz: to prefix namespace unique functions
// fill ... sections appropriately
#define ZZZ_DEF(N,...) \
static void funczz##N(void*); \
SyDefine(ZZZ, N) = { funczz##N, ... }; \
static void funczz##N(void *ptr)
// nameless def
#define ZZZ_DEF(...) SyDefineUnnamed(ZZZ) = { ... }
#endif
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~ Loop Boilerplates ~~~~~~~~~~~~~~~~~*/
#if 0
{
for (SyEach(ZZZ, zzz_ptr)){
zzz_ptr->
}
}
{
for (SyEachID(ZZZ, zzz_id)){
[zzz_id]
}
}
#endif
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~ User Primitives ~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#define SyType(S) SY__GLUE(S,_Type)
#define SyDeclare(S,N) SY__ALIGN_AS_LIT(8) SY__SEC_RW(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 SyRaw(S,N) (SY__UAddr)(SyAddress(S,N))
#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 SyStride(S) SY__ROUND_UP_POW2(sizeof(SyType(S)), 8)
#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 SyEachID(S,var) SY__U32 var=1; var<=SyCount(S); var+=1
#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 SyIDFromRaw(S,raw) SyIDFromAddress(S,(SyType(S)*)(raw))
#define SyIDFromRaw_Unchecked(S,raw) SyIDFromAddress_Unchecked(S,(SyType(S)*)(raw))
#define SyFlag(S,N) (1llu << (SyID(S,N) - 1))
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~ 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
// I dropped this here so that if you copy paste any of the
// above and forget to replace Typezz, you'll get auto-int like
// behavior from your error messages.
#define Typezz int
#endif //SY__H
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~ Function Definitions ~~~~~~~~~~~~~~~~~~~~~~~~~*/
#if SY__MAIN && SY__OS_WINDOWS && !defined(SY__MAIN_DEFINITIONS)
#define SY__MAIN_DEFINITIONS 1
#define SY__PE_MSDOS_MAGIC 0x5A4D
struct SY__PE_DosHeader{
SY__U16 magic;
SY__U16 last_page_size;
SY__U16 page_count;
SY__U16 reloc_count;
SY__U16 paragraph_header_size;
SY__U16 min_paragraph;
SY__U16 max_paragraph;
SY__U16 init_ss;
SY__U16 init_sp;
SY__U16 checksum;
SY__U16 init_ip;
SY__U16 init_cs;
SY__U16 reloc_table_file_off;
SY__U16 overlay_number;
SY__U16 reserved[4];
SY__U16 oem_id;
SY__U16 oem_info;
SY__U16 reserved2[10];
SY__U32 coff_file_offset;
};
#define SY__PE_SIGNATURE 0x00004550
struct SY__PE_CoffHeader{
SY__U16 machine_type;
SY__U16 section_count;
SY__U32 time_stamp;
SY__U32 symbol_table_foff;
SY__U32 symbol_count;
SY__U16 optional_header_size;
SY__U16 flags;
};
struct SY__PE_SectionHeader{
SY__U8 name[8];
SY__U32 vsize;
SY__U32 voff;
SY__U32 fsize;
SY__U32 foff;
SY__U32 relocations_foff;
SY__U32 line_numbers_foff;
SY__U16 relocation_count;
SY__U16 line_number_count;
SY__U32 flags;
};
void
sy__section_init(char *name, SY__U32 name_size,
void **first_out, void **opl_out){
if (name_size <= 8){
extern SY__U8 __ImageBase[];
SY__U8 *base = __ImageBase;
struct SY__PE_DosHeader *dos = (struct SY__PE_DosHeader*)base;
if (dos->magic == SY__PE_MSDOS_MAGIC){
SY__U32 *pe_signature = (SY__U32*)(base + dos->coff_file_offset);
if (*pe_signature == SY__PE_SIGNATURE){
struct SY__PE_CoffHeader *coff = (struct SY__PE_CoffHeader*)(pe_signature + 1);
SY__U32 sections_offset = (dos->coff_file_offset + sizeof(*pe_signature) +
sizeof(*coff) + coff->optional_header_size);
SY__U32 section_count = coff->section_count;
struct SY__PE_SectionHeader*
section = (struct SY__PE_SectionHeader*)(base + sections_offset);
for (SY__U32 i = 0; i < section_count; i += 1, section += 1){
SY__B32 match = 1;
for (SY__U32 j = 0; j < 8; j += 1){
if (name[j] != section->name[j]){
match = 0;
break;
}
if (name[j] == 0){
break;
}
}
if (match){
*first_out = base + section->voff;
*opl_out = base + section->voff + section->vsize;
break;
}
}
}
}
}
}
#endif //SY__MAIN_DEFINITIONS