Files
AnyPS5/core/libs/prx/libSceLibcInternal/Err.cpp
T
NikoandClaude Opus 5.5 c8ad92f878 feat(libSceLibcInternal): export _err, _warn and _getprogname
The PS5 3.20 export inventory lists _err, _warn and _getprogname in
libSceLibcInternal next to err, warn and getprogname, with the NIDs
UhKI6z9WWuo, XQFE8Y58WZM and iI6kGxgXzcU. In FreeBSD 11.4 libc the
underscore names are the definitions and the public names are weak
references to them (lib/libc/gen/err.c, lib/libc/gen/getprogname.c),
and libthr interposes none of them, so each pair is one function.

_err and _warn now hand their arguments to verr and vwarn, which use
errno at the call as err and warn do; _getprogname returns
getprogname(). The debt file records that the console's module was not
read.

guest_err checks the _warn and _err text for errno 13 with a formatted
message, that _err passes its status to the err_set_exit hook, and that
_warn without a format returns without calling the hook.
guest_program_name checks that _getprogname returns the current
__progname pointer.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-21 17:02:54 +02:00

151 lines
4.7 KiB
C++

#include "prx/libc/include/FileStream.hpp"
#include "prx/libc/include/Shutdown.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"
#include "SceTypes.hpp"
#include <cstdarg>
using ErrExit = void (APS5_VABI*)(int);
extern "C" {
extern const char* __progname_nid_postfix;
int APS5_VABI vfprintf_nid_postfix(FileStream* stream, const char* format, VaList* args);
int APS5_VABI fprintf_nid_postfix(FileStream* stream, const char* format, ...);
int APS5_VABI fputs_nid_postfix(const char* str, FileStream* stream);
char* APS5_VABI strerror_nid_postfix(int error);
int* APS5_VABI __error_nid_postfix();
}
namespace {
FileStream* g_errFile = nullptr;
ErrExit g_errExit = nullptr;
FileStream* ErrFile() {
if (g_errFile == nullptr) g_errFile = &_Stderr_nid_postfix;
return g_errFile;
}
const char* ProgramName() {
return __progname_nid_postfix ? __progname_nid_postfix : "(null)";
}
void Report(const char* format, VaList* args, const int* code) {
FileStream* const stream = ErrFile();
fprintf_nid_postfix(stream, "%s: ", ProgramName());
if (format != nullptr) {
vfprintf_nid_postfix(stream, format, args);
if (code != nullptr) fputs_nid_postfix(": ", stream);
}
if (code != nullptr) fprintf_nid_postfix(stream, "%s\n", strerror_nid_postfix(*code));
else fputs_nid_postfix("\n", stream);
}
[[noreturn]] void Exit(int status) {
if (g_errExit != nullptr) g_errExit(status);
LibcExit_nid_no_patch(status);
}
}
#ifdef _WIN32
#define APS5_ERR_VA_LIST __builtin_sysv_va_list
#define APS5_ERR_VA_START(list, last) __builtin_sysv_va_start(list, last)
#define APS5_ERR_VA_END(list) __builtin_sysv_va_end(list)
#else
#define APS5_ERR_VA_LIST std::va_list
#define APS5_ERR_VA_START(list, last) va_start(list, last)
#define APS5_ERR_VA_END(list) va_end(list)
#endif
extern "C" {
void APS5_VABI err_set_file_nid_postfix(FileStream* stream) {
g_errFile = stream != nullptr ? stream : &_Stderr_nid_postfix;
}
void APS5_VABI err_set_exit_nid_postfix(ErrExit function) {
g_errExit = function;
}
void APS5_VABI vwarnc_nid_postfix(int code, const char* format, VaList* args) {
Report(format, args, &code);
}
void APS5_VABI vwarn_nid_postfix(const char* format, VaList* args) {
vwarnc_nid_postfix(*__error_nid_postfix(), format, args);
}
void APS5_VABI vwarnx_nid_postfix(const char* format, VaList* args) {
Report(format, args, nullptr);
}
[[noreturn]] void APS5_VABI verrc_nid_postfix(int status, int code, const char* format, VaList* args) {
Report(format, args, &code);
Exit(status);
}
[[noreturn]] void APS5_VABI verr_nid_postfix(int status, const char* format, VaList* args) {
verrc_nid_postfix(status, *__error_nid_postfix(), format, args);
}
[[noreturn]] void APS5_VABI verrx_nid_postfix(int status, const char* format, VaList* args) {
Report(format, args, nullptr);
Exit(status);
}
void APS5_VABI warnc_nid_postfix(int code, const char* format, ...) {
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
vwarnc_nid_postfix(code, format, reinterpret_cast<VaList*>(args));
APS5_ERR_VA_END(args);
}
void APS5_VABI warn_nid_postfix(const char* format, ...) {
const int code = *__error_nid_postfix();
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
vwarnc_nid_postfix(code, format, reinterpret_cast<VaList*>(args));
APS5_ERR_VA_END(args);
}
void APS5_VABI _warn_nid_postfix(const char* format, ...) {
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
vwarn_nid_postfix(format, reinterpret_cast<VaList*>(args));
APS5_ERR_VA_END(args);
}
void APS5_VABI warnx_nid_postfix(const char* format, ...) {
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
vwarnx_nid_postfix(format, reinterpret_cast<VaList*>(args));
APS5_ERR_VA_END(args);
}
[[noreturn]] void APS5_VABI errc_nid_postfix(int status, int code, const char* format, ...) {
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
verrc_nid_postfix(status, code, format, reinterpret_cast<VaList*>(args));
}
[[noreturn]] void APS5_VABI err_nid_postfix(int status, const char* format, ...) {
const int code = *__error_nid_postfix();
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
verrc_nid_postfix(status, code, format, reinterpret_cast<VaList*>(args));
}
[[noreturn]] void APS5_VABI _err_nid_postfix(int status, const char* format, ...) {
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
verr_nid_postfix(status, format, reinterpret_cast<VaList*>(args));
}
[[noreturn]] void APS5_VABI errx_nid_postfix(int status, const char* format, ...) {
APS5_ERR_VA_LIST args;
APS5_ERR_VA_START(args, format);
verrx_nid_postfix(status, format, reinterpret_cast<VaList*>(args));
}
}