summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--TODO/.errmsg6
-rw-r--r--TODO/errmsg11
-rwxr-xr-xcompile8
-rw-r--r--compile.bat66
-rw-r--r--src/autojump.c11
-rw-r--r--src/con_.c3
-rw-r--r--src/demorec.c43
-rw-r--r--src/ent.c4
-rw-r--r--src/errmsg.c23
-rw-r--r--src/errmsg.h83
-rw-r--r--src/fov.c8
-rw-r--r--src/gameinfo.c29
-rw-r--r--src/hook.c10
-rw-r--r--src/l4dwarp.c5
-rw-r--r--src/nosleep.c9
-rw-r--r--src/portalcolours.c6
-rw-r--r--src/rinput.c11
-rw-r--r--src/sst.c36
18 files changed, 245 insertions, 127 deletions
diff --git a/TODO/.errmsg b/TODO/.errmsg
new file mode 100644
index 0000000..aefe3fc
--- /dev/null
+++ b/TODO/.errmsg
@@ -0,0 +1,6 @@
+Come up with a better error logging abstraction
+====
+This is done, see errmsg.h.
+
+Because it's all format string nonsense to talk to the engine, it's mostly a
+pile of macros, which is kind of wacky. But hey, it works.
diff --git a/TODO/errmsg b/TODO/errmsg
deleted file mode 100644
index 51b8aae..0000000
--- a/TODO/errmsg
+++ /dev/null
@@ -1,11 +0,0 @@
-Come up with a better error logging abstraction
-====
-Something like the BSD err/warn/errx/warnx maybe, although taking into account
-all the stupid Windows GetLastError differences too. As it stands, different
-source files have different ways of prefixing messages, a lot of strings are
-pretty redundant (would maybe be nice to have something closer to the DJB-style
-concatenated string messages to solve that problem?), and almost nothing bothers
-to include the actual system error string because doing so is currently doing
-annoying.
-
-pls fix
diff --git a/compile b/compile
index d921b78..6948527 100755
--- a/compile
+++ b/compile
@@ -28,9 +28,12 @@ fi
objs=
cc() {
objs="$objs .build/${1%%.c}.o"
+ _mn=" -DMODULE_NAME=${1%%.c}"
+ # ugly annoying special case
+ if [ "$_mn" = " -DMODULE_NAME=con_" ]; then _mn=" -DMODULE_NAME=con"
+ elif [ "$_mn" = "-DMODULE_NAME=sst" ]; then _mn=; fi
$CC -m32 -c -flto -fpic $cflags $warnings -I.build/include \
- -D_FILE_OFFSET_BITS=64 -DFILE_BASENAME="${1%%.c}" \
- -o ".build/${1%%.c}.o" "src/$1"
+ -D_FILE_OFFSET_BITS=64$_mn -o ".build/${1%%.c}.o" "src/$1"
}
ld() {
@@ -44,6 +47,7 @@ src="\
demorec.c
engineapi.c
ent.c
+ errmsg.c
extmalloc.c
fixes.c
fov.c
diff --git a/compile.bat b/compile.bat
index 60372a1..fa631b1 100644
--- a/compile.bat
+++ b/compile.bat
@@ -30,47 +30,63 @@ goto :main
:cc
for /F %%b in ("%1") do set basename=%%~nb
+set dmodname= -DMODULE_NAME=%basename%
+:: ugly annoying special cases
+if "%dmodname%"==" -DMODULE_NAME=con_" set dmodname= -DMODULE_NAME=con
+if "%dmodname%"==" -DMODULE_NAME=sst" set dmodname=
set objs=%objs% .build/%basename%.o
%CC% -m32 -c -flto %cflags% %warnings% -I.build/include -D_CRT_SECURE_NO_WARNINGS -D_DLL ^
--DWIN32_LEAN_AND_MEAN -DNOMINMAX -DFILE_BASENAME=%basename% -o .build/%basename%.o %1 || exit /b
+-DWIN32_LEAN_AND_MEAN -DNOMINMAX%dmodname% -o .build/%basename%.o %1 || exit /b
+goto :eof
+
+:src
goto :eof
:main
+
+set src=
+:: funny hack to build a list conveniently, lol.
+setlocal EnableDelayedExpansion
+for /f "tokens=2" %%f in ('findstr /B /C:":+ " "%~nx0"') do set src=!src! src/%%f
+setlocal DisableDelayedExpansion
+:+ autojump.c
+:+ con_.c
+:+ demorec.c
+:+ engineapi.c
+:+ ent.c
+:+ errmsg.c
+:+ extmalloc.c
+:+ fixes.c
+:+ fov.c
+:+ gamedata.c
+:+ gameinfo.c
+:+ hook.c
+:+ kv.c
+:+ l4dwarp.c
+:+ nosleep.c
+:+ portalcolours.c
+:+ rinput.c
+:+ sst.c
+:+ x86.c
+:: just tack these on, whatever
+if "%dbg%"=="1" (
+ set src=%src% src/dbg.c
+ set src=%src% src/udis86.c
+)
+
%HOSTCC% -municode -O2 %warnings% -D_CRT_SECURE_NO_WARNINGS ^
-o .build/codegen.exe src/build/codegen.c src/build/cmeta.c || exit /b
%HOSTCC% -municode -O2 %warnings% -D_CRT_SECURE_NO_WARNINGS ^
-o .build/mkgamedata.exe src/build/mkgamedata.c src/kv.c || exit /b
%HOSTCC% -municode -O2 %warnings% -D_CRT_SECURE_NO_WARNINGS -ladvapi32 ^
-o .build/mkentprops.exe src/build/mkentprops.c src/kv.c || exit /b
-.build\codegen.exe src/autojump.c src/con_.c src/demorec.c src/engineapi.c src/ent.c src/extmalloc.c src/fixes.c src/fov.c ^
-src/gamedata.c src/gameinfo.c src/hook.c src/kv.c src/l4dwarp.c src/nosleep.c src/portalcolours.c src/rinput.c src/sst.c src/x86.c || exit /b
+.build\codegen.exe%src% || exit /b
.build\mkgamedata.exe gamedata/engine.kv gamedata/gamelib.kv gamedata/inputsystem.kv || exit /b
.build\mkentprops.exe gamedata/entprops.kv || exit /b
llvm-rc /FO .build\dll.res src\dll.rc || exit /b
%CC% -shared -O0 -w -o .build/tier0.dll src/stubs/tier0.c
%CC% -shared -O0 -w -o .build/vstdlib.dll src/stubs/vstdlib.c
-call :cc src/autojump.c || exit /b
-call :cc src/con_.c || exit /b
-call :cc src/demorec.c || exit /b
-call :cc src/engineapi.c || exit /b
-call :cc src/ent.c || exit /b
-call :cc src/extmalloc.c || exit /b
-call :cc src/fixes.c || exit /b
-call :cc src/fov.c || exit /b
-call :cc src/gamedata.c || exit /b
-call :cc src/gameinfo.c || exit /b
-call :cc src/hook.c || exit /b
-call :cc src/kv.c || exit /b
-call :cc src/l4dwarp.c || exit /b
-call :cc src/nosleep.c || exit /b
-call :cc src/portalcolours.c || exit /b
-call :cc src/rinput.c || exit /b
-call :cc src/sst.c || exit /b
-call :cc src/x86.c || exit /b
-if "%dbg%"=="1" (
- call :cc src/dbg.c || exit /b
- call :cc src/udis86.c || exit /b
-)
+for %%b in (%src%) do ( call :cc %%b || exit /b )
if "%dbg%"=="1" (
:: ugh, microsoft.
set clibs=-lmsvcrtd -lvcruntimed -lucrtd
diff --git a/src/autojump.c b/src/autojump.c
index a8064da..e0b6a9f 100644
--- a/src/autojump.c
+++ b/src/autojump.c
@@ -18,6 +18,7 @@
#include "con_.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "gamedata.h"
#include "intdefs.h"
#include "hook.h"
@@ -63,30 +64,30 @@ static bool unprot(void *gm) {
void **vtable = *(void ***)gm;
bool ret = os_mprot(vtable + vtidx_CheckJumpButton, sizeof(void *),
PAGE_READWRITE);
- if (!ret) con_warn("autojump: couldn't make memory writable\n");
+ if (!ret) errmsg_errorsys("couldn't make virtual table writable");
return ret;
}
bool autojump_init(void) {
// TODO(featgen): auto-check these factories
if (!factory_client || !factory_server) {
- con_warn("autojump: missing required factories\n");
+ errmsg_warnx("missing required factories");
return false;
}
if (!has_vtidx_CheckJumpButton || !has_off_mv) {
- con_warn("autojump: missing gamedata entries for this engine\n");
+ errmsg_warnx("missing gamedata entries for this engine");
return false;
}
gmsv = factory_server("GameMovement001", 0);
if (!gmsv) {
- con_warn("autojump: couldn't get server-side game movement interface\n");
+ errmsg_errorx("couldn't get server-side game movement interface");
return false;
}
if (!unprot(gmsv)) return false;
gmcl = factory_client("GameMovement001", 0);
if (!gmcl) {
- con_warn("autojump: couldn't get client-side game movement interface\n");
+ errmsg_errorx("couldn't get client-side game movement interface");
return false;
}
if (!unprot(gmcl)) return false;
diff --git a/src/con_.c b/src/con_.c
index 5cfe046..f259324 100644
--- a/src/con_.c
+++ b/src/con_.c
@@ -399,6 +399,9 @@ static void helpuserhelpus(int pluginver, char ifaceverchar) {
con_msg("\n");
}
+// note: for now at least, not using errmsg_*() macros here because it doesn't
+// really make sense for these messages to be coming from "con"
+
static void warnoe(void) {
con_warn("sst: error: this engine version is not yet supported\n");
}
diff --git a/src/demorec.c b/src/demorec.c
index dc9e899..156e7c6 100644
--- a/src/demorec.c
+++ b/src/demorec.c
@@ -22,6 +22,7 @@
#include "con_.h"
#include "demorec.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "gamedata.h"
#include "gameinfo.h"
#include "hook.h"
@@ -116,23 +117,19 @@ static void hook_record_cb(const struct con_cmdargs *args) {
// we could use open(O_DIRECTORY), but that's not a thing on
// windows, of course.
struct os_stat s;
+ static const char *const errpfx = "ERROR: can't record demo: ";
if (os_stat(dir, &s) == -1) {
- con_warn("ERROR: can't record demo: ");
if (errno == ENOENT) {
- con_warn("subdirectory %.*s doesn't exist\n",
+ con_warn("%ssubdirectory %.*s doesn't exist\n", errpfx,
argdirlen, arg);
}
else {
- con_warn("%s\n", strerror(errno)); // guess this'll do.
+ con_warn("%s%s\n", errpfx, strerror(errno));
}
return;
}
if (!S_ISDIR(s.st_mode)) {
- // TODO(errmsg): duping this warning call to avoid duping
- // the string data, very stupid, oh well. if/when we have
- // New And Improved Logging this can be tidied up...
- con_warn("ERROR: can't record demo: ");
- con_warn("the path %.*s is not a directory\n",
+ con_warn("%spath %.*s is not a directory\n", errpfx,
argdirlen, arg);
return;
}
@@ -157,10 +154,10 @@ static void hook_stop_cb(const struct con_cmdargs *args) {
// XXX: probably want some general foreach-instruction macro once we start doing
// this kind of hackery in multiple different places
-#define NEXT_INSN(p) do { \
+#define NEXT_INSN(p, tgt) do { \
int _len = x86_len(p); \
if (_len == -1) { \
- con_warn("demorec: %s: unknown or invalid instruction\n", __func__); \
+ errmsg_errorx("unknown or invalid instruction looking for %s", tgt); \
return false; \
} \
(p) += _len; \
@@ -178,7 +175,7 @@ static inline bool find_demorecorder(struct con_cmd *cmd_stop) {
demorecorder = *indirect;
return true;
}
- NEXT_INSN(p);
+ NEXT_INSN(p, "demorecorder object");
}
#else
#warning TODO(linux): implement linux equivalent (cdecl!)
@@ -202,7 +199,7 @@ static inline bool find_recmembers(void *stoprecording) {
recording = mem_offset(demorecorder, mem_load32(p + 2));
}
if (recording && demonum) return true; // blegh
- NEXT_INSN(p);
+ NEXT_INSN(p, "state variables");
}
#else // linux is probably different here idk
#warning TODO(linux): implement linux equivalent (???)
@@ -212,42 +209,34 @@ static inline bool find_recmembers(void *stoprecording) {
bool demorec_init(void) {
if (!has_vtidx_StopRecording) {
- con_warn("demorec: missing gamedata entries for this engine\n");
+ errmsg_warnx("missing gamedata entries for this engine");
return false;
}
cmd_record = con_findcmd("record");
if (!cmd_record) { // can *this* even happen? I hope not!
- con_warn("demorec: couldn't find \"record\" command\n");
+ errmsg_errorx("couldn't find \"record\" command");
return false;
}
orig_record_cb = con_getcmdcb(cmd_record);
cmd_stop = con_findcmd("stop");
if (!cmd_stop) {
- con_warn("demorec: couldn't find \"stop\" command\n");
+ errmsg_errorx("couldn't find \"stop\" command");
return false;
}
orig_stop_cb = con_getcmdcb(cmd_stop);
if (!find_demorecorder(cmd_stop)) {
- con_warn("demorec: couldn't find demo recorder instance\n");
+ errmsg_errorx("couldn't find demo recorder instance");
return false;
}
void **vtable = *(void ***)demorecorder;
// XXX: 16 is totally arbitrary here! figure out proper bounds later
if (!os_mprot(vtable, 16 * sizeof(void *), PAGE_READWRITE)) {
- // TODO(errmsg): this is one of the only places I apparently bothered
- // to properly log this stuff. really should solve this at some point
-#ifdef _WIN32
- char err[128];
- OS_WINDOWS_ERROR(err);
-#else
- const char *err = strerror(errno);
-#endif
- con_warn("demorec: couldn't make memory writable: %s\n", err);
+ errmsg_errorsys("couldn't make virtual table writable");
return false;
}
if (!find_recmembers(vtable[vtidx_StopRecording])) {
- con_warn("demorec: couldn't find m_bRecording and m_nDemoNumber\n");
+ errmsg_errorx("couldn't find recording state variables");
return false;
}
@@ -357,7 +346,7 @@ DECL_VFUNC_DYN(int, GetEngineBuildNumber)
bool demorec_custom_init(void) {
if (!has_vtidx_GetEngineBuildNumber || !has_vtidx_RecordPacket) {
- con_warn("demorec: custom: missing gamedata entries for this engine\n");
+ errmsg_warnx("custom: missing gamedata entries for this engine");
return false;
}
diff --git a/src/ent.c b/src/ent.c
index 2e47208..392fceb 100644
--- a/src/ent.c
+++ b/src/ent.c
@@ -16,8 +16,8 @@
#include <stdbool.h>
-#include "con_.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "gamedata.h"
#include "gametype.h"
#include "intdefs.h"
@@ -52,7 +52,7 @@ bool ent_init(void) {
edicts = mem_offset(globalvars, off_edicts);
return true;
}
- con_warn("ent: not implemented for this engine\n");
+ errmsg_warnx("not implemented for this engine");
return false;
}
diff --git a/src/errmsg.c b/src/errmsg.c
new file mode 100644
index 0000000..63af533
--- /dev/null
+++ b/src/errmsg.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "con_.h"
+
+const char msg_note[] = "note: ";
+const char msg_warn[] = "warning: ";
+const char msg_error[] = "error: ";
+
+// vi: sw=4 ts=4 noet tw=80 cc=80
diff --git a/src/errmsg.h b/src/errmsg.h
new file mode 100644
index 0000000..17a4457
--- /dev/null
+++ b/src/errmsg.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INC_ERRMSG_H
+#define INC_ERRMSG_H
+
+#include "con_.h"
+#include "os.h"
+
+extern const char msg_note[], msg_warn[], msg_error[];
+
+#define _ERRMSG_STR1(x) #x
+#define _ERRMSG_STR(x) _ERRMSG_STR1(x)
+
+#ifdef MODULE_NAME
+#define _errmsg_msg(mod, msg, s, ...) \
+ con_warn("sst: %s: %s" s ": %s\n", mod, msg, __VA_ARGS__)
+// XXX: can we avoid using the ##__VA_ARGS__ extension here somehow?
+#define _errmsg_msgx(mod, msg, s, ...) \
+ con_warn("sst: %s: %s" s "\n", mod, msg, ##__VA_ARGS__)
+#else
+// dumb hack: we don't want sst.c to say "sst: sst:" - easier to just drop the
+// module parameter here so all the stuff below can just remain the same
+#define _errmsg_msg(ignored, msg, s, ...) \
+ con_warn("sst: %s" s ": %s\n", msg, __VA_ARGS__)
+#define _errmsg_msgx(ignored, msg, s, ...) \
+ con_warn("sst: %s" s "\n", msg, ##__VA_ARGS__)
+#endif
+
+#define _errmsg_std(msg, ...) \
+ _errmsg_msg(_ERRMSG_STR(MODULE_NAME), msg, __VA_ARGS__, strerror(errno))
+
+#define _errmsg_x(msg, ...) \
+ _errmsg_msgx(_ERRMSG_STR(MODULE_NAME), msg, __VA_ARGS__)
+
+#ifdef _WIN32
+#define _errmsg_sys(msg, ...) do { \
+ char _warnsys_buf[512]; \
+ OS_WINDOWS_ERROR(_warnsys_buf); \
+ _errmsg_msg(_ERRMSG_STR(MODULE_NAME), msg, __VA_ARGS__, _warnsys_buf); \
+} while (0)
+#define _errmsg_dl _errmsg_sys
+#else
+#define _errmsg_sys _errmsg_std
+static inline const char *_errmsg_dlerror(void) {
+ const char *e = dlerror();
+ if (!e) return "Unknown error"; // just in case, better avoid weirdness!
+ return e;
+}
+#define _errmsg_dl(msg, ...) \
+ _errmsg_msg(_ERRMSG_STR(MODULE_NAME), msg, __VA_ARGS__, _errmsg_dlerror());
+#endif
+
+// Reminder: will need add warnsock/errsock if we ever do stuff with sockets,
+// because of Windows's WSAGetLastError() abomination.
+#define errmsg_warnstd(...) _errmsg_std(msg_warn, __VA_ARGS__)
+#define errmsg_warnsys(...) _errmsg_sys(msg_warn, __VA_ARGS__)
+#define errmsg_warndl(...) _errmsg_dl(msg_warn, __VA_ARGS__)
+#define errmsg_warnx(...) _errmsg_x(msg_warn, __VA_ARGS__)
+
+#define errmsg_errorstd(...) _errmsg_std(msg_error, __VA_ARGS__)
+#define errmsg_errorsys(...) _errmsg_sys(msg_error, __VA_ARGS__)
+#define errmsg_errordl(...) _errmsg_dl(msg_error, __VA_ARGS__)
+#define errmsg_errorx(...) _errmsg_x(msg_error, __VA_ARGS__)
+
+#define errmsg_note(...) _errmsg_x(msg_note, __VA_ARGS__)
+
+#endif
+
+// vi: sw=4 ts=4 noet tw=80 cc=80
diff --git a/src/fov.c b/src/fov.c
index 151fa2e..c090651 100644
--- a/src/fov.c
+++ b/src/fov.c
@@ -21,6 +21,7 @@
#include "con_.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "ent.h"
#include "gametype.h"
#include "hook.h"
@@ -57,7 +58,8 @@ static bool find_SetDefaultFOV(struct con_cmd *fov) {
}
int len = x86_len(p);
if (len == -1) {
- con_warn("fov: find_SetDefaultFOV: unknown or invalid instruction\n");
+ errmsg_errorx("unknown or invalid instruction looking for %s",
+ "SetDefaultFOV");
return false;
}
p += len;
@@ -100,13 +102,13 @@ bool fov_init(bool has_ent) {
real_fov_desired = fov_desired;
}
if (!find_SetDefaultFOV(cmd_fov)) {
- con_warn("fov: couldn't find SetDefaultFOV function\n");
+ errmsg_errorx("couldn't find SetDefaultFOV function");
return false;
}
orig_SetDefaultFOV = (SetDefaultFOV_func)hook_inline(
(void *)orig_SetDefaultFOV, (void *)&hook_SetDefaultFOV);
if (!orig_SetDefaultFOV) {
- con_warn("fov: couldn't hook SetDefaultFOV function\n");
+ errmsg_errorsys("couldn't hook SetDefaultFOV function");
return false;
}
diff --git a/src/gameinfo.c b/src/gameinfo.c
index 36c9402..8fe17d9 100644
--- a/src/gameinfo.c
+++ b/src/gameinfo.c
@@ -21,6 +21,7 @@
#include "con_.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "gametype.h"
#include "intdefs.h"
#include "kv.h"
@@ -72,8 +73,7 @@ static void trygamelib(const os_char *path, os_char *outpath) {
os_strcpy(outpath, path);
}
else if (errno != ENOENT) {
- con_warn("gameinfo: failed to access %" fS ": %s\n", path,
- strerror(errno));
+ errmsg_warnstd("failed to access %" fS, path);
}
}
@@ -132,7 +132,7 @@ static inline void dolibsearch(const char *p, uint len, bool isgamebin,
int fmtspace = spaceleft - (sizeof("client" OS_DLSUFFIX) - 1);
int ret = os_snprintf(outp, fmtspace, fmt, len, p);
if (ret >= fmtspace) {
-toobig: con_warn("gameinfo: skipping an overly long search path\n");
+toobig: errmsg_warnx("skipping an overly long search path");
return;
}
outp += ret;
@@ -227,8 +227,7 @@ static void kv_cb(enum kv_token type, const char *p, uint len, void *_ctxt) {
if (ctxt->dontcarelvl) --ctxt->dontcarelvl; else --ctxt->nestlvl;
break;
case KV_COND_PREFIX: case KV_COND_SUFFIX:
- con_warn("gameinfo: warning: just ignoring conditional \"%.*s\"",
- len, p);
+ errmsg_warnx("just ignoring conditional \"%.*s\"", len, p);
}
#undef MATCH
}
@@ -237,7 +236,7 @@ DECL_VFUNC_DYN(const char *, GetGameDirectory)
bool gameinfo_init(void) {
if (!has_vtidx_GetGameDirectory) {
- con_warn("gameinfo: unsupported VEngineClient interface\n");
+ errmsg_errorx("unsupported VEngineClient interface");
return false;
}
@@ -245,13 +244,12 @@ bool gameinfo_init(void) {
// base dir is just cwd
os_char cwd[PATH_MAX];
if (!os_getcwd(cwd, sizeof(cwd) / sizeof(*cwd))) {
- con_warn("gameinfo: couldn't get working directory: %s\n",
- strerror(errno));
+ errmsg_errorstd("couldn't get working directory");
return false;
}
int len = os_strlen(cwd);
if (len + sizeof("/bin") > sizeof(bindir) / sizeof(*bindir)) {
- con_warn("gameinfo: working directory path is too long!\n");
+ errmsg_errorx("working directory path is too long!");
return false;
}
memcpy(bindir, cwd, len * sizeof(*cwd));
@@ -261,7 +259,7 @@ bool gameinfo_init(void) {
int gamedirlen = _snwprintf(gamedir, sizeof(gamedir) / sizeof(*gamedir),
L"%S", VCALL(engclient, GetGameDirectory));
if (gamedirlen < 0) { // encoding error??? ugh...
- con_warn("gameinfo: invalid game directory path!\n");
+ errmsg_errorx("invalid game directory path!");
return false;
}
#else
@@ -271,7 +269,7 @@ bool gameinfo_init(void) {
#endif
if (gamedirlen + sizeof("/gameinfo.txt") > sizeof(gamedir) /
sizeof(*gamedir)) {
- con_warn("gameinfo: game directory path is too long!\n");
+ errmsg_errorx("game directory path is too long!");
return false;
}
os_char gameinfopath[PATH_MAX];
@@ -281,7 +279,7 @@ bool gameinfo_init(void) {
14 * sizeof(os_char));
int fd = os_open(gameinfopath, O_RDONLY);
if (fd == -1) {
- con_warn("gameinfo: couldn't open gameinfo.txt: %s\n", strerror(errno));
+ errmsg_errorstd("couldn't open gameinfo.txt");
return false;
}
char buf[1024];
@@ -290,8 +288,7 @@ bool gameinfo_init(void) {
int nread;
while (nread = read(fd, buf, sizeof(buf))) {
if (nread == -1) {
- con_warn("gameinfo: couldn't read gameinfo.txt: %s\n",
- strerror(errno));
+ errmsg_errorstd("couldn't read gameinfo.txt");
goto e;
}
if (!kv_parser_feed(&kvp, buf, nread, &kv_cb, &ctxt)) goto ep;
@@ -303,8 +300,8 @@ bool gameinfo_init(void) {
if (GAMETYPE_MATCHES(L4DS)) gameinfo_title = "Left 4 Dead: Survivors";
return true;
-ep: con_warn("gameinfo: couldn't parse gameinfo.txt (%d:%d): %s\n",
- kvp.line, kvp.col, kvp.errmsg);
+ep: errmsg_errorx("couldn't parse gameinfo.txt (%d:%d): %s", kvp.line, kvp.col,
+ kvp.errmsg);
e: close(fd);
return false;
}
diff --git a/src/hook.c b/src/hook.c
index 9320636..bca226d 100644
--- a/src/hook.c
+++ b/src/hook.c
@@ -48,20 +48,24 @@ void *hook_inline(void *func_, void *target) {
if (!os_mprot(func, 5, PAGE_EXECUTE_READWRITE)) return false;
int len = 0;
for (;;) {
+ // FIXME: these cases may result in somewhat dodgy error messaging. They
+ // shouldn't happen anyway though. Maybe if we're confident we just
+ // compile 'em out of release builds some day, but that sounds a little
+ // scary. For now prefering confusing messages over crashes, I guess.
if (func[len] == X86_CALL) {
con_warn("hook_inline: can't trampoline call instructions\n");
- return false;
+ return 0;
}
int ilen = x86_len(func + len);
if (ilen == -1) {
con_warn("hook_inline: unknown or invalid instruction\n");
- return false;
+ return 0;
}
len += ilen;
if (len >= 5) break;
if (func[len] == X86_JMPIW) {
con_warn("hook_inline: can't trampoline jmp instructions\n");
- return false;
+ return 0;
}
}
// for simplicity, just bump alloc the trampoline. no need to free anyway
diff --git a/src/l4dwarp.c b/src/l4dwarp.c
index 20f52a5..7a77427 100644
--- a/src/l4dwarp.c
+++ b/src/l4dwarp.c
@@ -20,6 +20,7 @@
#include "con_.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "ent.h"
#include "gamedata.h"
#include "gametype.h"
@@ -34,7 +35,7 @@ DECL_VFUNC_DYN(void, Teleport, const struct vec3f *pos, const struct vec3f *ang,
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) { con_warn("error: couldn't access player entity\n"); return; }
+ if (!ed) { errmsg_errorx("couldn't access player entity"); return; }
void *e = VCALL(ed->ent_unknown, GetBaseEntity); // is this call required?
struct vec3f *org = mem_offset(e, off_entpos);
struct vec3f *ang = mem_offset(e, off_eyeang);
@@ -50,7 +51,7 @@ DEF_CCMD_HERE_UNREG(sst_l4d_testwarp, "Simulate a bot warping to you",
bool l4dwarp_init(void) {
if (!GAMETYPE_MATCHES(L4Dx)) return false;
if (!has_off_entpos || !has_off_eyeang || !has_vtidx_Teleport) {
- con_warn("l4dwarp: missing gamedata entries for this engine\n");
+ errmsg_warnx("missing gamedata entries for this engine");
return false;
}
con_reg(sst_l4d_testwarp);
diff --git a/src/nosleep.c b/src/nosleep.c
index c1c5a9b..c849f04 100644
--- a/src/nosleep.c
+++ b/src/nosleep.c
@@ -18,6 +18,7 @@
#include "con_.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "gamedata.h"
#include "hook.h"
#include "os.h"
@@ -41,22 +42,22 @@ bool nosleep_init(void) {
con_reg(engine_no_focus_sleep);
// TODO(featgen): auto-check these factories
if (!factory_inputsystem) {
- con_warn("nosleep: missing required factories\n");
+ errmsg_warnx("missing required factories");
return false;
}
if (!has_vtidx_SleepUntilInput) {
- con_warn("nosleep: missing gamedata entries for this engine\n");
+ errmsg_warnx("missing gamedata entries for this engine");
return false;
}
void *insys = factory_inputsystem("InputSystemVersion001", 0);
if (!insys) {
- con_warn("nosleep: couldn't get input system interface\n");
+ errmsg_errorx("couldn't get input system interface");
return false;
}
vtable = *(void ***)insys;
if (!os_mprot(vtable + vtidx_SleepUntilInput, sizeof(void *),
PAGE_READWRITE)) {
- con_warn("nosleep: couldn't make memory writable\n");
+ errmsg_errorx("couldn't make virtual table writable");
return false;
}
orig_SleepUntilInput = (SleepUntilInput_func)hook_vtable(vtable,
diff --git a/src/portalcolours.c b/src/portalcolours.c
index 00eb96b..750ee19 100644
--- a/src/portalcolours.c
+++ b/src/portalcolours.c
@@ -19,7 +19,7 @@
#include "con_.h"
#include "engineapi.h"
-#include "extmalloc.h"
+#include "errmsg.h"
#include "gametype.h"
#include "hook.h"
#include "intdefs.h"
@@ -123,13 +123,13 @@ bool portalcolours_init(void *clientlib) { // ... should libs be globals?
if (!GAMETYPE_MATCHES(Portal)) return false;
#ifdef _WIN32
if (!find_UTIL_Portal_Color(clientlib)) {
- con_warn("portalcolours: error: couldn't find UTIL_Portal_Color\n");
+ errmsg_errorx("couldn't find UTIL_Portal_Color");
return false;
}
orig_UTIL_Portal_Color = (UTIL_Portal_Color_func)hook_inline(
(void *)orig_UTIL_Portal_Color, (void *)&hook_UTIL_Portal_Color);
if (!orig_UTIL_Portal_Color) {
- con_warn("portalcolours: error: couldn't hook UTIL_Portal_Color\n");
+ errmsg_errorsys("couldn't hook UTIL_Portal_Color");
return false;
}
sst_portal_colour0->base.flags &= ~CON_HIDDEN;
diff --git a/src/rinput.c b/src/rinput.c
index 6286eda..1b81cf5 100644
--- a/src/rinput.c
+++ b/src/rinput.c
@@ -22,6 +22,7 @@
#include "con_.h"
#include "hook.h"
+#include "errmsg.h"
#include "intdefs.h"
// We reimplement m_rawinput by hooking cursor functions in the same way as
@@ -31,8 +32,6 @@
// loaded. If m_rawinput already exists, we do nothing; people should use the
// game's native raw input instead in that case.
-#define ERR "rinput: error: "
-
#define USAGEPAGE_MOUSE 1
#define USAGE_MOUSE 2
@@ -106,18 +105,18 @@ bool rinput_init(void) {
orig_GetCursorPos = (GetCursorPos_func)hook_inline((void *)&GetCursorPos,
(void *)&hook_GetCursorPos);
if (!orig_GetCursorPos) {
- con_warn(ERR "couldn't hook GetCursorPos\n");
+ errmsg_errorsys("couldn't hook %s", "GetCursorPos");
goto e0;
}
orig_SetCursorPos = (SetCursorPos_func)hook_inline((void *)&SetCursorPos,
(void *)&hook_SetCursorPos);
if (!orig_SetCursorPos) {
- con_warn(ERR "couldn't hook SetCursorPos\n");
+ errmsg_errorsys("couldn't hook %s", "SetCursorPos");
goto e1;
}
inwin = CreateWindowExW(0, L"RInput", L"RInput", 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (!inwin) {
- con_warn(ERR " couldn't create input window\n");
+ errmsg_errorsys("couldn't create input window");
goto e2;
}
RAWINPUTDEVICE rd = {
@@ -126,7 +125,7 @@ bool rinput_init(void) {
.usUsage = USAGE_MOUSE
};
if (!RegisterRawInputDevices(&rd, 1, sizeof(rd))) {
- con_warn(ERR " couldn't create raw mouse device\n");
+ errmsg_errorsys("couldn't create raw mouse device");
goto e3;
}
diff --git a/src/sst.c b/src/sst.c
index 39996c9..2ba4e9e 100644
--- a/src/sst.c
+++ b/src/sst.c
@@ -25,6 +25,7 @@
#include "con_.h"
#include "demorec.h"
#include "engineapi.h"
+#include "errmsg.h"
#include "ent.h"
#include "fov.h"
#include "fixes.h"
@@ -80,14 +81,14 @@ DEF_CCMD_HERE(sst_autoload_enable, "Register SST to load on game startup", 0) {
os_char path[PATH_MAX];
if (!os_dlfile(ownhandle(), path, sizeof(path) / sizeof(*path))) {
// hopefully by this point this won't happen, but, like, never know
- con_warn("error: failed to get path to plugin\n");
+ errmsg_errordl("failed to get path to plugin");
return;
}
os_char relpath[PATH_MAX];
#ifdef _WIN32
if (!PathRelativePathToW(relpath, searchdir, FILE_ATTRIBUTE_DIRECTORY,
path, 0)) {
- con_warn("error: couldn't compute a relative path for some reason\n");
+ errmsg_errorsys("couldn't compute a relative path for some reason");
return;
}
// arbitrary aesthetic judgement
@@ -98,13 +99,13 @@ DEF_CCMD_HERE(sst_autoload_enable, "Register SST to load on game startup", 0) {
int len = os_strlen(gameinfo_gamedir);
if (len + sizeof("/addons/" VDFBASENAME ".vdf") >
sizeof(path) / sizeof(*path)) {
- con_warn("error: path to VDF is too long\n");
+ errmsg_errorx("path to VDF is too long");
return;
}
memcpy(path, gameinfo_gamedir, len * sizeof(*gameinfo_gamedir));
memcpy(path + len, OS_LIT("/addons"), 8 * sizeof(os_char));
if (os_mkdir(path) == -1 && errno != EEXIST) {
- con_warn("error: couldn't create %" fS ": %s\n", path, strerror(errno));
+ errmsg_errorstd("couldn't create %" fS, path);
return;
}
memcpy(path + len + sizeof("/addons") - 1,
@@ -112,7 +113,7 @@ DEF_CCMD_HERE(sst_autoload_enable, "Register SST to load on game startup", 0) {
sizeof("/" VDFBASENAME ".vdf") * sizeof(os_char));
FILE *f = os_fopen(path, OS_LIT("wb"));
if (!f) {
- con_warn("error: couldn't open %" fS ": %s", path, strerror(errno));
+ errmsg_errorstd("couldn't open %" fS, path);
return;
}
// XXX: oh, crap, we're clobbering unicode again. welp, let's hope the
@@ -120,7 +121,7 @@ DEF_CCMD_HERE(sst_autoload_enable, "Register SST to load on game startup", 0) {
// doesn't matter.
if (fprintf(f, "Plugin { file \"%" fS "\" }\n", relpath) < 0 ||
fflush(f) == -1) {
- con_warn("error: couldn't write to %" fS ": %s", path, strerror(errno));
+ errmsg_errorstd("couldn't write to %" fS, path);
}
fclose(f);
}
@@ -130,14 +131,14 @@ DEF_CCMD_HERE(sst_autoload_disable, "Stop loading SST on game startup", 0) {
int len = os_strlen(gameinfo_gamedir);
if (len + sizeof("/addons/" VDFBASENAME ".vdf") >
sizeof(path) / sizeof(*path)) {
- con_warn("error: path to VDF is too long\n");
+ errmsg_errorx("path to VDF is too long");
return;
}
memcpy(path, gameinfo_gamedir, len * sizeof(*gameinfo_gamedir));
memcpy(path + len, OS_LIT("/addons/") OS_LIT(VDFBASENAME) OS_LIT(".vdf"),
sizeof("/addons/" VDFBASENAME ".vdf") * sizeof(os_char));
if (os_unlink(path) == -1 && errno != ENOENT) {
- con_warn("warning: couldn't delete %" fS ":%s\n", path, strerror(errno));
+ errmsg_warnstd("couldn't delete %" fS, path);
}
}
@@ -248,14 +249,13 @@ static void VCALLCONV hook_VGuiConnect(void) {
static void deferinit(void) {
vgui = factory_engine("VEngineVGui001", 0);
if (!vgui) {
- con_warn("sst: warning: couldn't get VEngineVGui for deferred "
- "feature setup\n");
+ errmsg_warnx("couldn't get VEngineVGui for deferred feature setup");
goto e;
}
if (!os_mprot(*(void ***)vgui + vtidx_VGuiConnect, sizeof(void *),
PAGE_READWRITE)) {
- con_warn("sst: warning: couldn't unprotect CEngineVGui vtable for "
- "deferred feature setup\n");
+ errmsg_warnsys("couldn't make CEngineVGui vtable writable for deferred "
+ "feature setup");
goto e;
}
orig_VGuiConnect = (VGuiConnect_func)hook_vtable(*(void ***)vgui,
@@ -295,11 +295,11 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {
clientlib = dlopen(gameinfo_clientlib, RTLD_NOW);
#endif
if (!clientlib) {
- con_warn("sst: warning: couldn't get the game's client library\n");
+ errmsg_warndl("couldn't get the game's client library");
}
else if (!(factory_client = (ifacefactory)os_dlsym(clientlib,
"CreateInterface"))) {
- con_warn("sst: warning: couldn't get client's CreateInterface\n");
+ errmsg_warndl("couldn't get client's CreateInterface");
}
#ifdef _WIN32
void *inputsystemlib = GetModuleHandleW(L"inputsystem.dll");
@@ -311,11 +311,11 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {
if (inputsystemlib) dlclose(inputsystemlib); // blegh
#endif
if (!inputsystemlib) {
- con_warn("sst: warning: couldn't get the input system library\n");
+ errmsg_warndl("couldn't get the input system library");
}
else if (!(factory_inputsystem = (ifacefactory)os_dlsym(inputsystemlib,
"CreateInterface"))) {
- con_warn("sst: warning: couldn't get input system's CreateInterface\n");
+ errmsg_warndl("couldn't get input system's CreateInterface");
}
// NOTE: this is technically redundant for early versions but I CBA writing
@@ -324,8 +324,8 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {
void *kvs = KeyValuesSystem();
kvsvt = *(void ***)kvs;
if (!os_mprot(kvsvt + 4, sizeof(void *), PAGE_READWRITE)) {
- con_warn("sst: warning: couldn't unprotect KeyValuesSystem "
- "vtable; won't be able to prevent nag message\n");
+ errmsg_warnx("couldn't make KeyValuesSystem vtable writable");
+ errmsg_note("won't be able to prevent any nag messages");
}
else {
orig_GetStringForSymbol = (GetStringForSymbol_func)hook_vtable(