diff --git a/_mirror b/_mirror index 15f0baf..a23d27f 160000 --- a/_mirror +++ b/_mirror @@ -1 +1 @@ -Subproject commit 15f0bafa8d6b428bea1a0931861e891e8d6017e7 +Subproject commit a23d27f206b89c4971803fdc74ac0d3a7b65217a diff --git a/bind/v4k.lua b/bind/v4k.lua index 471dea0..dadfbf0 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -2457,8 +2457,9 @@ const char *type; void struct_inscribe(const char *T,unsigned Tid,unsigned Tsz,unsigned OBJTYPEid, const char *infos); void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, const char *infos, const char *type); void function_inscribe(const char *F,unsigned Fid,void *func,const char *infos); - void reflected_printf(reflect_t *r); - void reflected_printf_all(); + void reflect_print(const char *symbol); + void reflect_dump(const char *mask); + void reflect_init(); typedef unsigned handle; unsigned rgba( uint8_t r, uint8_t g, uint8_t b, uint8_t a ); unsigned bgra( uint8_t b, uint8_t g, uint8_t r, uint8_t a ); diff --git a/demos/99-cart.c b/demos/99-cart.c new file mode 100644 index 0000000..41c5f91 --- /dev/null +++ b/demos/99-cart.c @@ -0,0 +1,47 @@ +// hello ui: config, window, system, ui, video +// - rlyeh, public domain. +// +// Compile with: +// `make demos\01-ui.c` (windows) +// `sh MAKE.bat demos/01-ui.c` (linux, osx) + +#include "v4k.h" + +int main() { + window_create(80, 0); + window_title(__FILE__); + + camera_t cam = camera(); + + vec3 route[] = { + vec3(0.0f, 0.0f, 5.0f), + vec3(0.0f, 0.0f, 10.0f), + vec3(0.0f, 2.0f, 20.0f), + vec3(0.0f, 8.0f, 30.0f), + vec3(0.0f, 12.0f, 40.0f), + vec3(0.0f, 0.0f, 80.0f), + }; + + #define route_len (sizeof route / sizeof route[0]) + + // app loop + while( window_swap() ) { + // input controls + if( input(KEY_ESC) ) break; + + // fps camera + bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R); + if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f); + vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active); + vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed); + camera_moveby(&cam, wasdecq); + camera_fps(&cam, mouse.x,mouse.y); + window_cursor( !active ); + + ddraw_ground(0); + + for (int i = 0; i < route_len; i++) { + + } + } +} diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 0dee92c..084f552 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -14241,6 +14241,22 @@ extern "C" { #define EXPAND_ARGS(args) EXPAND_RETURN_COUNT args ///- #define EXPAND_RETURN_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, count, ...) count ///- +// expands to the first argument +#define VA_FIRST(...) VA_F1RST(__VA_ARGS__, throwaway) +#define VA_F1RST(first, ...) first ///- +// if there's only one argument, expands to nothing. if there is more +// than one argument, expands to a comma followed by everything but +// the first argument. only supports up to 9 arguments but can be expanded. +#define VA_REST(...) VA_R3ST(VA_NUM(__VA_ARGS__), __VA_ARGS__) +#define VA_R3ST(qty, ...) VA_R3S7(qty, __VA_ARGS__) ///- +#define VA_R3S7(qty, ...) VA_R3S7_##qty(__VA_ARGS__) ///- +#define VA_R3S7_ONE(first) ///- +#define VA_R3S7_TWOORMORE(first, ...) , __VA_ARGS__ ///- +#define VA_NUM(...) VA_SELECT_10TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) ///- +#define VA_SELECT_10TH(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, ...) A10 +// VA_SPLIT() expands to A) 1 item OR B) 1 item + ',' + va_args[1..N] +#define VA_SPLIT(...) VA_FIRST(__VA_ARGS__) VA_REST(__VA_ARGS__) + #if is(cl) && !is(cpp) #define INLINE __inline #else @@ -14265,6 +14281,21 @@ extern "C" { // typedef union vec2 { float X,Y; }; vec2 a = {0,1}, b = vec2(0,1); #define C_CAST(type, ...) ( ifdef(c,(type),type) { __VA_ARGS__ } ) +// create a WARNING(...) macro +// usage: WARNING("this is displayed at compile time") +#if is(gcc) +# define WARNING(msg) WARN1NG( message( msg ) ) +# define WARN1NG(msg) _Pragma(#msg) +#elif is(cl) +# define WARNING(msg) __pragma( message( msg ) ) +#else +# define WARNING(msg) +#endif + +// document todos and fixmes via compiler warnings +#define TODO(str) ifdef(debug,WARNING("TO DO: " str " (" FILELINE ")")) +#define FIXME(str) ifdef(debug,WARNING("FIXME: " str " (" FILELINE ")")) + // ----------------------------------------------------------------------------- // autorun initializers for C // - rlyeh, public domain @@ -14273,29 +14304,25 @@ extern "C" { // note: XIU for C initializers, XCU for C++ initializers, XTU for C deinitializers #ifdef __cplusplus -#define AUTORUN \ - static void AUTORUN_U(f)(void); \ - static const int AUTORUN_J(AUTORUN_U(f),__1) = (AUTORUN_U(f)(), 1); \ - static void AUTORUN_U(f)(void) +#define AUTORUN_(fn) \ + static void fn(void); \ + static const int concat(fn,__1) = (fn(), 1); \ + static void fn(void) #elif defined _MSC_VER && !defined(__clang__) // cl, but not clang-cl -#define AUTORUN \ - static void AUTORUN_U(f)(void); \ - static int AUTORUN_J(AUTORUN_U(f),__1) (){ AUTORUN_U(f)(); return 0; } \ +#define AUTORUN_(fn) \ + static void fn(void); \ + static int concat(fn,__1) (){ fn(); return 0; } \ __pragma(section(".CRT$XIU", long, read)) \ __declspec(allocate(".CRT$XIU")) \ - static int(* AUTORUN_J(AUTORUN_U(f),__2) )() = AUTORUN_J(AUTORUN_U(f),__1); \ - static void AUTORUN_U(f)(void) + static int(* concat(fn,__2) )() = concat(fn,__1); \ + static void fn(void) #else // gcc,tcc,clang,clang-cl... -#define AUTORUN \ +#define AUTORUN_(fn) \ __attribute__((constructor)) \ - static void AUTORUN_U(f)(void) + static void fn(void) #endif -// join + unique macro utils - -#define AUTORUN_j(a, b) a##b -#define AUTORUN_J(a, b) AUTORUN_j(a, b) -#define AUTORUN_U(x) AUTORUN_J(x, __LINE__) +#define AUTORUN AUTORUN_( concat(concat(concat(fn_L,__LINE__),_),__COUNTER__) ) #if 0 // autorun demo void byebye(void) { puts("seen after main()"); } @@ -16577,8 +16604,8 @@ extern API int profiler_enabled; ///- // @todo: nested structs? pointers in members? // @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/) -#ifndef ifdef_objapi -#define ifdef_objapi(T,...) __VA_ARGS__ +#ifndef OBJTYPE +#define OBJTYPE(T) 0 #endif typedef struct reflect_t { @@ -16600,7 +16627,7 @@ typedef struct reflect_t { function_inscribe(#F,intern(#F),(void*)F, function_annotations) #define STRUCT(T, type, member, member_annotations) \ - struct_inscribe(#T,intern(#T),sizeof(T),ifdef(objapi,OBJTYPE_##T,0),NULL), \ + struct_inscribe(#T,intern(#T),sizeof(T),OBJTYPE(T),NULL), \ type_inscribe(#type,intern(#type),sizeof(((T){0}).member),member_annotations), \ member_inscribe(intern(#T), #member,intern(#member),(uintptr_t)&((T*)0)->member, member_annotations, #type ) @@ -16628,8 +16655,9 @@ API void struct_inscribe(const char *T,unsigned Tid,unsigned Tsz,u API void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, const char *infos, const char *type); API void function_inscribe(const char *F,unsigned Fid,void *func,const char *infos); -API void reflected_printf(reflect_t *r); -API void reflected_printf_all(); +API void reflect_print(const char *symbol); +API void reflect_dump(const char *mask); +API void reflect_init(); #line 0 #line 1 "engine/split/v4k_render.h" @@ -331987,9 +332015,9 @@ const struct in6_addr in6addr_loopback; /* ::1 */ #define chdir ifdef(cl, _chdir, chdir) #if is(cl) || is(tcc) #define ftruncate _chsize_s -#define flockfile ifdef(cl,_lock_file,(void)) -#define funlockfile ifdef(cl,_unlock_file,(void)) #endif +#define flockfile ifdef(cl,_lock_file,ifdef(mingw,_lock_file,(void))) +#define funlockfile ifdef(cl,_unlock_file,ifdef(mingw,_unlock_file,(void))) #else // gcc //#include // mingw64 does not have it #include // strncasecmp @@ -343824,42 +343852,40 @@ AUTORUN { static map(unsigned, reflect_t) reflects; static map(unsigned, array(reflect_t)) members; -void reflected_printf(reflect_t *r) { - printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s", - r->name ? r->name : "", r->info ? r->info : "", r->id, r->objtype, r->sz, r->addr, r->parent, r->type ? r->type : ""); -} -void reflected_printf_all() { - for each_map_ptr(reflects, unsigned, k, reflect_t, p) { - reflected_printf(p); - puts(""); +void reflect_init() { + if(!reflects) map_init_int(reflects); } +AUTORUN { + reflect_init(); } void type_inscribe(const char *TY,unsigned TYid,unsigned TYsz,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, TYid, ((reflect_t){TYid, 0, TYsz, TY, infos})); } void enum_inscribe(const char *E,unsigned Eid,unsigned Eval,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Eid, ((reflect_t){Eid,0, Eval, E,infos})); } unsigned enum_find(const char *E) { + reflect_init(); return map_find(reflects, intern(E))->sz; } void function_inscribe(const char *F,unsigned Fid,void *func,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Fid, ((reflect_t){Fid,0, 0, F,infos, func})); reflect_t *found = map_find(reflects,Fid); } void *function_find(const char *F) { + reflect_init(); return map_find(reflects, intern(F))->addr; } void struct_inscribe(const char *T,unsigned Tid,unsigned Tsz,unsigned OBJTYPEid, const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Tid, ((reflect_t){Tid, OBJTYPEid, Tsz, T, infos})); } void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, const char *infos, const char *type) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, (Mid<<16)|Tid, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type })); // add member separately as well if(!members) map_init_int(members); @@ -343867,15 +343893,52 @@ void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, cons array_push(*found, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type })); } reflect_t member_find(const char *T, const char *M) { + reflect_init(); return *map_find(reflects, (intern(M)<<16)|intern(T)); } void *member_findptr(void *obj, const char *T, const char *M) { + reflect_init(); return (char*)obj + member_find(T,M).sz; } array(reflect_t) members_find(const char *T) { + reflect_init(); return *map_find(members, intern(T)); } + +void reflect_dump(const char *mask) { + for each_map_ptr(reflects, unsigned, k, reflect_t, R) { + if( strmatchi(R->name, mask)) + printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n", + R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : ""); + } +} + +void reflect_print_(const reflect_t *R) { + static __thread int tabs = 0; + printf("%*.s", 4 * (tabs++), ""); + unsigned symbol_q = intern(R->name); + { + array(reflect_t) *RR = map_find(members, symbol_q); + /**/ if( RR ) { printf("struct %s: %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : ""); for each_array_ptr(*RR, reflect_t, it) reflect_print_(it); } + else if( R->addr ) printf("func %s(); %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : ""); + else if( !R->parent ) printf("enum %s = %d; %s%s\n", R->name, R->sz, R->info ? "// ":"", R->info ? R->info : ""); + else printf("%s %s; %s%s\n", R->type, R->name, R->info ? "// ":"", R->info ? R->info : ""); +/* + ifdef(debug, + printf("%.*sname:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n", + tabs, "", R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : ""); + ); +*/ + } + --tabs; +} + +void reflect_print(const char *symbol) { + reflect_t *found = map_find(reflects, intern(symbol)); + if( found ) reflect_print_(found); +} + // -- tests enum { @@ -343889,7 +343952,7 @@ typedef struct MyVec4 { float x,y,z,w; } MyVec4; -ifdef(objapi, enum { OBJTYPE_MyVec4 = 0x100 }); +enum { OBJTYPE_MyVec4 = 0x01 }; AUTOTEST { // register structs, enums and functions @@ -343922,7 +343985,11 @@ AUTOTEST { // printf("+%s MyVec4.%s // %s\n", R->type, R->name, R->info); } - // reflected_printf_all(); + // reflect_print("puts"); + // reflect_print("MYVALUE0"); + // reflect_print("MyVec4"); + + // reflect_dump("*"); } #line 0 diff --git a/engine/split/v4k_compat.c b/engine/split/v4k_compat.c index dd31130..3fe3c90 100644 --- a/engine/split/v4k_compat.c +++ b/engine/split/v4k_compat.c @@ -31,9 +31,9 @@ const struct in6_addr in6addr_loopback; /* ::1 */ #define chdir ifdef(cl, _chdir, chdir) #if is(cl) || is(tcc) #define ftruncate _chsize_s -#define flockfile ifdef(cl,_lock_file,(void)) -#define funlockfile ifdef(cl,_unlock_file,(void)) #endif +#define flockfile ifdef(cl,_lock_file,ifdef(mingw,_lock_file,(void))) +#define funlockfile ifdef(cl,_unlock_file,ifdef(mingw,_unlock_file,(void))) #else // gcc //#include // mingw64 does not have it #include // strncasecmp diff --git a/engine/split/v4k_config.h b/engine/split/v4k_config.h index 232208e..1c7f0c0 100644 --- a/engine/split/v4k_config.h +++ b/engine/split/v4k_config.h @@ -210,6 +210,22 @@ #define EXPAND_ARGS(args) EXPAND_RETURN_COUNT args ///- #define EXPAND_RETURN_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, count, ...) count ///- +// expands to the first argument +#define VA_FIRST(...) VA_F1RST(__VA_ARGS__, throwaway) +#define VA_F1RST(first, ...) first ///- +// if there's only one argument, expands to nothing. if there is more +// than one argument, expands to a comma followed by everything but +// the first argument. only supports up to 9 arguments but can be expanded. +#define VA_REST(...) VA_R3ST(VA_NUM(__VA_ARGS__), __VA_ARGS__) +#define VA_R3ST(qty, ...) VA_R3S7(qty, __VA_ARGS__) ///- +#define VA_R3S7(qty, ...) VA_R3S7_##qty(__VA_ARGS__) ///- +#define VA_R3S7_ONE(first) ///- +#define VA_R3S7_TWOORMORE(first, ...) , __VA_ARGS__ ///- +#define VA_NUM(...) VA_SELECT_10TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) ///- +#define VA_SELECT_10TH(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, ...) A10 +// VA_SPLIT() expands to A) 1 item OR B) 1 item + ',' + va_args[1..N] +#define VA_SPLIT(...) VA_FIRST(__VA_ARGS__) VA_REST(__VA_ARGS__) + #if is(cl) && !is(cpp) #define INLINE __inline #else @@ -234,6 +250,21 @@ // typedef union vec2 { float X,Y; }; vec2 a = {0,1}, b = vec2(0,1); #define C_CAST(type, ...) ( ifdef(c,(type),type) { __VA_ARGS__ } ) +// create a WARNING(...) macro +// usage: WARNING("this is displayed at compile time") +#if is(gcc) +# define WARNING(msg) WARN1NG( message( msg ) ) +# define WARN1NG(msg) _Pragma(#msg) +#elif is(cl) +# define WARNING(msg) __pragma( message( msg ) ) +#else +# define WARNING(msg) +#endif + +// document todos and fixmes via compiler warnings +#define TODO(str) ifdef(debug,WARNING("TO DO: " str " (" FILELINE ")")) +#define FIXME(str) ifdef(debug,WARNING("FIXME: " str " (" FILELINE ")")) + // ----------------------------------------------------------------------------- // autorun initializers for C // - rlyeh, public domain @@ -242,29 +273,25 @@ // note: XIU for C initializers, XCU for C++ initializers, XTU for C deinitializers #ifdef __cplusplus -#define AUTORUN \ - static void AUTORUN_U(f)(void); \ - static const int AUTORUN_J(AUTORUN_U(f),__1) = (AUTORUN_U(f)(), 1); \ - static void AUTORUN_U(f)(void) +#define AUTORUN_(fn) \ + static void fn(void); \ + static const int concat(fn,__1) = (fn(), 1); \ + static void fn(void) #elif defined _MSC_VER && !defined(__clang__) // cl, but not clang-cl -#define AUTORUN \ - static void AUTORUN_U(f)(void); \ - static int AUTORUN_J(AUTORUN_U(f),__1) (){ AUTORUN_U(f)(); return 0; } \ +#define AUTORUN_(fn) \ + static void fn(void); \ + static int concat(fn,__1) (){ fn(); return 0; } \ __pragma(section(".CRT$XIU", long, read)) \ __declspec(allocate(".CRT$XIU")) \ - static int(* AUTORUN_J(AUTORUN_U(f),__2) )() = AUTORUN_J(AUTORUN_U(f),__1); \ - static void AUTORUN_U(f)(void) + static int(* concat(fn,__2) )() = concat(fn,__1); \ + static void fn(void) #else // gcc,tcc,clang,clang-cl... -#define AUTORUN \ +#define AUTORUN_(fn) \ __attribute__((constructor)) \ - static void AUTORUN_U(f)(void) + static void fn(void) #endif -// join + unique macro utils - -#define AUTORUN_j(a, b) a##b -#define AUTORUN_J(a, b) AUTORUN_j(a, b) -#define AUTORUN_U(x) AUTORUN_J(x, __LINE__) +#define AUTORUN AUTORUN_( concat(concat(concat(fn_L,__LINE__),_),__COUNTER__) ) #if 0 // autorun demo void byebye(void) { puts("seen after main()"); } diff --git a/engine/split/v4k_reflect.c b/engine/split/v4k_reflect.c index c8e5db1..c74aeaa 100644 --- a/engine/split/v4k_reflect.c +++ b/engine/split/v4k_reflect.c @@ -7,42 +7,40 @@ static map(unsigned, reflect_t) reflects; static map(unsigned, array(reflect_t)) members; -void reflected_printf(reflect_t *r) { - printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s", - r->name ? r->name : "", r->info ? r->info : "", r->id, r->objtype, r->sz, r->addr, r->parent, r->type ? r->type : ""); -} -void reflected_printf_all() { - for each_map_ptr(reflects, unsigned, k, reflect_t, p) { - reflected_printf(p); - puts(""); +void reflect_init() { + if(!reflects) map_init_int(reflects); } +AUTORUN { + reflect_init(); } void type_inscribe(const char *TY,unsigned TYid,unsigned TYsz,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, TYid, ((reflect_t){TYid, 0, TYsz, TY, infos})); } void enum_inscribe(const char *E,unsigned Eid,unsigned Eval,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Eid, ((reflect_t){Eid,0, Eval, E,infos})); } unsigned enum_find(const char *E) { + reflect_init(); return map_find(reflects, intern(E))->sz; } void function_inscribe(const char *F,unsigned Fid,void *func,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Fid, ((reflect_t){Fid,0, 0, F,infos, func})); reflect_t *found = map_find(reflects,Fid); } void *function_find(const char *F) { + reflect_init(); return map_find(reflects, intern(F))->addr; } void struct_inscribe(const char *T,unsigned Tid,unsigned Tsz,unsigned OBJTYPEid, const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Tid, ((reflect_t){Tid, OBJTYPEid, Tsz, T, infos})); } void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, const char *infos, const char *type) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, (Mid<<16)|Tid, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type })); // add member separately as well if(!members) map_init_int(members); @@ -50,15 +48,52 @@ void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, cons array_push(*found, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type })); } reflect_t member_find(const char *T, const char *M) { + reflect_init(); return *map_find(reflects, (intern(M)<<16)|intern(T)); } void *member_findptr(void *obj, const char *T, const char *M) { + reflect_init(); return (char*)obj + member_find(T,M).sz; } array(reflect_t) members_find(const char *T) { + reflect_init(); return *map_find(members, intern(T)); } + +void reflect_dump(const char *mask) { + for each_map_ptr(reflects, unsigned, k, reflect_t, R) { + if( strmatchi(R->name, mask)) + printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n", + R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : ""); + } +} + +void reflect_print_(const reflect_t *R) { + static __thread int tabs = 0; + printf("%*.s", 4 * (tabs++), ""); + unsigned symbol_q = intern(R->name); + { + array(reflect_t) *RR = map_find(members, symbol_q); + /**/ if( RR ) { printf("struct %s: %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : ""); for each_array_ptr(*RR, reflect_t, it) reflect_print_(it); } + else if( R->addr ) printf("func %s(); %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : ""); + else if( !R->parent ) printf("enum %s = %d; %s%s\n", R->name, R->sz, R->info ? "// ":"", R->info ? R->info : ""); + else printf("%s %s; %s%s\n", R->type, R->name, R->info ? "// ":"", R->info ? R->info : ""); +/* + ifdef(debug, + printf("%.*sname:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n", + tabs, "", R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : ""); + ); +*/ + } + --tabs; +} + +void reflect_print(const char *symbol) { + reflect_t *found = map_find(reflects, intern(symbol)); + if( found ) reflect_print_(found); +} + // -- tests enum { @@ -72,7 +107,7 @@ typedef struct MyVec4 { float x,y,z,w; } MyVec4; -ifdef(objapi, enum { OBJTYPE_MyVec4 = 0x100 }); +enum { OBJTYPE_MyVec4 = 0x01 }; AUTOTEST { // register structs, enums and functions @@ -105,5 +140,9 @@ AUTOTEST { // printf("+%s MyVec4.%s // %s\n", R->type, R->name, R->info); } - // reflected_printf_all(); + // reflect_print("puts"); + // reflect_print("MYVALUE0"); + // reflect_print("MyVec4"); + + // reflect_dump("*"); } diff --git a/engine/split/v4k_reflect.h b/engine/split/v4k_reflect.h index eda5c8c..b4fb77a 100644 --- a/engine/split/v4k_reflect.h +++ b/engine/split/v4k_reflect.h @@ -4,8 +4,8 @@ // @todo: nested structs? pointers in members? // @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/) -#ifndef ifdef_objapi -#define ifdef_objapi(T,...) __VA_ARGS__ +#ifndef OBJTYPE +#define OBJTYPE(T) 0 #endif typedef struct reflect_t { @@ -27,7 +27,7 @@ typedef struct reflect_t { function_inscribe(#F,intern(#F),(void*)F, function_annotations) #define STRUCT(T, type, member, member_annotations) \ - struct_inscribe(#T,intern(#T),sizeof(T),ifdef(objapi,OBJTYPE_##T,0),NULL), \ + struct_inscribe(#T,intern(#T),sizeof(T),OBJTYPE(T),NULL), \ type_inscribe(#type,intern(#type),sizeof(((T){0}).member),member_annotations), \ member_inscribe(intern(#T), #member,intern(#member),(uintptr_t)&((T*)0)->member, member_annotations, #type ) @@ -55,5 +55,6 @@ API void struct_inscribe(const char *T,unsigned Tid,unsigned Tsz,u API void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, const char *infos, const char *type); API void function_inscribe(const char *F,unsigned Fid,void *func,const char *infos); -API void reflected_printf(reflect_t *r); -API void reflected_printf_all(); +API void reflect_print(const char *symbol); +API void reflect_dump(const char *mask); +API void reflect_init(); diff --git a/engine/v4k.c b/engine/v4k.c index 2406b17..27d2ff1 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -947,9 +947,9 @@ const struct in6_addr in6addr_loopback; /* ::1 */ #define chdir ifdef(cl, _chdir, chdir) #if is(cl) || is(tcc) #define ftruncate _chsize_s -#define flockfile ifdef(cl,_lock_file,(void)) -#define funlockfile ifdef(cl,_unlock_file,(void)) #endif +#define flockfile ifdef(cl,_lock_file,ifdef(mingw,_lock_file,(void))) +#define funlockfile ifdef(cl,_unlock_file,ifdef(mingw,_unlock_file,(void))) #else // gcc //#include // mingw64 does not have it #include // strncasecmp @@ -12784,42 +12784,40 @@ AUTORUN { static map(unsigned, reflect_t) reflects; static map(unsigned, array(reflect_t)) members; -void reflected_printf(reflect_t *r) { - printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s", - r->name ? r->name : "", r->info ? r->info : "", r->id, r->objtype, r->sz, r->addr, r->parent, r->type ? r->type : ""); -} -void reflected_printf_all() { - for each_map_ptr(reflects, unsigned, k, reflect_t, p) { - reflected_printf(p); - puts(""); +void reflect_init() { + if(!reflects) map_init_int(reflects); } +AUTORUN { + reflect_init(); } void type_inscribe(const char *TY,unsigned TYid,unsigned TYsz,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, TYid, ((reflect_t){TYid, 0, TYsz, TY, infos})); } void enum_inscribe(const char *E,unsigned Eid,unsigned Eval,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Eid, ((reflect_t){Eid,0, Eval, E,infos})); } unsigned enum_find(const char *E) { + reflect_init(); return map_find(reflects, intern(E))->sz; } void function_inscribe(const char *F,unsigned Fid,void *func,const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Fid, ((reflect_t){Fid,0, 0, F,infos, func})); reflect_t *found = map_find(reflects,Fid); } void *function_find(const char *F) { + reflect_init(); return map_find(reflects, intern(F))->addr; } void struct_inscribe(const char *T,unsigned Tid,unsigned Tsz,unsigned OBJTYPEid, const char *infos) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, Tid, ((reflect_t){Tid, OBJTYPEid, Tsz, T, infos})); } void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, const char *infos, const char *type) { - if(!reflects) map_init_int(reflects); + reflect_init(); map_find_or_add(reflects, (Mid<<16)|Tid, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type })); // add member separately as well if(!members) map_init_int(members); @@ -12827,15 +12825,52 @@ void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, cons array_push(*found, ((reflect_t){Mid, 0, Msz, M, infos, NULL, Tid, type })); } reflect_t member_find(const char *T, const char *M) { + reflect_init(); return *map_find(reflects, (intern(M)<<16)|intern(T)); } void *member_findptr(void *obj, const char *T, const char *M) { + reflect_init(); return (char*)obj + member_find(T,M).sz; } array(reflect_t) members_find(const char *T) { + reflect_init(); return *map_find(members, intern(T)); } + +void reflect_dump(const char *mask) { + for each_map_ptr(reflects, unsigned, k, reflect_t, R) { + if( strmatchi(R->name, mask)) + printf("name:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n", + R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : ""); + } +} + +void reflect_print_(const reflect_t *R) { + static __thread int tabs = 0; + printf("%*.s", 4 * (tabs++), ""); + unsigned symbol_q = intern(R->name); + { + array(reflect_t) *RR = map_find(members, symbol_q); + /**/ if( RR ) { printf("struct %s: %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : ""); for each_array_ptr(*RR, reflect_t, it) reflect_print_(it); } + else if( R->addr ) printf("func %s(); %s%s\n", R->name, R->info ? "// ":"", R->info ? R->info : ""); + else if( !R->parent ) printf("enum %s = %d; %s%s\n", R->name, R->sz, R->info ? "// ":"", R->info ? R->info : ""); + else printf("%s %s; %s%s\n", R->type, R->name, R->info ? "// ":"", R->info ? R->info : ""); +/* + ifdef(debug, + printf("%.*sname:%s info:'%s' id:%u objtype:%u sz:%u addr:%p parent:%u type:%s\n", + tabs, "", R->name ? R->name : "", R->info ? R->info : "", R->id, R->objtype, R->sz, R->addr, R->parent, R->type ? R->type : ""); + ); +*/ + } + --tabs; +} + +void reflect_print(const char *symbol) { + reflect_t *found = map_find(reflects, intern(symbol)); + if( found ) reflect_print_(found); +} + // -- tests enum { @@ -12849,7 +12884,7 @@ typedef struct MyVec4 { float x,y,z,w; } MyVec4; -ifdef(objapi, enum { OBJTYPE_MyVec4 = 0x100 }); +enum { OBJTYPE_MyVec4 = 0x01 }; AUTOTEST { // register structs, enums and functions @@ -12882,7 +12917,11 @@ AUTOTEST { // printf("+%s MyVec4.%s // %s\n", R->type, R->name, R->info); } - // reflected_printf_all(); + // reflect_print("puts"); + // reflect_print("MYVALUE0"); + // reflect_print("MyVec4"); + + // reflect_dump("*"); } #line 0 diff --git a/engine/v4k.h b/engine/v4k.h index 3f4ece3..b0f8928 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -308,6 +308,22 @@ extern "C" { #define EXPAND_ARGS(args) EXPAND_RETURN_COUNT args ///- #define EXPAND_RETURN_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, _7_, _8_, _9_, count, ...) count ///- +// expands to the first argument +#define VA_FIRST(...) VA_F1RST(__VA_ARGS__, throwaway) +#define VA_F1RST(first, ...) first ///- +// if there's only one argument, expands to nothing. if there is more +// than one argument, expands to a comma followed by everything but +// the first argument. only supports up to 9 arguments but can be expanded. +#define VA_REST(...) VA_R3ST(VA_NUM(__VA_ARGS__), __VA_ARGS__) +#define VA_R3ST(qty, ...) VA_R3S7(qty, __VA_ARGS__) ///- +#define VA_R3S7(qty, ...) VA_R3S7_##qty(__VA_ARGS__) ///- +#define VA_R3S7_ONE(first) ///- +#define VA_R3S7_TWOORMORE(first, ...) , __VA_ARGS__ ///- +#define VA_NUM(...) VA_SELECT_10TH(__VA_ARGS__, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, TWOORMORE, ONE, throwaway) ///- +#define VA_SELECT_10TH(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, ...) A10 +// VA_SPLIT() expands to A) 1 item OR B) 1 item + ',' + va_args[1..N] +#define VA_SPLIT(...) VA_FIRST(__VA_ARGS__) VA_REST(__VA_ARGS__) + #if is(cl) && !is(cpp) #define INLINE __inline #else @@ -332,6 +348,21 @@ extern "C" { // typedef union vec2 { float X,Y; }; vec2 a = {0,1}, b = vec2(0,1); #define C_CAST(type, ...) ( ifdef(c,(type),type) { __VA_ARGS__ } ) +// create a WARNING(...) macro +// usage: WARNING("this is displayed at compile time") +#if is(gcc) +# define WARNING(msg) WARN1NG( message( msg ) ) +# define WARN1NG(msg) _Pragma(#msg) +#elif is(cl) +# define WARNING(msg) __pragma( message( msg ) ) +#else +# define WARNING(msg) +#endif + +// document todos and fixmes via compiler warnings +#define TODO(str) ifdef(debug,WARNING("TO DO: " str " (" FILELINE ")")) +#define FIXME(str) ifdef(debug,WARNING("FIXME: " str " (" FILELINE ")")) + // ----------------------------------------------------------------------------- // autorun initializers for C // - rlyeh, public domain @@ -340,29 +371,25 @@ extern "C" { // note: XIU for C initializers, XCU for C++ initializers, XTU for C deinitializers #ifdef __cplusplus -#define AUTORUN \ - static void AUTORUN_U(f)(void); \ - static const int AUTORUN_J(AUTORUN_U(f),__1) = (AUTORUN_U(f)(), 1); \ - static void AUTORUN_U(f)(void) +#define AUTORUN_(fn) \ + static void fn(void); \ + static const int concat(fn,__1) = (fn(), 1); \ + static void fn(void) #elif defined _MSC_VER && !defined(__clang__) // cl, but not clang-cl -#define AUTORUN \ - static void AUTORUN_U(f)(void); \ - static int AUTORUN_J(AUTORUN_U(f),__1) (){ AUTORUN_U(f)(); return 0; } \ +#define AUTORUN_(fn) \ + static void fn(void); \ + static int concat(fn,__1) (){ fn(); return 0; } \ __pragma(section(".CRT$XIU", long, read)) \ __declspec(allocate(".CRT$XIU")) \ - static int(* AUTORUN_J(AUTORUN_U(f),__2) )() = AUTORUN_J(AUTORUN_U(f),__1); \ - static void AUTORUN_U(f)(void) + static int(* concat(fn,__2) )() = concat(fn,__1); \ + static void fn(void) #else // gcc,tcc,clang,clang-cl... -#define AUTORUN \ +#define AUTORUN_(fn) \ __attribute__((constructor)) \ - static void AUTORUN_U(f)(void) + static void fn(void) #endif -// join + unique macro utils - -#define AUTORUN_j(a, b) a##b -#define AUTORUN_J(a, b) AUTORUN_j(a, b) -#define AUTORUN_U(x) AUTORUN_J(x, __LINE__) +#define AUTORUN AUTORUN_( concat(concat(concat(fn_L,__LINE__),_),__COUNTER__) ) #if 0 // autorun demo void byebye(void) { puts("seen after main()"); } @@ -2644,8 +2671,8 @@ extern API int profiler_enabled; ///- // @todo: nested structs? pointers in members? // @todo: declare TYPEDEF(vec3, float[3]), TYPEDEF(mat4, vec4[4]/*float[16]*/) -#ifndef ifdef_objapi -#define ifdef_objapi(T,...) __VA_ARGS__ +#ifndef OBJTYPE +#define OBJTYPE(T) 0 #endif typedef struct reflect_t { @@ -2667,7 +2694,7 @@ typedef struct reflect_t { function_inscribe(#F,intern(#F),(void*)F, function_annotations) #define STRUCT(T, type, member, member_annotations) \ - struct_inscribe(#T,intern(#T),sizeof(T),ifdef(objapi,OBJTYPE_##T,0),NULL), \ + struct_inscribe(#T,intern(#T),sizeof(T),OBJTYPE(T),NULL), \ type_inscribe(#type,intern(#type),sizeof(((T){0}).member),member_annotations), \ member_inscribe(intern(#T), #member,intern(#member),(uintptr_t)&((T*)0)->member, member_annotations, #type ) @@ -2695,8 +2722,9 @@ API void struct_inscribe(const char *T,unsigned Tid,unsigned Tsz,u API void member_inscribe(unsigned Tid, const char *M,unsigned Mid,unsigned Msz, const char *infos, const char *type); API void function_inscribe(const char *F,unsigned Fid,void *func,const char *infos); -API void reflected_printf(reflect_t *r); -API void reflected_printf_all(); +API void reflect_print(const char *symbol); +API void reflect_dump(const char *mask); +API void reflect_init(); #line 0 #line 1 "engine/split/v4k_render.h"