diff options
| author | xolatile | 2025-07-16 23:07:43 +0200 |
|---|---|---|
| committer | xolatile | 2025-07-16 23:07:43 +0200 |
| commit | 7256502afa0babe60fcafbd2888cd3e33c3f9b6b (patch) | |
| tree | 8a8495662a69bdadc4b5d9152656b9f02a44d668 /src/shared/command.h | |
| parent | bc596ac9d4cdd00abf537b88d3c544be161330cc (diff) | |
| download | xolatile-badassbug-7256502afa0babe60fcafbd2888cd3e33c3f9b6b.tar.xz xolatile-badassbug-7256502afa0babe60fcafbd2888cd3e33c3f9b6b.tar.zst | |
Source code, broken...
Diffstat (limited to 'src/shared/command.h')
| -rw-r--r-- | src/shared/command.h | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/src/shared/command.h b/src/shared/command.h new file mode 100644 index 0000000..475e492 --- /dev/null +++ b/src/shared/command.h @@ -0,0 +1,335 @@ +// script binding functionality + +enum { VAL_NULL = 0, VAL_INT, VAL_FLOAT, VAL_STR, VAL_ANY, VAL_CODE, VAL_MACRO, VAL_IDENT }; + +enum +{ + CODE_START = 0, + CODE_OFFSET, + CODE_POP, + CODE_ENTER, + CODE_EXIT, + CODE_VAL, + CODE_VALI, + CODE_MACRO, + CODE_BOOL, + CODE_BLOCK, + CODE_COMPILE, + CODE_FORCE, + CODE_RESULT, + CODE_IDENT, CODE_IDENTU, CODE_IDENTARG, + CODE_COM, CODE_COMD, CODE_COMC, CODE_COMV, + CODE_CONC, CODE_CONCW, CODE_CONCM, CODE_DOWN, + CODE_SVAR, CODE_SVAR1, + CODE_IVAR, CODE_IVAR1, CODE_IVAR2, CODE_IVAR3, + CODE_FVAR, CODE_FVAR1, + CODE_LOOKUP, CODE_LOOKUPU, CODE_LOOKUPARG, CODE_ALIAS, CODE_ALIASU, CODE_ALIASARG, CODE_CALL, CODE_CALLU, CODE_CALLARG, + CODE_PRINT, + CODE_LOCAL, + + CODE_OP_MASK = 0x3F, + CODE_RET = 6, + CODE_RET_MASK = 0xC0, + + /* return type flags */ + RET_NULL = VAL_NULL<<CODE_RET, + RET_STR = VAL_STR<<CODE_RET, + RET_INT = VAL_INT<<CODE_RET, + RET_FLOAT = VAL_FLOAT<<CODE_RET, +}; + +enum { ID_VAR, ID_FVAR, ID_SVAR, ID_COMMAND, ID_ALIAS, ID_LOCAL }; + +enum { IDF_PERSIST = 1<<0, IDF_OVERRIDE = 1<<1, IDF_HEX = 1<<2, IDF_READONLY = 1<<3, IDF_OVERRIDDEN = 1<<4, IDF_UNKNOWN = 1<<5, IDF_ARG = 1<<6, IDF_EMUVAR = 1<<7 }; + +struct ident; + +struct identval +{ + union + { + int i; // ID_VAR, VAL_INT + float f; // ID_FVAR, VAL_FLOAT + char *s; // ID_SVAR, VAL_STR + const uint *code; // VAL_CODE + ident *id; // VAL_IDENT + }; +}; + +struct tagval : identval +{ + int type; + + void setint(int val) { type = VAL_INT; i = val; } + void setfloat(float val) { type = VAL_FLOAT; f = val; } + void setstr(char *val) { type = VAL_STR; s = val; } + void setnull() { type = VAL_NULL; i = 0; } + void setcode(const uint *val) { type = VAL_CODE; code = val; } + void setmacro(const uint *val) { type = VAL_MACRO; code = val; } + void setident(ident *val) { type = VAL_IDENT; id = val; } + + const char *getstr() const; + int getint() const; + float getfloat() const; + bool getbool() const; + + void cleanup(); +}; + +struct identstack +{ + identval val; + int valtype; + identstack *next; +}; + +union identvalptr +{ + int *i; // ID_VAR + float *f; // ID_FVAR + char **s; // ID_SVAR +}; + +typedef void (__cdecl *identfun)(); + +struct ident +{ + uchar type; // one of ID_* above + union + { + uchar valtype; // ID_ALIAS + uchar numargs; // ID_COMMAND + }; + ushort flags; + int index; + const char *name; + union + { + struct // ID_VAR, ID_FVAR, ID_SVAR + { + union + { + struct { int minval, maxval; }; // ID_VAR + struct { float minvalf, maxvalf; }; // ID_FVAR + }; + identvalptr storage; + identval overrideval; + }; + struct // ID_ALIAS + { + uint *code; + identval val; + identstack *stack; + }; + struct // ID_COMMAND + { + const char *args; + uint argmask; + }; + }; + identfun fun; // ID_VAR, ID_FVAR, ID_SVAR, ID_COMMAND + + ident() {} + // ID_VAR + ident(int t, const char *n, int m, int x, int *s, void *f = NULL, int flags = 0) + : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minval(m), maxval(x), fun((identfun)f) + { storage.i = s; } + // ID_FVAR + ident(int t, const char *n, float m, float x, float *s, void *f = NULL, int flags = 0) + : type(t), flags(flags | (m > x ? IDF_READONLY : 0)), name(n), minvalf(m), maxvalf(x), fun((identfun)f) + { storage.f = s; } + // ID_SVAR + ident(int t, const char *n, char **s, void *f = NULL, int flags = 0) + : type(t), flags(flags), name(n), fun((identfun)f) + { storage.s = s; } + // ID_ALIAS + ident(int t, const char *n, char *a, int flags) + : type(t), valtype(VAL_STR), flags(flags), name(n), code(NULL), stack(NULL) + { val.s = a; } + ident(int t, const char *n, int a, int flags) + : type(t), valtype(VAL_INT), flags(flags), name(n), code(NULL), stack(NULL) + { val.i = a; } + ident(int t, const char *n, float a, int flags) + : type(t), valtype(VAL_FLOAT), flags(flags), name(n), code(NULL), stack(NULL) + { val.f = a; } + ident(int t, const char *n, int flags) + : type(t), valtype(VAL_NULL), flags(flags), name(n), code(NULL), stack(NULL) + {} + ident(int t, const char *n, const tagval &v, int flags) + : type(t), valtype(v.type), flags(flags), name(n), code(NULL), stack(NULL) + { val = v; } + // ID_COMMAND + ident(int t, const char *n, const char *args, uint argmask, int numargs, void *f = NULL, int flags = 0) + : type(t), numargs(numargs), flags(flags), name(n), args(args), argmask(argmask), fun((identfun)f) + {} + + void changed() { if(fun) fun(); } + + void setval(const tagval &v) + { + valtype = v.type; + val = v; + } + + void setval(const identstack &v) + { + valtype = v.valtype; + val = v.val; + } + + void forcenull() + { + if(valtype==VAL_STR) delete[] val.s; + valtype = VAL_NULL; + } + + float getfloat() const; + int getint() const; + const char *getstr() const; + void getval(tagval &v) const; +}; + +extern void addident(ident *id); + +extern tagval *commandret; +extern const char *intstr(int v); +extern void intret(int v); +extern const char *floatstr(float v); +extern void floatret(float v); +extern void stringret(char *s); +extern void result(tagval &v); +extern void result(const char *s); + +static inline int parseint(const char *s) +{ + return int(strtoul(s, NULL, 0)); +} + +static inline float parsefloat(const char *s) +{ + // not all platforms (windows) can parse hexadecimal integers via strtod + char *end; + double val = strtod(s, &end); + return val || end==s || (*end!='x' && *end!='X') ? float(val) : float(parseint(s)); +} + +static inline void intformat(char *buf, int v, int len = 20) { nformatstring(buf, len, "%d", v); } +static inline void floatformat(char *buf, float v, int len = 20) { nformatstring(buf, len, v==int(v) ? "%.1f" : "%.6g", v); } + +static inline const char *getstr(const identval &v, int type) +{ + switch(type) + { + case VAL_STR: case VAL_MACRO: return v.s; + case VAL_INT: return intstr(v.i); + case VAL_FLOAT: return floatstr(v.f); + default: return ""; + } +} +inline const char *tagval::getstr() const { return ::getstr(*this, type); } +inline const char *ident::getstr() const { return ::getstr(val, valtype); } + +static inline int getint(const identval &v, int type) +{ + switch(type) + { + case VAL_INT: return v.i; + case VAL_FLOAT: return int(v.f); + case VAL_STR: case VAL_MACRO: return parseint(v.s); + default: return 0; + } +} +inline int tagval::getint() const { return ::getint(*this, type); } +inline int ident::getint() const { return ::getint(val, valtype); } + +static inline float getfloat(const identval &v, int type) +{ + switch(type) + { + case VAL_FLOAT: return v.f; + case VAL_INT: return float(v.i); + case VAL_STR: case VAL_MACRO: return parsefloat(v.s); + default: return 0.0f; + } +} +inline float tagval::getfloat() const { return ::getfloat(*this, type); } +inline float ident::getfloat() const { return ::getfloat(val, valtype); } + +inline void ident::getval(tagval &v) const +{ + switch(valtype) + { + case VAL_STR: case VAL_MACRO: v.setstr(newstring(val.s)); break; + case VAL_INT: v.setint(val.i); break; + case VAL_FLOAT: v.setfloat(val.f); break; + default: v.setnull(); break; + } +} + +// nasty macros for registering script functions, abuses globals to avoid excessive infrastructure +#define KEYWORD(name, type) UNUSED static bool __dummy_##name = addkeyword(type, #name) +#define COMMANDN(name, fun, nargs) UNUSED static bool __dummy_##fun = addcommand(#name, (identfun)fun, nargs) +#define COMMAND(name, nargs) COMMANDN(name, name, nargs) + +#define _VAR(name, global, min, cur, max, persist) int global = variable(#name, min, cur, max, &global, NULL, persist) +#define VARN(name, global, min, cur, max) _VAR(name, global, min, cur, max, 0) +#define VARNP(name, global, min, cur, max) _VAR(name, global, min, cur, max, IDF_PERSIST) +#define VARNR(name, global, min, cur, max) _VAR(name, global, min, cur, max, IDF_OVERRIDE) +#define VAR(name, min, cur, max) _VAR(name, name, min, cur, max, 0) +#define VARP(name, min, cur, max) _VAR(name, name, min, cur, max, IDF_PERSIST) +#define VARR(name, min, cur, max) _VAR(name, name, min, cur, max, IDF_OVERRIDE) +#define _VARF(name, global, min, cur, max, body, persist) void var_##name(); int global = variable(#name, min, cur, max, &global, var_##name, persist); void var_##name() { body; } +#define VARFN(name, global, min, cur, max, body) _VARF(name, global, min, cur, max, body, 0) +#define VARF(name, min, cur, max, body) _VARF(name, name, min, cur, max, body, 0) +#define VARFP(name, min, cur, max, body) _VARF(name, name, min, cur, max, body, IDF_PERSIST) +#define VARFR(name, min, cur, max, body) _VARF(name, name, min, cur, max, body, IDF_OVERRIDE) +#define VARFNP(name, global, min, cur, max, body) _VARF(name, global, min, cur, max, body, IDF_PERSIST) + +#define _HVAR(name, global, min, cur, max, persist) int global = variable(#name, min, cur, max, &global, NULL, persist | IDF_HEX) +#define HVARN(name, global, min, cur, max) _HVAR(name, global, min, cur, max, 0) +#define HVARNP(name, global, min, cur, max) _HVAR(name, global, min, cur, max, IDF_PERSIST) +#define HVARNR(name, global, min, cur, max) _HVAR(name, global, min, cur, max, IDF_OVERRIDE) +#define HVAR(name, min, cur, max) _HVAR(name, name, min, cur, max, 0) +#define HVARP(name, min, cur, max) _HVAR(name, name, min, cur, max, IDF_PERSIST) +#define HVARR(name, min, cur, max) _HVAR(name, name, min, cur, max, IDF_OVERRIDE) +#define _HVARF(name, global, min, cur, max, body, persist) void var_##name(); int global = variable(#name, min, cur, max, &global, var_##name, persist | IDF_HEX); void var_##name() { body; } +#define HVARFN(name, global, min, cur, max, body) _HVARF(name, global, min, cur, max, body, 0) +#define HVARF(name, min, cur, max, body) _HVARF(name, name, min, cur, max, body, 0) +#define HVARFP(name, min, cur, max, body) _HVARF(name, name, min, cur, max, body, IDF_PERSIST) +#define HVARFR(name, min, cur, max, body) _HVARF(name, name, min, cur, max, body, IDF_OVERRIDE) + +#define _FVAR(name, global, min, cur, max, persist) float global = fvariable(#name, min, cur, max, &global, NULL, persist) +#define FVARN(name, global, min, cur, max) _FVAR(name, global, min, cur, max, 0) +#define FVARNP(name, global, min, cur, max) _FVAR(name, global, min, cur, max, IDF_PERSIST) +#define FVARNR(name, global, min, cur, max) _FVAR(name, global, min, cur, max, IDF_OVERRIDE) +#define FVAR(name, min, cur, max) _FVAR(name, name, min, cur, max, 0) +#define FVARP(name, min, cur, max) _FVAR(name, name, min, cur, max, IDF_PERSIST) +#define FVARR(name, min, cur, max) _FVAR(name, name, min, cur, max, IDF_OVERRIDE) +#define _FVARF(name, global, min, cur, max, body, persist) void var_##name(); float global = fvariable(#name, min, cur, max, &global, var_##name, persist); void var_##name() { body; } +#define FVARFN(name, global, min, cur, max, body) _FVARF(name, global, min, cur, max, body, 0) +#define FVARF(name, min, cur, max, body) _FVARF(name, name, min, cur, max, body, 0) +#define FVARFP(name, min, cur, max, body) _FVARF(name, name, min, cur, max, body, IDF_PERSIST) +#define FVARFR(name, min, cur, max, body) _FVARF(name, name, min, cur, max, body, IDF_OVERRIDE) + +#define _SVAR(name, global, cur, persist) char *global = svariable(#name, cur, &global, NULL, persist) +#define SVARN(name, global, cur) _SVAR(name, global, cur, 0) +#define SVARNP(name, global, cur) _SVAR(name, global, cur, IDF_PERSIST) +#define SVARNR(name, global, cur) _SVAR(name, global, cur, IDF_OVERRIDE) +#define SVAR(name, cur) _SVAR(name, name, cur, 0) +#define SVARP(name, cur) _SVAR(name, name, cur, IDF_PERSIST) +#define SVARR(name, cur) _SVAR(name, name, cur, IDF_OVERRIDE) +#define _SVARF(name, global, cur, body, persist) void var_##name(); char *global = svariable(#name, cur, &global, var_##name, persist); void var_##name() { body; } +#define SVARFN(name, global, cur, body) _SVARF(name, global, cur, body, 0) +#define SVARF(name, cur, body) _SVARF(name, name, cur, body, 0) +#define SVARFP(name, cur, body) _SVARF(name, name, cur, body, IDF_PERSIST) +#define SVARFR(name, cur, body) _SVARF(name, name, cur, body, IDF_OVERRIDE) + +// anonymous inline commands, uses nasty template trick with line numbers to keep names unique +#define ICOMMANDNS(name, cmdname, nargs, proto, b) template<int N> struct cmdname; template<> struct cmdname<__LINE__> { static bool init; static void run proto; }; bool cmdname<__LINE__>::init = addcommand(name, (identfun)cmdname<__LINE__>::run, nargs); void cmdname<__LINE__>::run proto \ + { b; } +#define ICOMMANDN(name, cmdname, nargs, proto, b) ICOMMANDNS(#name, cmdname, nargs, proto, b) +#define ICOMMANDNAME(name) _icmd_##name +#define ICOMMAND(name, nargs, proto, b) ICOMMANDN(name, ICOMMANDNAME(name), nargs, proto, b) +#define ICOMMANDSNAME _icmds_ +#define ICOMMANDS(name, nargs, proto, b) ICOMMANDNS(name, ICOMMANDSNAME, nargs, proto, b) + |
