diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/3p/chibicc/chibicc.h | 4 | ||||
-rw-r--r-- | src/3p/chibicc/tokenize.c | 2 | ||||
-rw-r--r-- | src/ac.c | 5 | ||||
-rw-r--r-- | src/alias.c | 1 | ||||
-rw-r--r-- | src/autojump.c | 2 | ||||
-rw-r--r-- | src/bind.c | 2 | ||||
-rw-r--r-- | src/bitbuf.h | 2 | ||||
-rw-r--r-- | src/build/cmeta.c | 87 | ||||
-rw-r--r-- | src/build/cmeta.h | 6 | ||||
-rw-r--r-- | src/build/codegen.c | 84 | ||||
-rw-r--r-- | src/build/mkentprops.c | 1 | ||||
-rw-r--r-- | src/build/mkgamedata.c | 1 | ||||
-rw-r--r-- | src/build/vec.h | 1 | ||||
-rw-r--r-- | src/con_.c | 53 | ||||
-rw-r--r-- | src/con_.h | 2 | ||||
-rw-r--r-- | src/democustom.c | 4 | ||||
-rw-r--r-- | src/demorec.c | 1 | ||||
-rw-r--r-- | src/engineapi.c | 8 | ||||
-rw-r--r-- | src/ent.c | 4 | ||||
-rw-r--r-- | src/event.h | 56 | ||||
-rw-r--r-- | src/extmalloc.c | 26 | ||||
-rw-r--r-- | src/feature.h | 2 | ||||
-rw-r--r-- | src/fov.c | 9 | ||||
-rw-r--r-- | src/fov.h | 2 | ||||
-rw-r--r-- | src/gamedata.c | 2 | ||||
-rw-r--r-- | src/gamedata.h | 2 | ||||
-rw-r--r-- | src/gameinfo.c | 3 | ||||
-rw-r--r-- | src/hook.h | 2 | ||||
-rw-r--r-- | src/kv.c | 2 | ||||
-rw-r--r-- | src/kv.h | 2 | ||||
-rw-r--r-- | src/l4dwarp.c | 8 | ||||
-rw-r--r-- | src/os.h | 2 | ||||
-rw-r--r-- | src/portalcolours.c | 1 | ||||
-rw-r--r-- | src/sst.c | 14 | ||||
-rw-r--r-- | src/sst.h | 4 | ||||
-rw-r--r-- | src/vcall.h | 98 | ||||
-rw-r--r-- | src/x86util.h | 4 |
37 files changed, 337 insertions, 172 deletions
diff --git a/src/3p/chibicc/chibicc.h b/src/3p/chibicc/chibicc.h index dd810ec..2a80ecf 100644 --- a/src/3p/chibicc/chibicc.h +++ b/src/3p/chibicc/chibicc.h @@ -7,7 +7,7 @@ #include <ctype.h> #include <errno.h> #include <stdarg.h> -#include <stdbool.h> +//#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -93,7 +93,7 @@ _Noreturn void error(char *fmt, ...) __attribute__((format(printf, 1, 2))); _Noreturn void error_at(char *loc, char *fmt, ...) __attribute__((format(printf, 2, 3))); _Noreturn void error_tok(Token *tok, char *fmt, ...) __attribute__((format(printf, 2, 3))); void warn_tok(Token *tok, char *fmt, ...) __attribute__((format(printf, 2, 3))); -bool equal(Token *tok, char *op); +bool equal(const Token *tok, const char *op); Token *skip(Token *tok, char *op); bool consume(Token **rest, Token *tok, char *str); void convert_pp_tokens(Token *tok); diff --git a/src/3p/chibicc/tokenize.c b/src/3p/chibicc/tokenize.c index 8ed414e..3b15df9 100644 --- a/src/3p/chibicc/tokenize.c +++ b/src/3p/chibicc/tokenize.c @@ -77,7 +77,7 @@ void warn_tok(Token *tok, char *fmt, ...) { } // Consumes the current token if it matches `op`. -bool equal(Token *tok, char *op) { +bool equal(const Token *tok, const char *op) { return memcmp(tok->loc, op, tok->len) == 0 && op[tok->len] == '\0'; } @@ -15,7 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <stdlib.h> #include "bind.h" @@ -144,7 +143,7 @@ static void startlockdown(void) { HANDLE_EVENT(Tick) { #ifdef _WIN32 - static int fewticks = 0; + static uint fewticks = 0; // just check this every so often (roughly 0.1-0.3s depending on game) if (lockdown && !(++fewticks & 7)) inhook_check(); #endif @@ -198,7 +197,7 @@ static void VCALLCONV hook_DispatchInputEvent(void *this, static bool find_DispatchInputEvent(void) { #ifdef _WIN32 - // Crazy pointer-chasing path to get to DispachInputEvent (to log keypresses + // Crazy pointer-chasing path to get to DispatchInputEvent (to log keypresses // and their associated binds): // IGameUIFuncs interface // -> CGameUIFuncs::GetDesktopResolution vfunc diff --git a/src/alias.c b/src/alias.c index b94a6d5..765f735 100644 --- a/src/alias.c +++ b/src/alias.c @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <string.h> #include "alias.h" diff --git a/src/autojump.c b/src/autojump.c index c4f54f4..d26ab9e 100644 --- a/src/autojump.c +++ b/src/autojump.c @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> - #include "con_.h" #include "engineapi.h" #include "errmsg.h" @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> - #include "con_.h" #include "dbg.h" #include "errmsg.h" diff --git a/src/bitbuf.h b/src/bitbuf.h index 104c9a1..8700af3 100644 --- a/src/bitbuf.h +++ b/src/bitbuf.h @@ -17,8 +17,6 @@ #ifndef INC_BITBUF_H #define INC_BITBUF_H -#include <stdbool.h> - #include "intdefs.h" // NOTE: This code assumes it's running on a little endian machine, because, diff --git a/src/build/cmeta.c b/src/build/cmeta.c index 260d33f..7f314c7 100644 --- a/src/build/cmeta.c +++ b/src/build/cmeta.c @@ -14,13 +14,13 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <stdio.h> #include <string.h> #include "../intdefs.h" #include "../os.h" #include "cmeta.h" +#include "vec.h" /* * This file does C metadata parsing/scraping for the build system. This @@ -73,16 +73,16 @@ Type *array_of(Type *base, int len) { #include "../3p/chibicc/tokenize.c" // one more copypaste from preprocess.c for #include <filename> and then I'm // done I promise -static char *join_tokens(Token *tok, Token *end) { +static char *join_tokens(const Token *tok, const Token *end) { int len = 1; - for (Token *t = tok; t != end && t->kind != TK_EOF; t = t->next) { + for (const Token *t = tok; t != end && t->kind != TK_EOF; t = t->next) { if (t != tok && t->has_space) len++; len += t->len; } char *buf = calloc(1, len); int pos = 0; - for (Token *t = tok; t != end && t->kind != TK_EOF; t = t->next) { + for (const Token *t = tok; t != end && t->kind != TK_EOF; t = t->next) { if (t != tok && t->has_space) buf[pos++] = ' '; strncpy(buf + pos, t->loc, t->len); @@ -166,7 +166,7 @@ const struct cmeta *cmeta_loadfile(const os_char *f) { // picks it anyway, and gives far better diagnostics. void cmeta_includes(const struct cmeta *cm, void (*cb)(const char *f, bool issys, void *ctxt), void *ctxt) { - Token *tp = (Token *)cm; + const Token *tp = (const Token *)cm; if (!tp || !tp->next || !tp->next->next) return; // #, include, "string" while (tp) { if (!tp->at_bol || !equal(tp, "#")) { tp = tp->next; continue; } @@ -187,7 +187,7 @@ void cmeta_includes(const struct cmeta *cm, else if (equal(tp, "<")) { tp = tp->next; if (!tp) break; - Token *end = tp; + const Token *end = tp; while (!equal(end, ">")) { end = end->next; if (!end) return; // shouldn't happen in valid source obviously @@ -210,7 +210,7 @@ void cmeta_includes(const struct cmeta *cm, // we're not writing something weird. Don't write something weird! void cmeta_conmacros(const struct cmeta *cm, void (*cb)(const char *, bool, bool)) { - Token *tp = (Token *)cm; + const Token *tp = (const Token *)cm; if (!tp || !tp->next || !tp->next->next) return; // DEF_xyz, (, name while (tp) { bool isplusminus = false, isvar = false; @@ -271,7 +271,7 @@ void cmeta_conmacros(const struct cmeta *cm, } const char *cmeta_findfeatmacro(const struct cmeta *cm) { - Token *tp = (Token *)cm; + const Token *tp = (const Token *)cm; if (!tp || !tp->next) return 0; // FEATURE, ( while (tp) { if (equal(tp, "FEATURE") && equal(tp->next, "(")) { @@ -288,7 +288,7 @@ const char *cmeta_findfeatmacro(const struct cmeta *cm) { void cmeta_featinfomacros(const struct cmeta *cm, void (*cb)( enum cmeta_featmacro type, const char *param, void *ctxt), void *ctxt) { - Token *tp = (Token *)cm; + const Token *tp = (const Token *)cm; if (!tp || !tp->next) return; while (tp) { int type = -1; @@ -336,26 +336,73 @@ void cmeta_featinfomacros(const struct cmeta *cm, void (*cb)( } } -void cmeta_evdefmacros(const struct cmeta *cm, - void (*cb_def)(const char *name)) { - Token *tp = (Token *)cm; +struct vec_str VEC(const char *); + +static void pushmacroarg(const Token *last, const char *start, + struct vec_str *list) { + int len = last->loc - start + last->len; + char *dup = malloc(len + 1); + if (!dup) die1("couldn't allocate memory"); + memcpy(dup, start, len); + dup[len] = '\0'; + if (!vec_push(list, dup)) die1("couldn't append to array"); +} + +// XXX: maybe this should be used for the other functions too. it'd be less ugly +// and handle closing parentheses better, but alloc for tokens we don't care +// about. probably a worthy tradeoff? +static const Token *macroargs(const Token *t, struct vec_str *list) { + int paren = 1; + const Token *last; // avoids copying extra ws/comments in + for (const char *start = t->loc; t; last = t, t = t->next) { + if (equal(t, "(")) { + ++paren; + } + else if (equal(t, ")")) { + if (!--paren) { + pushmacroarg(last, start, list); + return t->next; + } + } + else if (paren == 1 && equal(t, ",")) { + pushmacroarg(last, start, list); + t = t->next; + if (t) start = t->loc; // slightly annoying... + } + } + // I guess we handle this here. + fprintf(stderr, "cmeta: fatal: unexpected EOF in %s\n", t->filename); + exit(2); +} + +void cmeta_evdefmacros(const struct cmeta *cm, void (*cb)(const char *name, + const char *const *params, int nparams, bool predicate)) { + const Token *tp = (const Token *)cm; if (!tp || !tp->next || !tp->next->next) return; // DEF_EVENT, (, name while (tp) { + bool predicate = true; if (equal(tp, "DEF_EVENT") && equal(tp->next, "(")) { - tp = tp->next->next; - char *name = malloc(tp->len + 1); - if (!name) die1("couldn't allocate memory"); - memcpy(name, tp->loc, tp->len); - name[tp->len] = '\0'; - cb_def(name); + predicate = false; } - tp = tp->next; + else if (!equal(tp, "DEF_PREDICATE") || !equal(tp->next, "(")) { + tp = tp->next; + continue; + } + tp = tp->next->next; + struct vec_str args = {0}; + tp = macroargs(tp, &args); + if (args.sz == 0) { + fprintf(stderr, "cmeta: fatal: missing event parameters in %s\n", + tp->filename); + exit(2); + } + cb(args.data[0], args.data + 1, args.sz - 1, predicate); } } void cmeta_evhandlermacros(const struct cmeta *cm, const char *modname, void (*cb_handler)(const char *evname, const char *modname)) { - Token *tp = (Token *)cm; + const Token *tp = (const Token *)cm; while (tp) { if (equal(tp, "HANDLE_EVENT") && equal(tp->next, "(")) { tp = tp->next->next; diff --git a/src/build/cmeta.h b/src/build/cmeta.h index 40c4ac5..48a2d6d 100644 --- a/src/build/cmeta.h +++ b/src/build/cmeta.h @@ -17,8 +17,6 @@ #ifndef INC_CMETA_H #define INC_CMETA_H -#include <stdbool.h> - #include "../os.h" struct cmeta; @@ -76,8 +74,8 @@ void cmeta_featinfomacros(const struct cmeta *cm, void (*cb)( * Iterates through all event-related macros and takes note of which events are * defined, giving a callback for each. */ -void cmeta_evdefmacros(const struct cmeta *cm, void (*cb)(const char *name)); - +void cmeta_evdefmacros(const struct cmeta *cm, void (*cb)(const char *name, + const char *const *params, int nparams, bool predicate)); /* * Iterates through all event-related macros and gives a callback for each event * that is handled by the given module. diff --git a/src/build/codegen.c b/src/build/codegen.c index 04a9058..f5231c0 100644 --- a/src/build/codegen.c +++ b/src/build/codegen.c @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -139,12 +138,15 @@ push: if (!vec_push(vecp, param)) die("couldn't allocate memory"); DECL_SKIPLIST(static, event, struct event, const char *, 4) struct event { - const char *name; + usize name; // string, but tagged pointer - see below + const char *const *params; + int nparams; + //char pad[4]; struct vec_usize handlers; // strings, but with tagged pointers - see below struct skiplist_hdr_event hdr; }; static inline int cmp_event(struct event *e, const char *s) { - return strcmp(e->name, s); + return strcmp((const char *)(e->name & ~1ull), s); } static inline struct skiplist_hdr_event *hdr_event(struct event *e) { return &e->hdr; @@ -152,12 +154,15 @@ static inline struct skiplist_hdr_event *hdr_event(struct event *e) { DEF_SKIPLIST(static, event, cmp_event, hdr_event) static struct skiplist_hdr_event events = {0}; -static void onevdef(const char *name) { +static void onevdef(const char *name, const char *const *params, int nparams, + bool predicate) { struct event *e = skiplist_get_event(&events, name); if (!e) { struct event *e = malloc(sizeof(*e)); if (!e) die("couldn't allocate memory"); - e->name = name; + // hack: using unused pointer bit to distinguish the two types of event + e->name = (usize)name | predicate; + e->params = params; e->nparams = nparams; e->handlers = (struct vec_usize){0}; e->hdr = (struct skiplist_hdr_event){0}; skiplist_insert_event(&events, name, e); @@ -445,19 +450,70 @@ _( "") H_() for (const struct event *e = events.x[0]; e; e = e->hdr.x[0]) { _( "") -F( "void _evemit_%s(void) {", e->name) - for (usize *pp = e->handlers.data; - pp - e->handlers.data < e->handlers.sz; ++pp) { - const char *modname = (const char *)(*pp & ~1ull); -F( " void _evhandler_%s_%s(void);", modname, e->name) // blegh. - if (*pp & 1ull) { - // note: has_* variables are already included by this point (above) -F( " if (has_%s) _evhandler_%s_%s();", modname, modname, e->name) + // gotta break from the string emit macros for a sec in order to do the + // somewhat more complicated task sometimes referred to as a "for loop" + fprintf(out, "%s_%s(", e->name & 1 ? "bool CHECK" : "void EMIT", + (const char *)(e->name & ~1ull)); + for (int n = 0; n < (int)e->nparams - 1; ++n) { + fprintf(out, "typeof(%s) a%d, ", e->params[n], n + 1); + } + if (e->nparams && strcmp(e->params[0], "void")) { + fprintf(out, "typeof(%s) a%d", e->params[e->nparams - 1], + e->nparams); } else { -F( " _evhandler_%s_%s();", modname, e->name) + // just unilaterally doing void for now. when we're fully on C23 + // eventually we can unilaterally do nothing instead + fputs("void", out); } +_( ") {") + for (usize *pp = e->handlers.data; + pp - e->handlers.data < e->handlers.sz; ++pp) { + const char *modname = (const char *)(*pp & ~1ull); + fprintf(out, "\t%s _evhandler_%s_%s(", e->name & 1 ? "bool" : "void", + modname, (const char *)(e->name & ~1ull)); + for (int n = 0; n < (int)e->nparams - 1; ++n) { + fprintf(out, "typeof(%s) a%d, ", e->params[n], n + 1); + } + if (e->nparams && strcmp(e->params[0], "void")) { + fprintf(out, "typeof(%s) a%d", e->params[e->nparams - 1], + e->nparams); + } + else { + fputs("void", out); + } + fputs(");\n\t", out); + // conditional and non-conditional cases - in theory could be + // unified a bit but this is easier to make output relatively pretty + // note: has_* variables are already included by this point (above) + if (e->name & 1) { + if (*pp & 1) fprintf(out, "if (has_%s && !", modname); + else fprintf(out, "if (!"); + fprintf(out, "_evhandler_%s_%s(", modname, + (const char *)(e->name & ~1ull)); + // XXX: much repetitive drivel here + for (int n = 0; n < (int)e->nparams - 1; ++n) { + fprintf(out, "a%d,", n + 1); + } + if (e->nparams && strcmp(e->params[0], "void")) { + fprintf(out, "a%d", e->nparams); + } + fputs(")) return false;\n", out); + } + else { + if (*pp & 1) fprintf(out, "if (has_%s) ", modname); + fprintf(out, "_evhandler_%s_%s(", modname, + (const char *)(e->name & ~1ull)); + for (int n = 0; n < (int)e->nparams - 1; ++n) { + fprintf(out, "a%d,", n + 1); + } + if (e->nparams && strcmp(e->params[0], "void")) { + fprintf(out, "a%d", e->nparams); + } + fputs(");\n", out); + } } + if (e->name & 1) fputs("\treturn true;\n", out); _( "}") } if (fclose(out) == EOF) die("couldn't fully write evglue.gen.h"); diff --git a/src/build/mkentprops.c b/src/build/mkentprops.c index 300dafa..fdb6982 100644 --- a/src/build/mkentprops.c +++ b/src/build/mkentprops.c @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/build/mkgamedata.c b/src/build/mkgamedata.c index 7d7a425..fdb2aef 100644 --- a/src/build/mkgamedata.c +++ b/src/build/mkgamedata.c @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/src/build/vec.h b/src/build/vec.h index 50b0a3b..6b4dffb 100644 --- a/src/build/vec.h +++ b/src/build/vec.h @@ -4,7 +4,6 @@ #define INC_VEC_H #include <errno.h> -#include <stdbool.h> #include <stdlib.h> #include "../intdefs.h" @@ -15,7 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <stddef.h> // should be implied by stdlib but glibc is dumb (offsetof) #include <stdlib.h> #include <stdio.h> @@ -64,8 +63,12 @@ DECL_VFUNC_DYN(struct con_var *, FindVar, const char *) DECL_VFUNC_DYN(struct con_cmd *, FindCommand, const char *) DECL_VFUNC_DYN(void, CallGlobalChangeCallbacks, struct con_var *, const char *, float) -DECL_VFUNC_CDECLDYN(void, ConsoleColorPrintf, const struct con_colour *, - const char *, ...) +// sad: since adding the cool abstraction, we can't do varargs (because you +// can't pass varargs to other varargs of course). we only get a pointer to it +// via VFUNC so just declare the typedef here - I don't wanna write any more +// macros today. +typedef void (*ConsoleColorPrintf_func)(void *, const struct con_colour *, + const char *, ...); static inline void initval(struct con_var *v) { // v->strlen is set to defaultval len in _DEF_CVAR so we don't need to call @@ -81,7 +84,7 @@ static inline void initval(struct con_var *v) { // required, we call the Internal* virtual functions by actual virtual lookup. // since the vtables are filled dynamically (below), we store this index; other // indices are just offset from this one since the 3-or-4 functions are all -// right next to each other. the #defines allow us to still use the nice VCALL +// right next to each other. the #defines allow us to still use the nice vcall // stuff. static int vtidx_InternalSetValue; #define vtidx_InternalSetFloatValue (vtidx_InternalSetValue + 1) @@ -180,10 +183,10 @@ static void VCALLCONV ChangeStringValue(struct con_var *this, const char *s, // do need callbacks for at least one feature, so do our own minimal thing if (this->cb) this->cb(this); // also call global callbacks, as is polite. - VCALL(_con_iface, CallGlobalChangeCallbacks, this, old, oldf); + CallGlobalChangeCallbacks(_con_iface, this, old, oldf); } -static void VCALLCONV InternalSetValue(struct con_var *this, const char *v) { +static void VCALLCONV InternalSetValue_impl(struct con_var *this, const char *v) { float oldf = this->fval; float newf = atof(v); char tmp[32]; @@ -198,7 +201,7 @@ static void VCALLCONV InternalSetValue(struct con_var *this, const char *v) { if (!(this->base.flags & CON_NOPRINT)) ChangeStringValue(this, v, oldf); } -static void VCALLCONV InternalSetFloatValue(struct con_var *this, float v) { +static void VCALLCONV InternalSetFloatValue_impl(struct con_var *this, float v) { if (v == this->fval) return; ClampValue(this, &v); float old = this->fval; @@ -210,7 +213,7 @@ static void VCALLCONV InternalSetFloatValue(struct con_var *this, float v) { } } -static void VCALLCONV InternalSetIntValue(struct con_var *this, int v) { +static void VCALLCONV InternalSetIntValue_impl(struct con_var *this, int v) { if (v == this->ival) return; float f = (float)v; if (ClampValue(this, &f)) v = (int)f; @@ -233,22 +236,22 @@ DECL_VFUNC_DYN(void, InternalSetColorValue, struct con_colour) static void VCALLCONV SetValue_str_thunk(void *thisoff, const char *v) { struct con_var *this = mem_offset(thisoff, -offsetof(struct con_var, vtable_iconvar)); - VCALL(&this->parent->base, InternalSetValue, v); + InternalSetValue(&this->parent->base, v); } static void VCALLCONV SetValue_f_thunk(void *thisoff, float v) { struct con_var *this = mem_offset(thisoff, -offsetof(struct con_var, vtable_iconvar)); - VCALL(&this->parent->base, InternalSetFloatValue, v); + InternalSetFloatValue(&this->parent->base, v); } static void VCALLCONV SetValue_i_thunk(void *thisoff, int v) { struct con_var *this = mem_offset(thisoff, -offsetof(struct con_var, vtable_iconvar)); - VCALL(&this->parent->base, InternalSetIntValue, v); + InternalSetIntValue(&this->parent->base, v); } static void VCALLCONV SetValue_colour_thunk(void *thisoff, struct con_colour v) { struct con_var *this = mem_offset(thisoff, -offsetof(struct con_var, vtable_iconvar)); - VCALL(&this->parent->base, InternalSetColorValue, v); + InternalSetColorValue(&this->parent->base, v); } // more misc thunks, hopefully these just compile to a sub and a jmp @@ -322,13 +325,13 @@ void *_con_vtab_iconvar[7] = { }; void con_reg(void *cmd_or_var) { - VCALL(_con_iface, RegisterConCommand, cmd_or_var); + RegisterConCommand(_con_iface, cmd_or_var); } void con_init(void) { // FIXME: ConsoleColorPrintf isn't working in Portal 2, possible regression? _con_colourmsgf = VFUNC(_con_iface, ConsoleColorPrintf); - dllid = VCALL(_con_iface, AllocateDLLIdentifier); + dllid = AllocateDLLIdentifier(_con_iface); void **pc = _con_vtab_cmd + 3 + NVDTOR, **pv = _con_vtab_var + 3 + NVDTOR, **pi = _con_vtab_iconvar @@ -362,13 +365,13 @@ void con_init(void) { *pv++ = (void *)&Init; // var-specific vtidx_InternalSetValue = pv - _con_vtab_var; - *pv++ = (void *)&InternalSetValue; - *pv++ = (void *)&InternalSetFloatValue; - *pv++ = (void *)&InternalSetIntValue; + *pv++ = (void *)&InternalSetValue_impl; + *pv++ = (void *)&InternalSetFloatValue_impl; + *pv++ = (void *)&InternalSetIntValue_impl; if (GAMETYPE_MATCHES(L4D2x) || GAMETYPE_MATCHES(Portal2)) { // ugh, annoying // This is InternalSetColorValue, but that's basically the same thing, // when you think about it. - *pv++ = (void *)&InternalSetIntValue; + *pv++ = (void *)&InternalSetIntValue_impl; } *pv++ = (void *)&ClampValue;; *pv++ = (void *)&ChangeStringValue; @@ -415,15 +418,15 @@ bool con_detect(int pluginver) { // *actually* calls the const-overloaded FindVar on other branches, // which just happens to still work fine. From there, we can figure out // the actual ABI to use to avoid spectacular crashes. - if (VCALL(_con_iface, FindCommandBase_p2, "portal2_square_portals")) { + if (FindCommandBase_p2(_con_iface, "portal2_square_portals")) { _gametype_tag |= _gametype_tag_Portal2; return true; } - if (VCALL(_con_iface, FindCommand_nonp2, "l4d2_snd_adrenaline")) { + if (FindCommand_nonp2(_con_iface, "l4d2_snd_adrenaline")) { // while we're here, also distinguish Survivors, the stupid Japanese // arcade game a few people seem to care about for some reason // (which for some other reason also has some vtable changes) - if (VCALL(_con_iface, FindVar_nonp2, "avatarbasemodel")) { + if (FindVar_nonp2(_con_iface, "avatarbasemodel")) { _gametype_tag |= _gametype_tag_L4DS; } else { @@ -431,7 +434,7 @@ bool con_detect(int pluginver) { } return true; } - if (VCALL(_con_iface, FindVar_nonp2, "z_difficulty")) { + if (FindVar_nonp2(_con_iface, "z_difficulty")) { _gametype_tag |= _gametype_tag_L4D1; return true; } @@ -463,16 +466,16 @@ bool con_detect(int pluginver) { } void con_disconnect(void) { - VCALL(_con_iface, UnregisterConCommands, dllid); + UnregisterConCommands(_con_iface, dllid); freevars(); } struct con_var *con_findvar(const char *name) { - return VCALL(_con_iface, FindVar, name); + return FindVar(_con_iface, name); } struct con_cmd *con_findcmd(const char *name) { - return VCALL(_con_iface, FindCommand, name); + return FindCommand(_con_iface, name); } #define GETTER(T, N, M) T N(const struct con_var *v) { return v->parent->M; } @@ -18,8 +18,6 @@ #ifndef INC_CON_H #define INC_CON_H -#include <stdbool.h> - #include "intdefs.h" #if defined(__GNUC__) || defined(__clang__) diff --git a/src/democustom.c b/src/democustom.c index c7de77b..f8c7c9d 100644 --- a/src/democustom.c +++ b/src/democustom.c @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> - #include "bitbuf.h" #include "con_.h" #include "democustom.h" @@ -121,7 +119,7 @@ INIT { // > there might be some other l4d2 versions where it's 11 but idk // So here we have to figure out the network protocol version! // NOTE: assuming engclient != null as GEBN index relies on client version - int buildnum = VCALL(engclient, GetEngineBuildNumber); + int buildnum = GetEngineBuildNumber(engclient); // condition is redundant until other GetEngineBuildNumber offsets are added // if (GAMETYPE_MATCHES(L4D2)) { nbits_msgtype = 6; diff --git a/src/demorec.c b/src/demorec.c index 50128f0..4434534 100644 --- a/src/demorec.c +++ b/src/demorec.c @@ -15,7 +15,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <string.h> #include "con_.h" diff --git a/src/engineapi.c b/src/engineapi.c index cef085b..8cc3dd6 100644 --- a/src/engineapi.c +++ b/src/engineapi.c @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <stdlib.h> // used in generated code #include <string.h> // " @@ -42,7 +41,6 @@ DECL_VFUNC(void *, GetGlobalVars, 1) void *globalvars; DECL_VFUNC_DYN(void *, GetAllServerClasses) -DECL_VFUNC_DYN(int, GetEngineBuildNumber) DECL_VFUNC(int, GetEngineBuildNumber_newl4d2, 99) // duping gamedata entry, yuck @@ -71,7 +69,7 @@ bool engineapi_init(int pluginver) { // } void *pim = factory_server("PlayerInfoManager002", 0); - if (pim) globalvars = VCALL(pim, GetGlobalVars); + if (pim) globalvars = GetGlobalVars(pim); void *srvdll; // TODO(compat): add this back when there's gamedata for 009 (no point atm) @@ -93,7 +91,7 @@ bool engineapi_init(int pluginver) { // till gamedata is set up, so we have to have a bit of redundant logic here // to bootstrap things. if (GAMETYPE_MATCHES(L4D2) && GAMETYPE_MATCHES(Client013) && - VCALL(engclient, GetEngineBuildNumber_newl4d2) >= 2200) { + GetEngineBuildNumber_newl4d2(engclient) >= 2200) { _gametype_tag |= _gametype_tag_TheLastStand; } @@ -104,7 +102,7 @@ bool engineapi_init(int pluginver) { if (!gameinfo_init()) { con_disconnect(); return false; } if (has_vtidx_GetAllServerClasses && has_sz_SendProp && has_off_SP_varname && has_off_SP_offset) { - initentprops(VCALL(srvdll, GetAllServerClasses)); + initentprops(GetAllServerClasses(srvdll)); } return true; } @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> - #include "engineapi.h" #include "errmsg.h" #include "feature.h" @@ -37,7 +35,7 @@ void *ent_getedict(int idx) { return mem_offset(*edicts, sz_edict * idx); } else { - return VCALL(engserver, PEntityOfEntIndex, idx); + return PEntityOfEntIndex(engserver, idx); } } diff --git a/src/event.h b/src/event.h index e439201..86a443e 100644 --- a/src/event.h +++ b/src/event.h @@ -20,15 +20,53 @@ #define _EVENT_CAT4_(a, b, c, d) a##b##c##d #define _EVENT_CAT4(a, b, c, d) _EVENT_CAT4_(a, b, c, d) -#define DECL_EVENT(evname) void _evemit_##evname(void); -#define DEF_EVENT(evname) \ - DECL_EVENT(evname) \ - static inline void _evown_##evname(void) { _evemit_##evname(); } -#define EMIT_EVENT(evname) _evown_##evname() - -#define HANDLE_EVENT(evname) \ - void _EVENT_CAT4(_evhandler_, MODULE_NAME, _, evname)(void) \ - /* function body here */ +/* + * Declares an event defined somewhere in the codebase, allowing a handler to be + * defined with HANDLE_EVENT() below. Takes an optional list of types for + * parameters. The handler will be called every time the event is emitted by the + * declaring module. + */ +#define DECL_EVENT(evname, ...) typedef void _must_declare_event_##evname; + +/* + * Declares a predicate - a special type of even returning bool. Predicates are + * used to determine whether some other action should be performed, and + * generally should not have side effects, since they get short-circuited and + * thus won't always fire when a check is being performed. + */ +#define DECL_PREDICATE(evname, ...) typedef bool _must_declare_event_##evname; + +/* + * Defines an event belonging to this module. Doing so allows EMIT_<event>() to + * be called to fire handlers in all modules. Two modules (i.e. source files) + * cannot define an event (or predicate) with the same name. + */ +#define DEF_EVENT(event, ...) void EMIT_##event(__VA_ARGS__); + +/* + * Defines a predicate belonging to this module. Doing so allows CHECK_<pred>() + * to be called to determine whether to perform some action. Predicates share a + * namespace with events and two modules cannot define two things with the same + * name. + */ +#define DEF_PREDICATE(pred, ...) bool CHECK_##pred(__VA_ARGS__); + +/* + * Begins an event handler function that gets hooked up to an event by the code + * generation system. This is type-generic: if the event is a regular event, + * the function will return void; if it is a predicate it will return bool. + * Takes a function argument list which must match the type lists given to the + * above DEF/DECL macros. + * + * Note again that predicates are not guaranteed to fire at all due to + * short-circuiting and thus generally should not have side effects. + * + * In the current event implementation, each source file may handle only one of + * each event type, as any more wouldn't be too useful anyway. + */ +#define HANDLE_EVENT(evname, ...) \ + _must_declare_event_##evname _EVENT_CAT4(_evhandler_, MODULE_NAME, _, \ + evname)(__VA_ARGS__) /* function body here */ #endif diff --git a/src/extmalloc.c b/src/extmalloc.c index 9117db0..edd1d54 100644 --- a/src/extmalloc.c +++ b/src/extmalloc.c @@ -36,25 +36,17 @@ IMPORT void *g_pMemAlloc; // affected by naming (overloads are grouped, and *reversed* inside of a // group!?), we get this amusing ABI difference between platforms: #ifdef _WIN32 -DECL_VFUNC(void *, Alloc, 1, usize sz) -DECL_VFUNC(void *, Realloc, 3, void *mem, usize sz) -DECL_VFUNC(void, Free, 5, void *mem) +DECL_VFUNC(void *, Alloc, 1, usize) +DECL_VFUNC(void *, Realloc, 3, void *, usize) +DECL_VFUNC(void, Free, 5, void *) #else -DECL_VFUNC(void *, Alloc, 0, usize sz) -DECL_VFUNC(void *, Realloc, 1, void *mem, usize sz) -DECL_VFUNC(void, Free, 2, void *mem) +DECL_VFUNC(void *, Alloc, 0, usize) +DECL_VFUNC(void *, Realloc, 1, void *, usize) +DECL_VFUNC(void, Free, 2, void *) #endif -void *extmalloc(usize sz) { - return VCALL(g_pMemAlloc, Alloc, sz); -} - -void *extrealloc(void *mem, usize sz) { - return VCALL(g_pMemAlloc, Realloc, mem, sz); -} - -void extfree(void *mem) { - VCALL(g_pMemAlloc, Free, mem); -} +void *extmalloc(usize sz) { return Alloc(g_pMemAlloc, sz); } +void *extrealloc(void *mem, usize sz) { return Realloc(g_pMemAlloc, mem, sz); } +void extfree(void *mem) { Free(g_pMemAlloc, mem); } // vi: sw=4 ts=4 noet tw=80 cc=80 diff --git a/src/feature.h b/src/feature.h index 5277bca..e1e4688 100644 --- a/src/feature.h +++ b/src/feature.h @@ -17,8 +17,6 @@ #ifndef INC_FEATURE_H #define INC_FEATURE_H -#include <stdbool.h> - #define _FEATURE_CAT1(a, b) a##b #define _FEATURE_CAT(a, b) _FEATURE_CAT1(a, b) @@ -17,8 +17,6 @@ // TODO(linux): theoretically, probably ifdef out the cvar-replacement stuff; we // expect any game that's been ported to linux to already have fov_desired -#include <stdbool.h> - #include "con_.h" #include "engineapi.h" #include "errmsg.h" @@ -74,10 +72,9 @@ static void fovcb(struct con_var *v) { } // ensure FOV is applied on load, if the engine wouldn't do that itself -HANDLE_EVENT(ClientActive) { - if (real_fov_desired == fov_desired) { - void *player = ent_get(1); // " - if (player) orig_SetDefaultFOV(player, con_getvari(fov_desired)); +HANDLE_EVENT(ClientActive, struct edict *player) { + if (player && real_fov_desired == fov_desired) { + orig_SetDefaultFOV(player, con_getvari(fov_desired)); } } @@ -17,8 +17,6 @@ #ifndef INC_FOV_H #define INC_FOV_H -#include <stdbool.h> - bool fov_init(bool has_ent); void fov_end(void); diff --git a/src/gamedata.c b/src/gamedata.c index 7b89257..639b2f8 100644 --- a/src/gamedata.c +++ b/src/gamedata.c @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> - #include "gametype.h" // same as gamedata.h, not worth putting in its own thing diff --git a/src/gamedata.h b/src/gamedata.h index 678d572..471e5bb 100644 --- a/src/gamedata.h +++ b/src/gamedata.h @@ -17,8 +17,6 @@ #ifndef INC_GAMEDATA_H #define INC_GAMEDATA_H -#include <stdbool.h> - #ifdef _WIN32 #define NVDTOR 1 #else diff --git a/src/gameinfo.c b/src/gameinfo.c index b371e76..f8b5311 100644 --- a/src/gameinfo.c +++ b/src/gameinfo.c @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #ifdef _WIN32 #include <shlwapi.h> #endif @@ -260,7 +259,7 @@ bool gameinfo_init(void) { // to respect the system code page setting, otherwise some users using e.g. // Cyrillic folder names and successfully loading their speedgames won't be // able to load SST. Thanks Windows! - const char *lcpgamedir = VCALL(engclient, GetGameDirectory); + const char *lcpgamedir = GetGameDirectory(engclient); int gamedirlen = MultiByteToWideChar(CP_ACP, 0, lcpgamedir, strlen(lcpgamedir), gamedir, sizeof(gamedir) / sizeof(*gamedir)); if (!gamedirlen) { @@ -17,8 +17,6 @@ #ifndef INC_HOOK_H #define INC_HOOK_H -#include <stdbool.h> - #include "intdefs.h" bool hook_init(void); @@ -14,8 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> - #include "intdefs.h" #include "kv.h" #include "unreachable.h" @@ -17,8 +17,6 @@ #ifndef INC_KV_H #define INC_KV_H -#include <stdbool.h> - #include "intdefs.h" /* diff --git a/src/l4dwarp.c b/src/l4dwarp.c index 5412b64..5540763 100644 --- a/src/l4dwarp.c +++ b/src/l4dwarp.c @@ -34,14 +34,14 @@ REQUIRE_GAMEDATA(off_eyeang) REQUIRE_GAMEDATA(vtidx_Teleport) DECL_VFUNC_DYN(void *, GetBaseEntity) -DECL_VFUNC_DYN(void, Teleport, const struct vec3f *pos, const struct vec3f *ang, - const struct vec3f *vel) +DECL_VFUNC_DYN(void, Teleport, const struct vec3f */*pos*/, + const struct vec3f */*pos*/, const struct vec3f */*vel*/) DEF_CCMD_HERE_UNREG(sst_l4d_testwarp, "Simulate a bot warping to you", CON_SERVERSIDE | CON_CHEAT) { struct edict *ed = ent_getedict(con_cmdclient + 1); if (!ed) { errmsg_errorx("couldn't access player entity"); return; } - void *e = VCALL(ed->ent_unknown, GetBaseEntity); // is this call required? + void *e = GetBaseEntity(ed->ent_unknown); // is this call required? struct vec3f *org = mem_offset(e, off_entpos); struct vec3f *ang = mem_offset(e, off_eyeang); // L4D idle warps go up to 10 units behind relative to whatever angle the @@ -49,7 +49,7 @@ DEF_CCMD_HERE_UNREG(sst_l4d_testwarp, "Simulate a bot warping to you", // displacing vertically float pitch = ang->x * M_PI / 180, yaw = ang->y * M_PI / 180; float shift = -10 * cos(pitch); - VCALL(e, Teleport, &(struct vec3f){org->x + shift * cos(yaw), + Teleport(e, &(struct vec3f){org->x + shift * cos(yaw), org->y + shift * sin(yaw), org->z}, 0, &(struct vec3f){0, 0, 0}); } @@ -17,8 +17,6 @@ #ifndef INC_OS_H #define INC_OS_H -#include <stdbool.h> - /* * Here we declare an absolute ton of wrappers, macros, compatibility shims, * reimplementations and so on to try in vain to sweep the inconsistencies diff --git a/src/portalcolours.c b/src/portalcolours.c index 231aa01..2231da4 100644 --- a/src/portalcolours.c +++ b/src/portalcolours.c @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <string.h> #include "con_.h" @@ -14,7 +14,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ -#include <stdbool.h> #include <string.h> #ifdef _WIN32 @@ -429,20 +428,17 @@ DECL_VFUNC_DYN(void, ServerCommand, const char *) DEF_CVAR(_sst_onload_echo, "EXPERIMENTAL! Don't rely on this existing!", "", CON_HIDDEN) -DEF_EVENT(ClientActive) -DEF_EVENT(Tick) +DEF_EVENT(ClientActive, struct edict */*player*/) +DEF_EVENT(Tick, bool /*simulating*/) // Quick and easy server tick event. Eventually, we might want a deeper hook // for anything timing-sensitive, but this will do for our current needs. static void VCALLCONV GameFrame(void *this, bool simulating) { - EMIT_EVENT(Tick); + EMIT_Tick(simulating); } static void VCALLCONV ClientActive(void *this, struct edict *player) { - // XXX: it's kind of dumb that we get handed the edict here then go look it - // up again in fov.c but I can't be bothered refactoring any further now - // that this finally works, do something later lol - EMIT_EVENT(ClientActive); + EMIT_ClientActive(player); // continuing dumb portal hack. didn't even seem worth adding a feature for if (has_vtidx_ServerCommand && con_getvarstr(_sst_onload_echo)[0]) { @@ -454,7 +450,7 @@ static void VCALLCONV ClientActive(void *this, struct edict *player) { memcpy(s + 6, con_getvarstr(_sst_onload_echo), _sst_onload_echo->strlen); memcpy(s + 6 + _sst_onload_echo->strlen - 1, "\"\n", 3); - VCALL(engserver, ServerCommand, s); + ServerCommand(engserver, s); free(s); } } @@ -21,8 +21,8 @@ /* misc stuff that doesn't belong anywhere else */ -DECL_EVENT(ClientActive) -DECL_EVENT(Tick) +DECL_EVENT(ClientActive, struct edict */*player*/) +DECL_EVENT(Tick, bool /*simulating*/) extern void *clientlib; diff --git a/src/vcall.h b/src/vcall.h index caee70a..778ba09 100644 --- a/src/vcall.h +++ b/src/vcall.h @@ -35,32 +35,108 @@ #define VCALLCONV #endif +// black magic argument list maker thingmy, similar to the PPMAGIC_MAP thing, +// but slightly different, so we get to have all this nonsense twice. not sorry + +// note: arg numbering is counting down instead of up because it's easier to +// treat the vararg macros like a stack, and doesn't actually matter otherwise +// also note: I just did 16. that should be enough +#define _VCALL_ARG00() +#define _VCALL_ARG01(t) typeof(t) a1 +#define _VCALL_ARG02(t1, t2) typeof(t1) a2, typeof(t2) a1 +#define _VCALL_ARG03(t1, t2, t3) typeof(t1) a3, typeof(t2) a2, typeof(t3) a1 +#define _VCALL_ARG04(t1, t2, t3, t4) \ + typeof(t1) a4, typeof(t2) a3, typeof(t3) a2, typeof(t4) a1 +#define _VCALL_ARG05(t, ...) typeof(t) a5, _VCALL_ARG04(__VA_ARGS__) +#define _VCALL_ARG06(t, ...) typeof(t) a6, _VCALL_ARG05(__VA_ARGS__) +#define _VCALL_ARG07(t, ...) typeof(t) a7, _VCALL_ARG06(__VA_ARGS__) +#define _VCALL_ARG08(t, ...) typeof(t) a8, _VCALL_ARG07(__VA_ARGS__) +#define _VCALL_ARG09(t, ...) typeof(t) a9, _VCALL_ARG08(__VA_ARGS__) +#define _VCALL_ARG10(t, ...) typeof(t) a10, _VCALL_ARG09(__VA_ARGS__) +#define _VCALL_ARG11(t, ...) typeof(t) a11, _VCALL_ARG10(__VA_ARGS__) +#define _VCALL_ARG12(t, ...) typeof(t) a12, _VCALL_ARG11(__VA_ARGS__) +#define _VCALL_ARG13(t, ...) typeof(t) a13, _VCALL_ARG12(__VA_ARGS__) +#define _VCALL_ARG14(t, ...) typeof(t) a14, _VCALL_ARG14(__VA_ARGS__) +#define _VCALL_ARG15(t, ...) typeof(t) a15, _VCALL_ARG15(__VA_ARGS__) +#define _VCALL_ARG16(t, ...) typeof(t) a16, _VCALL_ARG16(__VA_ARGS__) + +#define _VCALL_ARG_N(x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, \ + x11, x12, x13, x14, x15, x16, N, ...) \ + _VCALL_ARG##N + +#define _VCALL_ARGLIST(...) \ + _VCALL_ARG_N(__VA_ARGS__ __VA_OPT__(,) \ + 16, 15, 14, 13, 12, 11, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01, 00) \ + (__VA_ARGS__) + +// aannd we need these as well... +#define _VCALL_PASS00() +#define _VCALL_PASS01() a1 +#define _VCALL_PASS02() a2, a1 +#define _VCALL_PASS03() a3, a2, a1 +#define _VCALL_PASS04() a4, a3, a2, a1 +#define _VCALL_PASS05() a5, _VCALL_PASS04() +#define _VCALL_PASS06() a6, _VCALL_PASS05() +#define _VCALL_PASS07() a7, _VCALL_PASS06() +#define _VCALL_PASS08() a8, _VCALL_PASS07() +#define _VCALL_PASS09() a9, _VCALL_PASS08() +#define _VCALL_PASS10() a10, _VCALL_PASS09() +#define _VCALL_PASS11() a11, _VCALL_PASS10() +#define _VCALL_PASS12() a12, _VCALL_PASS11() +#define _VCALL_PASS13() a13, _VCALL_PASS12() +#define _VCALL_PASS14() a14, _VCALL_PASS13() +#define _VCALL_PASS15() a15, _VCALL_PASS14() +#define _VCALL_PASS16() a16, _VCALL_PASS15() +#define _VCALL_PASS_N(x01, x02, x03, x04, x05, x06, x07, x08, x09, x10, x11, \ + x12, x13, x14, x15, x16, N, ...) \ + _VCALL_PASS##N + +#define _VCALL_PASSARGS(...) \ + _VCALL_PASS_N(__VA_ARGS__ __VA_OPT__(,) 16, 15, 14, 13, 12, 11, 10, 09, \ + 08, 07, 06, 05, 04, 03, 02, 01, 00)() + +#define VFUNC(x, name) ((*(name##_func **)(x))[vtidx_##name]) +#define VCALL(x, name, ...) VFUNC(x, name)(x, ##__VA_ARGS__) + +// even more magic: return keyword only if not void +#define _VCALL_RETKW_(x, n, ...) n +#define _VCALL_RETKW(...) _VCALL_RETKW_(__VA_ARGS__, return,) +#define _VCALL_RET_void() x, , +#define _VCALL_RET(t) _VCALL_RETKW(_VCALL_RET_##t()) + +// I thought static inline was supposed to prevent unused warnings??? +#if defined(__GNUC__) || defined(__clang__) +#define _VCALL_UNUSED __attribute__((unused)) +#else +#define _VCALL_UNUSED +#endif + #define _DECL_VFUNC_DYN(ret, conv, name, ...) \ - /* XXX: GCC extension, seems worthwhile vs having two macros for one thing. - Replace with __VA_OPT__(,) whenever that gets fully standardised. */ \ - typedef ret (*conv name##_func)(void *this, ##__VA_ARGS__); + typedef typeof(ret) (*conv name##_func)(void * __VA_OPT__(,) __VA_ARGS__); \ + static inline _VCALL_UNUSED typeof(ret) name(void *this __VA_OPT__(,) \ + _VCALL_ARGLIST(__VA_ARGS__)) { \ + _VCALL_RET(ret) VCALL(this, name __VA_OPT__(,) \ + _VCALL_PASSARGS(__VA_ARGS__)); \ + } #define _DECL_VFUNC(ret, conv, name, idx, ...) \ enum { vtidx_##name = (idx) }; \ - _DECL_VFUNC_DYN(ret, conv, name, ##__VA_ARGS__) + _DECL_VFUNC_DYN(ret, conv, name __VA_OPT__(,) __VA_ARGS__) /* Define a virtual function with a known index */ #define DECL_VFUNC(ret, name, idx, ...) \ - _DECL_VFUNC(ret, VCALLCONV, name, idx, ##__VA_ARGS__) + _DECL_VFUNC(ret, VCALLCONV, name, idx __VA_OPT__(,) __VA_ARGS__) /* Define a virtual function with a known index, without thiscall convention */ #define DECL_VFUNC_CDECL(ret, name, idx, ...) \ - _DECL_VFUNC(ret, , name, idx, ##__VA_ARGS__) + _DECL_VFUNC(ret, , name, idx __VA_OPT__(,) __VA_ARGS__) /* Define a virtual function with an index defined elsewhere */ #define DECL_VFUNC_DYN(ret, name, ...) \ - _DECL_VFUNC_DYN(ret, VCALLCONV, name, ##__VA_ARGS__) + _DECL_VFUNC_DYN(ret, VCALLCONV, name __VA_OPT__(,) __VA_ARGS__) /* Define a virtual function with an index defined elsewhere, without thiscall */ #define DECL_VFUNC_CDECLDYN(ret, name, ...) \ - _DECL_VFUNC_DYN(ret, , name, ##__VA_ARGS__) - -#define VFUNC(x, name) ((*(name##_func **)(x))[vtidx_##name]) -#define VCALL(x, name, ...) VFUNC(x, name)(x, ##__VA_ARGS__) + _DECL_VFUNC_DYN(ret, , name __VA_OPT__(,) __VA_ARGS__) #endif diff --git a/src/x86util.h b/src/x86util.h index 0ae89ae..85a824e 100644 --- a/src/x86util.h +++ b/src/x86util.h @@ -17,8 +17,6 @@ #ifndef INC_X86UTIL_H #define INC_X86UTIL_H -#include <stdbool.h> - #include "errmsg.h" #include "x86.h" @@ -35,3 +33,5 @@ } while (0) #endif + +// vi: sw=4 ts=4 noet tw=80 cc=80 |