From 988181b71ee24df0c349a2c0ad0a0e656eefe7e9 Mon Sep 17 00:00:00 2001 From: James Y Knight Date: Tue, 30 Jul 2019 11:59:25 -0400 Subject: [PATCH] Add support for the glibc-specific error.h header. This includes the functions 'error', 'error_at_line', and their associated global variables. --- dynamic.list | 4 +++ include/error.h | 21 ++++++++++++++ src/legacy/error.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 include/error.h create mode 100644 src/legacy/error.c diff --git a/dynamic.list b/dynamic.list index ee0d363b..9c8450f4 100644 --- a/dynamic.list +++ b/dynamic.list @@ -42,4 +42,8 @@ __progname; __progname_full; __stack_chk_guard; + +error_print_progname; +error_message_count; +error_one_per_line; }; diff --git a/include/error.h b/include/error.h new file mode 100644 index 00000000..03b1ca41 --- /dev/null +++ b/include/error.h @@ -0,0 +1,21 @@ +#ifndef _ERROR_H +#define _ERROR_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern void (*error_print_progname) (void); +extern unsigned int error_message_count; +extern int error_one_per_line; + +void error(int, int, const char *, ...); +void error_at_line(int, int, const char *, unsigned int, const char *, ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/legacy/error.c b/src/legacy/error.c new file mode 100644 index 00000000..c5000fa4 --- /dev/null +++ b/src/legacy/error.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#include "libc.h" + +void (*error_print_progname) (void) = 0; +unsigned int error_message_count = 0; +int error_one_per_line = 0; + +static unsigned int saved_linenum = 0; +static const char *saved_file = 0; + +static void errorv(int status, int errnum, const char *file, unsigned int linenum, const char *fmt, va_list ap) +{ + ++error_message_count; + + fflush(stdout); + flockfile(stderr); + + if (error_print_progname) + error_print_progname(); + else { + fprintf(stderr, "%s:", __progname_full); + if (!file) + fputc(' ', stderr); + } + + if (file) + fprintf(stderr, "%s:%u: ", file, linenum); + + vfprintf(stderr, fmt, ap); + if (errnum) + fprintf(stderr, ": %s", strerror(errnum)); + fputc('\n', stderr); + + funlockfile(stderr); + + if (status) + exit(status); +} + +void error(int status, int errnum, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + errorv(status, errnum, NULL, 0, fmt, ap); + va_end(ap); +} + +void error_at_line(int status, int errnum, const char *file, unsigned int linenum, const char *fmt, ...) +{ + if (error_one_per_line) { + if(saved_linenum == linenum && file != NULL && + saved_file != NULL && !strcmp(file, saved_file)) + return; + saved_linenum = linenum; + // Assuming that the lifetime of the passed in file name extends + // until the next call is rather questionable, but appears to be + // the expected semantics. + saved_file = file; + } + + va_list ap; + va_start(ap, fmt); + errorv(status, errnum, file, linenum, fmt, ap); + va_end(ap); +} -- 2.22.0.709.g102302147b-goog