36 #if defined(DEVEL_RALF)
41 #define GLOBAL_STRING_BUFFERS 4
44 #define GBS_GLOBAL_STRING_SIZE 64000
49 # define HAVE_VSNPRINTF
53 # define PRINT2BUFFER(buffer, bufsize, templat, parg) vsnprintf(buffer, bufsize, templat, parg)
55 # define PRINT2BUFFER(buffer, bufsize, templat, parg) vsprintf(buffer, templat, parg)
58 #define PRINT2BUFFER_CHECKED(printed, buffer, bufsize, templat, parg) \
59 (printed) = PRINT2BUFFER(buffer, bufsize, templat, parg); \
60 if ((printed) < 0 || (size_t)(printed) >= (bufsize)) { \
61 GBK_terminatef("Internal buffer overflow (size=%zu, used=%i)\n", \
62 (bufsize), (printed)); \
88 const
char *
GlobalStringBuffers::vstrf(const
char *templat, va_list parg,
int allow_reuse) {
92 if (nextIdx[0] == 0) {
94 nextIdx[my_idx] = (my_idx+1)%GLOBAL_STRING_BUFFERS;
98 if (allow_reuse == -1) {
102 if (buffer[my_idx] == templat) {
103 lifetime[my_idx] = 0;
104 #if defined(TRACE_BUFFER_USAGE)
105 printf(
"Reusing buffer #%i\n", my_idx);
106 #endif // TRACE_BUFFER_USAGE
107 if (nextIdx[my_idx] == idx) idx = my_idx;
110 #if defined(TRACE_BUFFER_USAGE)
112 printf(
"(buffer to reuse is not buffer #%i (%p))\n", my_idx, buffer[my_idx]);
114 #endif // TRACE_BUFFER_USAGE
117 printf(
"buffer[%i]=%p\n", my_idx, buffer[my_idx]);
123 if (lifetime[idx] == 0) {
127 for (my_idx = nextIdx[idx]; lifetime[my_idx]>0; my_idx = nextIdx[my_idx]) {
128 #if defined(TRACE_BUFFER_USAGE)
129 printf(
"decreasing lifetime[%i] (%i->%i)\n", my_idx, lifetime[my_idx], lifetime[my_idx]-1);
130 #endif // TRACE_BUFFER_USAGE
137 #if defined(TRACE_BUFFER_USAGE)
138 printf(
"Printed into global buffer #%i ('%s')\n", my_idx, buffer[my_idx]);
139 #endif // TRACE_BUFFER_USAGE
141 last_global_string_size = psize;
147 #if defined(TRACE_BUFFER_USAGE)
149 printf(
"Allow reuse of buffer #%i\n", my_idx);
151 #endif // TRACE_BUFFER_USAGE
153 return buffer[my_idx];
169 return globBuf.vstrf(templat, parg, 0);
174 const char *gstr =
globBuf.vstrf(templat, parg, 1);
218 static char *buffer =
NULp;
225 last_global_string_size = old_size;
276 p += sprintf(buffer,
"ARB ERROR: ");
279 vsprintf(p, templat, parg);
281 freedup(GB_error_buffer, buffer);
294 io_error = strerror(errno);
299 "Some unhandled error occurred, but it was not an IO-Error. "
300 "Please send detailed information about how the error occurred to devel@arb-home.de "
301 "or ignore this error (if possible).";
306 if (filename) error =
GBS_global_string(
"While %s '%s': %s", action, filename, io_error);
310 if (filename) error =
GBS_global_string(
"Concerning '%s': %s", filename, io_error);
311 else error = io_error;
326 if (GB_error_buffer) {
328 fprintf(stderr,
"%s\n", GB_error_buffer);
343 if (GB_error_buffer) {
344 static SmartCharPtr err;
346 GB_error_buffer =
NULp;
351 return "Program logic error: Something went wrong, but reason is unknown";
355 freenull(GB_error_buffer);
378 error =
GBS_global_string(
"Failed to %s '%s'.\n(Reason: %s)", do_something, special, error);
429 previous_spamfilter(current_spamfilter),
430 what_is_filtered(what_is_filtered_),
433 accepted(acceptedMessages)
435 current_spamfilter =
this;
439 if (current_spamfilter ==
this) {
440 current_spamfilter = previous_spamfilter;
442 const char *msg =
GBS_global_string(
"suppressed %i related messages about %s (see logfile)", suppressed, what_is_filtered.c_str());
451 bool MessageSpamFilter::is_spam() {
453 if (shown<accepted) {
464 void MessageSpamFilter::filter_warning(
const char *
message) {
474 if (current_spamfilter) current_spamfilter->filter_warning(message);
491 "If you've made changes to the database, consider to save it using a different name.\n"
492 "Try to fix the cause of the error and restart ARB.");
494 #ifdef ASSERTION_USED
495 fputs(full_message, stderr);
514 fprintf(stderr,
"Error: '%s'\n", error);
515 fputs(
"Can't continue - terminating..\n", stderr);
561 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
566 globBuf.vstrf(global_buffer, empty, -1);
574 fprintf(stderr,
"[Action: `%s`]\n", system_command);
fflush(stderr);
576 int res = system(system_command);
592 "System call was `%s`%s",
593 error, system_command,
594 res == -1 ?
"" :
"\n(Note: console window may contain additional information)");
606 const char *existing_quote = strchr(arg,
'\'');
608 while (existing_quote) {
609 if (existing_quote>arg) {
611 out.
ncat(arg, existing_quote-arg);
616 arg = existing_quote+1;
617 existing_quote = strchr(arg,
'\'');
629 const char *charsToEscape =
"\"\\";
630 const char *escape = arg+strcspn(arg, charsToEscape);
635 out.
ncat(arg, escape-arg);
639 escape = arg+strcspn(arg, charsToEscape);
656 #define TEST_EXPECT_SQUOTE(plain,squote_expected) do { \
657 char *plain_squoted = GBK_singlequote(plain); \
658 TEST_EXPECT_EQUAL(plain_squoted, squote_expected); \
659 free(plain_squoted); \
662 #define TEST_EXPECT_DQUOTE(plain,dquote_expected) do { \
663 char *plain_dquoted = GBK_doublequote(plain); \
664 TEST_EXPECT_EQUAL(plain_dquoted, dquote_expected); \
665 free(plain_dquoted); \
668 #define TEST_EXPECT_ECHOED_EQUALS(echoarg,expected_echo) do { \
669 char *cmd = GBS_global_string_copy("echo %s > %s", echoarg, tmpfile); \
670 TEST_EXPECT_NO_ERROR(GBK_system(cmd)); \
671 FileContent out(tmpfile); \
672 TEST_EXPECT_NO_ERROR(out.has_error()); \
673 TEST_EXPECT_EQUAL(out.lines()[0], expected_echo); \
677 #define TEST_EXPECT_SQUOTE_IDENTITY(plain) do { \
678 char *plain_squoted = GBK_singlequote(plain); \
679 TEST_EXPECT_ECHOED_EQUALS(plain_squoted,plain); \
680 free(plain_squoted); \
683 #define TEST_EXPECT_DQUOTE_IDENTITY(plain) do { \
684 char *plain_dquoted = GBK_doublequote(plain); \
685 TEST_EXPECT_ECHOED_EQUALS(plain_dquoted,plain); \
686 free(plain_dquoted); \
689 void TEST_quoting() {
690 const char *tmpfile =
"quoted.output";
697 {
"",
"''",
"\"\"" },
698 {
" ",
"' '",
"\" \"" },
699 {
"unquoted",
"'unquoted'",
"\"unquoted\"" },
700 {
"part 'is' squoted",
"'part '\\''is'\\'' squoted'",
"\"part 'is' squoted\"" },
701 {
"part \"is\" dquoted",
"'part \"is\" dquoted'",
"\"part \\\"is\\\" dquoted\"" },
702 {
"'squoted'",
"\\''squoted'\\'",
"\"'squoted'\"" },
703 {
"\"dquoted\"",
"'\"dquoted\"'",
"\"\\\"dquoted\\\"\"" },
704 {
"'",
"\\'",
"\"'\"" },
705 {
"\"",
"'\"'",
"\"\\\"\"" },
706 {
"\\",
"'\\'",
"\"\\\\\"" },
707 {
"'\"'\"",
"\\''\"'\\''\"'",
"\"'\\\"'\\\"\"" },
708 {
"`wc -c <min_ascii.arb | tr -d ' '`",
709 "'`wc -c <min_ascii.arb | tr -d '\\'' '\\''`'",
710 "\"`wc -c <min_ascii.arb | tr -d ' '`\"" },
715 const quoting& arg = args[a];
717 TEST_EXPECT_SQUOTE(arg.plain, arg.squoted);
718 TEST_EXPECT_SQUOTE_IDENTITY(arg.plain);
720 TEST_EXPECT_DQUOTE(arg.plain, arg.dquoted);
722 TEST_EXPECT_DQUOTE_IDENTITY(arg.plain);
726 TEST_EXPECT_ECHOED_EQUALS(dquoted,
"16");
void GBS_restore_global_buffers(GlobalStringBuffers *saved)
MessageSpamFilter(std::string what_is_filtered_, int acceptedMessages=5)
void GB_warning(const char *message)
const char * GBS_vglobal_string(const char *templat, va_list parg)
gb_warning_func_type show_warning
static char * GB_error_buffer
GB_ERROR GBK_system(const char *system_command)
static size_t last_global_string_size
return string(buffer, length)
gb_information_func_type show_message
GB_ERROR GB_append_exportedError(GB_ERROR error)
void GB_warning_if(const char *message)
void demangle_backtrace(const class BackTraceInfo &trace, FILE *out, const char *message)
const char * GBS_global_string_to_buffer(char *buffer, size_t bufsize, const char *templat,...)
char * GBK_doublequote(const char *arg)
GB_ERROR GB_IO_error(const char *action, const char *filename)
char * ARB_strdup(const char *str)
#define ARB_CRASH_CODE(sig)
void GB_internal_errorf(const char *templat,...)
GB_ERROR GB_export_IO_error(const char *action, const char *filename)
const char * GBS_global_string(const char *templat,...)
#define FORWARD_FORMATTED(receiver, format)
void GBK_terminatef(const char *templat,...)
#define ARB_SIGSEGV(backtrace)
void cat(const char *from)
char * GBS_vglobal_string_copy(const char *templat, va_list parg)
static GlobalStringBuffers globBuf
class BackTraceInfo * GBK_get_backtrace(size_t skipFramesAtBottom)
void GBK_dump_former_backtrace(class BackTraceInfo *trace, FILE *out, const char *message)
#define ARRAY_ELEMS(array)
gb_error_handler_type show_error
GB_ERROR GB_export_error(const char *error)
GB_ERROR GB_await_error()
char * ARB_strduplen(const char *p, unsigned len)
void GB_warningf(const char *templat,...)
TYPE * ARB_alloc(size_t nelem)
arb_handlers * active_arb_handlers
static void show_warning(const char *message)
void message(char *errortext)
static void error(const char *msg)
GB_ERROR GBK_assert_msg(const char *assertion, const char *file, int linenr)
__ATTR__VFORMAT_MEMBER(1) const char *vstrf(const char *templat
void GBS_reuse_buffer(const char *global_buffer)
GB_ERROR GB_print_error()
fputs(TRACE_PREFIX, stderr)
GB_ERROR GB_export_errorf(const char *templat,...)
void GB_internal_error(const char *message)
void ncat(const char *from, size_t count)
char * GBK_singlequote(const char *arg)
BackTraceInfo(size_t skipFramesAtBottom)
void GBK_free_backtrace(class BackTraceInfo *trace)
GB_ERROR GB_failedTo_error(const char *do_something, const char *special, GB_ERROR error)
const char * GBS_static_string(const char *str)
void GBK_dump_backtrace(FILE *out, const char *message)
#define PRINT2BUFFER_CHECKED(printed, buffer, bufsize, templat, parg)
GlobalStringBuffers * GBS_store_global_buffers()
void GB_information(const char *message)
void GBK_terminate(const char *error)
void GB_informationf(const char *templat,...)
#define FORWARD_FORMATTED_NORETURN(receiver, format)
#define TEST_EXPECT_EQUAL(expr, want)
#define GBS_GLOBAL_STRING_SIZE
void cat_sQuoted(const char *from)
#define GLOBAL_STRING_BUFFERS
char * GBS_global_string_copy(const char *templat,...)