35 #if defined(DEVEL_RALF)
40 #define GLOBAL_STRING_BUFFERS 4
43 #define GBS_GLOBAL_STRING_SIZE 64000
48 # define HAVE_VSNPRINTF
52 # define PRINT2BUFFER(buffer, bufsize, templat, parg) vsnprintf(buffer, bufsize, templat, parg)
54 # define PRINT2BUFFER(buffer, bufsize, templat, parg) vsprintf(buffer, templat, parg)
57 #define PRINT2BUFFER_CHECKED(printed, buffer, bufsize, templat, parg) \
58 (printed) = PRINT2BUFFER(buffer, bufsize, templat, parg); \
59 if ((printed) < 0 || (size_t)(printed) >= (bufsize)) { \
60 GBK_terminatef("Internal buffer overflow (size=%zu, used=%i)\n", \
61 (bufsize), (printed)); \
87 const
char *
GlobalStringBuffers::vstrf(const
char *templat, va_list parg,
int allow_reuse) {
91 if (nextIdx[0] == 0) {
93 nextIdx[my_idx] = (my_idx+1)%GLOBAL_STRING_BUFFERS;
97 if (allow_reuse == -1) {
101 if (buffer[my_idx] == templat) {
102 lifetime[my_idx] = 0;
103 #if defined(TRACE_BUFFER_USAGE)
104 printf(
"Reusing buffer #%i\n", my_idx);
105 #endif // TRACE_BUFFER_USAGE
106 if (nextIdx[my_idx] == idx) idx = my_idx;
109 #if defined(TRACE_BUFFER_USAGE)
111 printf(
"(buffer to reuse is not buffer #%i (%p))\n", my_idx, buffer[my_idx]);
113 #endif // TRACE_BUFFER_USAGE
116 printf(
"buffer[%i]=%p\n", my_idx, buffer[my_idx]);
122 if (lifetime[idx] == 0) {
126 for (my_idx = nextIdx[idx]; lifetime[my_idx]>0; my_idx = nextIdx[my_idx]) {
127 #if defined(TRACE_BUFFER_USAGE)
128 printf(
"decreasing lifetime[%i] (%i->%i)\n", my_idx, lifetime[my_idx], lifetime[my_idx]-1);
129 #endif // TRACE_BUFFER_USAGE
136 #if defined(TRACE_BUFFER_USAGE)
137 printf(
"Printed into global buffer #%i ('%s')\n", my_idx, buffer[my_idx]);
138 #endif // TRACE_BUFFER_USAGE
140 last_global_string_size = psize;
146 #if defined(TRACE_BUFFER_USAGE)
148 printf(
"Allow reuse of buffer #%i\n", my_idx);
150 #endif // TRACE_BUFFER_USAGE
152 return buffer[my_idx];
168 return globBuf.vstrf(templat, parg, 0);
173 const char *gstr =
globBuf.vstrf(templat, parg, 1);
217 static char *buffer =
NULp;
224 last_global_string_size = old_size;
275 p += sprintf(buffer,
"ARB ERROR: ");
278 vsprintf(p, templat, parg);
280 freedup(GB_error_buffer, buffer);
293 io_error = strerror(errno);
298 "Some unhandled error occurred, but it was not an IO-Error. "
299 "Please send detailed information about how the error occurred to devel@arb-home.de "
300 "or ignore this error (if possible).";
305 if (filename) error =
GBS_global_string(
"While %s '%s': %s", action, filename, io_error);
309 if (filename) error =
GBS_global_string(
"Concerning '%s': %s", filename, io_error);
310 else error = io_error;
325 if (GB_error_buffer) {
327 fprintf(stderr,
"%s\n", GB_error_buffer);
342 if (GB_error_buffer) {
343 static SmartCharPtr err;
345 GB_error_buffer =
NULp;
350 return "Program logic error: Something went wrong, but reason is unknown";
354 freenull(GB_error_buffer);
377 error =
GBS_global_string(
"Failed to %s '%s'.\n(Reason: %s)", do_something, special, error);
432 "If you've made changes to the database, consider to save it using a different name.\n"
433 "Try to fix the cause of the error and restart ARB.");
435 #ifdef ASSERTION_USED
436 fputs(full_message, stderr);
455 fprintf(stderr,
"Error: '%s'\n", error);
456 fputs(
"Can't continue - terminating..\n", stderr);
495 #pragma GCC diagnostic ignored "-Wmissing-format-attribute"
500 globBuf.vstrf(global_buffer, empty, -1);
508 fprintf(stderr,
"[Action: `%s`]\n", system_command);
fflush(stderr);
510 int res = system(system_command);
526 "System call was `%s`%s",
527 error, system_command,
528 res == -1 ?
"" :
"\n(Note: console window may contain additional information)");
540 const char *existing_quote = strchr(arg,
'\'');
542 while (existing_quote) {
543 if (existing_quote>arg) {
545 out.
ncat(arg, existing_quote-arg);
550 arg = existing_quote+1;
551 existing_quote = strchr(arg,
'\'');
567 const char *charsToEscape =
"\"\\";
568 const char *escape = arg+strcspn(arg, charsToEscape);
573 out.
ncat(arg, escape-arg);
577 escape = arg+strcspn(arg, charsToEscape);
594 #define TEST_EXPECT_SQUOTE(plain,squote_expected) do { \
595 char *plain_squoted = GBK_singlequote(plain); \
596 TEST_EXPECT_EQUAL(plain_squoted, squote_expected); \
597 free(plain_squoted); \
600 #define TEST_EXPECT_DQUOTE(plain,dquote_expected) do { \
601 char *plain_dquoted = GBK_doublequote(plain); \
602 TEST_EXPECT_EQUAL(plain_dquoted, dquote_expected); \
603 free(plain_dquoted); \
606 #define TEST_EXPECT_ECHOED_EQUALS(echoarg,expected_echo) do { \
607 char *cmd = GBS_global_string_copy("echo %s > %s", echoarg, tmpfile); \
608 TEST_EXPECT_NO_ERROR(GBK_system(cmd)); \
609 FileContent out(tmpfile); \
610 TEST_EXPECT_NO_ERROR(out.has_error()); \
611 TEST_EXPECT_EQUAL(out.lines()[0], expected_echo); \
615 #define TEST_EXPECT_SQUOTE_IDENTITY(plain) do { \
616 char *plain_squoted = GBK_singlequote(plain); \
617 TEST_EXPECT_ECHOED_EQUALS(plain_squoted,plain); \
618 free(plain_squoted); \
621 #define TEST_EXPECT_DQUOTE_IDENTITY(plain) do { \
622 char *plain_dquoted = GBK_doublequote(plain); \
623 TEST_EXPECT_ECHOED_EQUALS(plain_dquoted,plain); \
624 free(plain_dquoted); \
627 void TEST_quoting() {
628 const char *tmpfile =
"quoted.output";
635 {
"",
"''",
"\"\"" },
636 {
" ",
"' '",
"\" \"" },
637 {
"unquoted",
"'unquoted'",
"\"unquoted\"" },
638 {
"part 'is' squoted",
"'part '\\''is'\\'' squoted'",
"\"part 'is' squoted\"" },
639 {
"part \"is\" dquoted",
"'part \"is\" dquoted'",
"\"part \\\"is\\\" dquoted\"" },
640 {
"'squoted'",
"\\''squoted'\\'",
"\"'squoted'\"" },
641 {
"\"dquoted\"",
"'\"dquoted\"'",
"\"\\\"dquoted\\\"\"" },
642 {
"'",
"\\'",
"\"'\"" },
643 {
"\"",
"'\"'",
"\"\\\"\"" },
644 {
"\\",
"'\\'",
"\"\\\\\"" },
645 {
"'\"'\"",
"\\''\"'\\''\"'",
"\"'\\\"'\\\"\"" },
646 {
"`wc -c <min_ascii.arb | tr -d ' '`",
647 "'`wc -c <min_ascii.arb | tr -d '\\'' '\\''`'",
648 "\"`wc -c <min_ascii.arb | tr -d ' '`\"" },
653 const quoting& arg = args[a];
655 TEST_EXPECT_SQUOTE(arg.plain, arg.squoted);
656 TEST_EXPECT_SQUOTE_IDENTITY(arg.plain);
658 TEST_EXPECT_DQUOTE(arg.plain, arg.dquoted);
660 TEST_EXPECT_DQUOTE_IDENTITY(arg.plain);
664 TEST_EXPECT_ECHOED_EQUALS(dquoted,
"16");
void GBS_restore_global_buffers(GlobalStringBuffers *saved)
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
gb_information_func_type show_message
GB_ERROR GB_append_exportedError(GB_ERROR error)
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
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
#define GLOBAL_STRING_BUFFERS
char * GBS_global_string_copy(const char *templat,...)