relibc: implement error()/error_at_line() as real symbols (not header inlines)
The header-only static-inline error()/error_at_line() collided with gnulib's own
lib/error.c ('redefinition of error', building m4): autotools link-detects a
system error(), skips its replacement, then the inline in <error.h> clashes with
gnulib's definition. Implement them properly in relibc (src/header/error) with
the glibc globals (error_message_count, error_one_per_line, error_print_progname)
and make <error.h> a pure extern declaration. Fixes m4/gnulib and keeps
mesa/libelf (the original <error.h> consumers) working via the real symbol.
This commit is contained in:
+21
-41
@@ -2,56 +2,36 @@
|
||||
*
|
||||
* Red Bear OS / relibc. Mirrors glibc <error.h>: error() and error_at_line()
|
||||
* print the program name (best effort), a formatted message, and optionally a
|
||||
* strerror() of errnum to stderr, then exit() when status is non-zero. Provided
|
||||
* as complete inline implementations so portable tooling (elfutils/libelf,
|
||||
* GNU-style CLIs) that includes <error.h> builds and behaves correctly.
|
||||
* strerror() of errnum to stderr, then exit() when status is non-zero.
|
||||
*
|
||||
* These are DECLARED here and IMPLEMENTED as real exported symbols in relibc
|
||||
* (src/header/error). They must NOT be static-inline: autotools/gnulib link-test
|
||||
* for a system error() and, finding one, skip compiling their own lib/error.c —
|
||||
* a header-only inline collides with that replacement ("redefinition of
|
||||
* 'error'", seen building m4/gnulib).
|
||||
*/
|
||||
#ifndef _ERROR_H
|
||||
#define _ERROR_H 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void error(int __status, int __errnum, const char *__format, ...) {
|
||||
va_list __ap;
|
||||
fflush(stdout);
|
||||
va_start(__ap, __format);
|
||||
vfprintf(stderr, __format, __ap);
|
||||
va_end(__ap);
|
||||
if (__errnum != 0) {
|
||||
fprintf(stderr, ": %s", strerror(__errnum));
|
||||
}
|
||||
fputc('\n', stderr);
|
||||
if (__status != 0) {
|
||||
exit(__status);
|
||||
}
|
||||
}
|
||||
/* Count of messages printed by error()/error_at_line(). */
|
||||
extern unsigned int error_message_count;
|
||||
|
||||
static inline void error_at_line(int __status, int __errnum,
|
||||
const char *__fname, unsigned int __lineno,
|
||||
const char *__format, ...) {
|
||||
va_list __ap;
|
||||
fflush(stdout);
|
||||
if (__fname != NULL) {
|
||||
fprintf(stderr, "%s:%u: ", __fname, __lineno);
|
||||
}
|
||||
va_start(__ap, __format);
|
||||
vfprintf(stderr, __format, __ap);
|
||||
va_end(__ap);
|
||||
if (__errnum != 0) {
|
||||
fprintf(stderr, ": %s", strerror(__errnum));
|
||||
}
|
||||
fputc('\n', stderr);
|
||||
if (__status != 0) {
|
||||
exit(__status);
|
||||
}
|
||||
}
|
||||
/* When non-zero, error_at_line() prints each distinct file:line only once. */
|
||||
extern int error_one_per_line;
|
||||
|
||||
/* Optional hook to print the program name instead of the default. */
|
||||
extern void (*error_print_progname)(void);
|
||||
|
||||
extern void error(int __status, int __errnum, const char *__format, ...)
|
||||
__attribute__((__format__(__printf__, 3, 4)));
|
||||
|
||||
extern void error_at_line(int __status, int __errnum, const char *__fname,
|
||||
unsigned int __lineno, const char *__format, ...)
|
||||
__attribute__((__format__(__printf__, 5, 6)));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user