removed this function which was not publically exported in glib.h. to
authorTim Janik <timj@gtk.org>
Mon, 24 Aug 1998 05:26:53 +0000 (05:26 +0000)
committerTim Janik <timj@src.gnome.org>
Mon, 24 Aug 1998 05:26:53 +0000 (05:26 +0000)
Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>

        * glib.h:
        * gstring.c:
        * gstrfuncs.c:
        (g_vsprintf): removed this function which was not publically
        exported in glib.h. to export it, it should have been named
        differently in the first place, since its semantics differ from
        vsprintf(). apart from that, it was a possible cause for
        problems since it worked on a previously allocated memory area and
        was used in a lot places of glib. exporting it would have been a
        guararant for problems with threaded programs.
        (g_printf_string_upper_bound): exported this function to return
        a string size, guarranteed to be big enough to hold the fully
        expanded format+args string. added 'q', 'L' and 'll' flag handling.
        in fact, the newly allocated area is in most cases much bigger than
        required.
        (g_strdup_vprintf()): new function returning a newly allocated string
        containing the contents of *format and associated args (size is
        calculated with g_printf_string_upper_bound()).
        (g_strdup_printf): new function which wraps g_strdup_vprintf().

        * configure.in: check for va_copy() or __va_copy() alternatively.
        check whether va_lists can be copyied by value.

        * glib.h: provide a definition for G_VA_COPY.

        * glib.h:
        * gmessages.c:
        (g_logv):
        (g_vsnprintf):
        pass va_lists by value, not by reference, since this causes problems
        on platforms that implement va_list as as arrays. internaly, use
        G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
        va_list variable, if multiple passes are required. changed all
        callers.

        * glib.h:
        * gerror.h:
        renamed g_debug() to g_on_error_query(), cleaned up a bit.
        renamed g_stack_trace() to g_on_error_stack_trace() since both
        functions cluttered different namespaces.
        there is an appropriate comment in glib.h now that explains the
        unix and gdb specific dependencies of both functions.
        removed g_attach_process().
        g_on_error_stack_trace() should probably be handled with caution,
        i've seem several different linux versions (2.0.x) become unstable
        after invokation of this function.

29 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
NEWS
acconfig.h
configure.in
gbacktrace.c
gerror.c
glib.h
glib/gbacktrace.c
glib/gerror.c
glib/glib.h
glib/gmessages.c
glib/gscanner.c
glib/gstrfuncs.c
glib/gstring.c
glib/gutils.c
glibconfig.h.in
gmessages.c
gmodule/testgmodule.c
gscanner.c
gstrfuncs.c
gstring.c
gutils.c

index 256ebca..4d42396 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
index 256ebca..4d42396 100644 (file)
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
index 256ebca..4d42396 100644 (file)
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
index 256ebca..4d42396 100644 (file)
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
index 256ebca..4d42396 100644 (file)
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
index 256ebca..4d42396 100644 (file)
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
index 256ebca..4d42396 100644 (file)
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
index 256ebca..4d42396 100644 (file)
@@ -1,3 +1,52 @@
+Mon Aug 24 02:08:56 1998  Tim Janik  <timj@gtk.org>
+
+       * glib.h:
+       * gstring.c:
+       * gstrfuncs.c:
+       (g_vsprintf): removed this function which was not publically
+       exported in glib.h. to export it, it should have been named
+       differently in the first place, since its semantics differ from
+       vsprintf(). apart from that, it was a possible cause for
+       problems since it worked on a previously allocated memory area and
+       was used in a lot places of glib. exporting it would have been a
+       guararant for problems with threaded programs.
+       (g_printf_string_upper_bound): exported this function to return
+       a string size, guarranteed to be big enough to hold the fully
+       expanded format+args string. added 'q', 'L' and 'll' flag handling.
+       in fact, the newly allocated area is in most cases much bigger than
+       required.
+       (g_strdup_vprintf()): new function returning a newly allocated string
+       containing the contents of *format and associated args (size is
+       calculated with g_printf_string_upper_bound()).
+       (g_strdup_printf): new function which wraps g_strdup_vprintf().
+
+       * configure.in: check for va_copy() or __va_copy() alternatively.
+       check whether va_lists can be copyied by value.
+
+       * glib.h: provide a definition for G_VA_COPY.
+
+       * glib.h:
+       * gmessages.c: 
+       (g_logv): 
+       (g_vsnprintf):
+       pass va_lists by value, not by reference, since this causes problems
+       on platforms that implement va_list as as arrays. internaly, use
+       G_VA_COPY (new_arg, org_arg); va_end (new_arg); to produce a second
+       va_list variable, if multiple passes are required. changed all
+       callers.
+
+       * glib.h:
+       * gerror.h:
+       renamed g_debug() to g_on_error_query(), cleaned up a bit.
+       renamed g_stack_trace() to g_on_error_stack_trace() since both
+       functions cluttered different namespaces.
+       there is an appropriate comment in glib.h now that explains the
+       unix and gdb specific dependencies of both functions.
+       removed g_attach_process().
+       g_on_error_stack_trace() should probably be handled with caution,
+       i've seem several different linux versions (2.0.x) become unstable
+       after invokation of this function.
+
 1998-08-18: Elliot Lee <sopwith@redhat.com>
 
        . In gmem.c, add the ability to exclude memory chunks from the
diff --git a/NEWS b/NEWS
index d4c8ea8..8068051 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,14 @@ Overview of Changes in GLib 1.1.3:
 
 * New library gmodule included which basically wraps dlopen() facilities.
 * New g_log() mechanism for logging of messages at different log levels,
-  associated with certain log domains.
+  associated with certain log domains (define -DG_LOG_DOMAIN for your module).
+* New inline functions for bit masks tests.
+* GNode functions now return the newly allocated node.
+* New macro G_VA_COPY() to work around va_list copying oddities on some
+  platforms. the non-static g_vsprintf() function vanished in favour of
+  a publically exported g_strdup_vprintf().
+* New utility functions for string and printf-like format handling .
+* Lotsa bug fixes and cleanups as always ;)
 
 Overview of Changes in GLib 1.1.2:
 
index e5fd43b..9c4e45f 100644 (file)
@@ -62,6 +62,9 @@
 #undef SIZEOF_INT
 #undef SIZEOF_VOID_P
 
+#undef G_VA_COPY
+#undef G_VA_COPY_AS_ARRAY
+
 #undef GLIB_MAJOR_VERSION
 #undef GLIB_MINOR_VERSION
 #undef GLIB_MICRO_VERSION
index 6b1d684..533bda8 100644 (file)
@@ -222,6 +222,87 @@ if test $gtk_ok = no; then
 fi
 AC_MSG_RESULT($gtk_ok)
 
+dnl **********************
+dnl *** va_copy checks ***
+dnl **********************
+dnl we currently check for all three cases, so we get all results in config.log
+AC_MSG_CHECKING(for an implementation of va_copy())
+AC_CACHE_VAL(glib_cv_va_copy,[
+       AC_TRY_RUN([
+       #include <stdarg.h>
+       void f (int i, ...) {
+       va_list args1, args2;
+       va_start (args1, i);
+       va_copy (args2, args1);
+       if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+         exit (1);
+       va_end (args1); va_end (args2);
+       }
+       int main() {
+         f (0, 42);
+         return 0;
+       }],
+       glib_cv_va_copy=yes
+       ,
+       glib_cv_va_copy=no
+       ,)
+])
+AC_MSG_RESULT($glib_cv_va_copy)
+AC_MSG_CHECKING(for an implementation of __va_copy())
+AC_CACHE_VAL(glib_cv___va_copy,[
+       AC_TRY_RUN([
+       #include <stdarg.h>
+       void f (int i, ...) {
+       va_list args1, args2;
+       va_start (args1, i);
+       __va_copy (args2, args1);
+       if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+         exit (1);
+       va_end (args1); va_end (args2);
+       }
+       int main() {
+         f (0, 42);
+         return 0;
+       }],
+       glib_cv___va_copy=yes
+       ,
+       glib_cv___va_copy=no
+       ,)
+])
+AC_MSG_RESULT($glib_cv___va_copy)
+AC_MSG_CHECKING(whether va_lists can be copied by value)
+AC_CACHE_VAL(glib_cv_va_val_copy,[
+       AC_TRY_RUN([
+       #include <stdarg.h>
+       void f (int i, ...) {
+       va_list args1, args2;
+       va_start (args1, i);
+       args2 = args1;
+       if (va_arg (args2, int) != 42 || va_arg (args1, int) != 42)
+         exit (1);
+       va_end (args1); va_end (args2);
+       }
+       int main() {
+         f (0, 42);
+         return 0;
+       }],
+       glib_cv_va_val_copy=yes
+       ,
+       glib_cv_va_val_copy=no
+       ,)
+])
+if test "x$glib_cv_va_copy" = "xyes"; then
+  AC_DEFINE(G_VA_COPY, va_copy)
+else if test "x$glib_cv___va_copy" = "xyes"; then
+  AC_DEFINE(G_VA_COPY, __va_copy)
+fi
+fi
+if test "x$glib_cv_va_val_copy" = "xno"; then
+  AC_DEFINE(G_VA_COPY_AS_ARRAY)
+fi
+AC_MSG_RESULT($glib_cv_va_val_copy)
+
+
 dnl ***********************
 dnl *** g_module checks ***
 dnl ***********************
index cff505b..b2834b2 100644 (file)
@@ -36,9 +36,6 @@
 #include <string.h> /* for bzero on BSD systems */
 #endif
 
-#define INTERACTIVE 0
-#define STACK_TRACE 1
-
 
 #ifndef NO_FD_SET
 #  define SELECT_MASK fd_set
 #endif
 
 
-static int  do_query (char *prompt);
-static void debug (const gchar *progname, int method);
-static void stack_trace (char **);
-static void stack_trace_sigchld (int);
-
+static void stack_trace (char **args);
 
-static int stack_trace_done;
+extern volatile gboolean glib_on_error_halt;
+volatile gboolean glib_on_error_halt = TRUE;
 
 void
-g_debug (const gchar *progname)
+g_on_error_query (const gchar *prg_name)
 {
-  char buf[32];
-
-  fprintf (stdout, "[n]othing, [e]xit, [s]tack trace, [a]ttach to process: ");
+  static const gchar *query1 = "[E]xit, [H]alt";
+  static const gchar *query2 = ", show [S]tack trace";
+  static const gchar *query3 = " or [P]roceed";
+  gchar buf[16];
+
+  if (!prg_name)
+    prg_name = g_get_prgname ();
+  
+ retry:
+  
+  if (prg_name)
+    fprintf (stdout,
+            "%s (pid:%u): %s%s%s: ",
+            prg_name,
+            (guint) getpid (),
+            query1,
+            query2,
+            query3);
+  else
+    fprintf (stdout,
+            "(process:%u): %s%s: ",
+            (guint) getpid (),
+            query1,
+            query3);
   fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if (strcmp (buf, "n\n") == 0)
+  
+  fgets (buf, 8, stdin);
+
+  if ((buf[0] == 'E' || buf[0] == 'e')
+      && buf[1] == '\n')
+    _exit (0);
+  else if ((buf[0] == 'P' || buf[0] == 'p')
+          && buf[1] == '\n')
     return;
-  else if (strcmp (buf, "s\n") == 0)
-    debug (progname, STACK_TRACE);
-  else if (strcmp (buf, "a\n") == 0)
-    debug (progname, INTERACTIVE);
+  else if (prg_name
+          && (buf[0] == 'S' || buf[0] == 's')
+          && buf[1] == '\n')
+    {
+      g_on_error_stack_trace (prg_name);
+      goto retry;
+    }
+  else if ((buf[0] == 'H' || buf[0] == 'h')
+          && buf[1] == '\n')
+    {
+      while (glib_on_error_halt)
+       ;
+      glib_on_error_halt = TRUE;
+      return;
+    }
   else
-    exit (0);
-}
-
-void
-g_attach_process (const gchar *progname,
-                 gboolean     query)
-{
-  if (!query || do_query ("attach to process"))
-    debug (progname, INTERACTIVE);
+    goto retry;
 }
 
 void
-g_stack_trace (const gchar *progname,
-              gboolean     query)
-{
-  if (!query || do_query ("print stack trace"))
-    debug (progname, STACK_TRACE);
-}
-
-static int
-do_query (char *prompt)
-{
-  char buf[32];
-
-  fprintf (stdout, "%s (y/n) ", prompt);
-  fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if ((strcmp (buf, "yes\n") == 0) ||
-      (strcmp (buf, "y\n") == 0) ||
-      (strcmp (buf, "YES\n") == 0) ||
-      (strcmp (buf, "Y\n") == 0))
-    return TRUE;
-
-  return FALSE;
-}
-
-static void
-debug (const char *progname,
-       int   method)
+g_on_error_stack_trace (const gchar *prg_name)
 {
   pid_t pid;
-  char buf[16];
-  char *args[4] = { "gdb", NULL, NULL, NULL };
-  volatile int x;
+  gchar buf[16];
+  gchar *args[4] = { "gdb", NULL, NULL, NULL };
+
+  if (!prg_name)
+    return;
 
-  sprintf (buf, "%d", (int) getpid ());
+  sprintf (buf, "%u", (guint) getpid ());
 
-  args[1] = (gchar*) progname;
+  args[1] = (gchar*) prg_name;
   args[2] = buf;
 
-  switch (method)
+  pid = fork ();
+  if (pid == 0)
     {
-    case INTERACTIVE:
-      fprintf (stdout, "pid: %s\n", buf);
-      break;
-    case STACK_TRACE:
-      pid = fork ();
-      if (pid == 0)
-       {
-         stack_trace (args);
-         _exit (0);
-       }
-      else if (pid == (pid_t) -1)
-       {
-         perror ("could not fork");
-         return;
-       }
-      break;
+      stack_trace (args);
+      _exit (0);
     }
-
-  x = 1;
-  while (x)
+  else if (pid == (pid_t) -1)
+    {
+      perror ("unable to fork gdb");
+      return;
+    }
+  
+  while (glib_on_error_halt)
     ;
+  glib_on_error_halt = TRUE;
+}
+
+static gboolean stack_trace_done = FALSE;
+
+static void
+stack_trace_sigchld (int signum)
+{
+  stack_trace_done = TRUE;
 }
 
 static void
@@ -167,12 +165,12 @@ stack_trace (char **args)
   char buffer[256];
   char c;
 
-  stack_trace_done = 0;
+  stack_trace_done = FALSE;
   signal (SIGCHLD, stack_trace_sigchld);
 
   if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
     {
-      perror ("could open pipe");
+      perror ("unable to open pipe");
       _exit (0);
     }
 
@@ -189,7 +187,7 @@ stack_trace (char **args)
     }
   else if (pid == (pid_t) -1)
     {
-      perror ("could not fork");
+      perror ("unable to fork");
       _exit (0);
     }
 
@@ -252,9 +250,3 @@ stack_trace (char **args)
   close (out_fd[1]);
   _exit (0);
 }
-
-static void
-stack_trace_sigchld (int signum)
-{
-  stack_trace_done = 1;
-}
index cff505b..b2834b2 100644 (file)
--- a/gerror.c
+++ b/gerror.c
@@ -36,9 +36,6 @@
 #include <string.h> /* for bzero on BSD systems */
 #endif
 
-#define INTERACTIVE 0
-#define STACK_TRACE 1
-
 
 #ifndef NO_FD_SET
 #  define SELECT_MASK fd_set
 #endif
 
 
-static int  do_query (char *prompt);
-static void debug (const gchar *progname, int method);
-static void stack_trace (char **);
-static void stack_trace_sigchld (int);
-
+static void stack_trace (char **args);
 
-static int stack_trace_done;
+extern volatile gboolean glib_on_error_halt;
+volatile gboolean glib_on_error_halt = TRUE;
 
 void
-g_debug (const gchar *progname)
+g_on_error_query (const gchar *prg_name)
 {
-  char buf[32];
-
-  fprintf (stdout, "[n]othing, [e]xit, [s]tack trace, [a]ttach to process: ");
+  static const gchar *query1 = "[E]xit, [H]alt";
+  static const gchar *query2 = ", show [S]tack trace";
+  static const gchar *query3 = " or [P]roceed";
+  gchar buf[16];
+
+  if (!prg_name)
+    prg_name = g_get_prgname ();
+  
+ retry:
+  
+  if (prg_name)
+    fprintf (stdout,
+            "%s (pid:%u): %s%s%s: ",
+            prg_name,
+            (guint) getpid (),
+            query1,
+            query2,
+            query3);
+  else
+    fprintf (stdout,
+            "(process:%u): %s%s: ",
+            (guint) getpid (),
+            query1,
+            query3);
   fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if (strcmp (buf, "n\n") == 0)
+  
+  fgets (buf, 8, stdin);
+
+  if ((buf[0] == 'E' || buf[0] == 'e')
+      && buf[1] == '\n')
+    _exit (0);
+  else if ((buf[0] == 'P' || buf[0] == 'p')
+          && buf[1] == '\n')
     return;
-  else if (strcmp (buf, "s\n") == 0)
-    debug (progname, STACK_TRACE);
-  else if (strcmp (buf, "a\n") == 0)
-    debug (progname, INTERACTIVE);
+  else if (prg_name
+          && (buf[0] == 'S' || buf[0] == 's')
+          && buf[1] == '\n')
+    {
+      g_on_error_stack_trace (prg_name);
+      goto retry;
+    }
+  else if ((buf[0] == 'H' || buf[0] == 'h')
+          && buf[1] == '\n')
+    {
+      while (glib_on_error_halt)
+       ;
+      glib_on_error_halt = TRUE;
+      return;
+    }
   else
-    exit (0);
-}
-
-void
-g_attach_process (const gchar *progname,
-                 gboolean     query)
-{
-  if (!query || do_query ("attach to process"))
-    debug (progname, INTERACTIVE);
+    goto retry;
 }
 
 void
-g_stack_trace (const gchar *progname,
-              gboolean     query)
-{
-  if (!query || do_query ("print stack trace"))
-    debug (progname, STACK_TRACE);
-}
-
-static int
-do_query (char *prompt)
-{
-  char buf[32];
-
-  fprintf (stdout, "%s (y/n) ", prompt);
-  fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if ((strcmp (buf, "yes\n") == 0) ||
-      (strcmp (buf, "y\n") == 0) ||
-      (strcmp (buf, "YES\n") == 0) ||
-      (strcmp (buf, "Y\n") == 0))
-    return TRUE;
-
-  return FALSE;
-}
-
-static void
-debug (const char *progname,
-       int   method)
+g_on_error_stack_trace (const gchar *prg_name)
 {
   pid_t pid;
-  char buf[16];
-  char *args[4] = { "gdb", NULL, NULL, NULL };
-  volatile int x;
+  gchar buf[16];
+  gchar *args[4] = { "gdb", NULL, NULL, NULL };
+
+  if (!prg_name)
+    return;
 
-  sprintf (buf, "%d", (int) getpid ());
+  sprintf (buf, "%u", (guint) getpid ());
 
-  args[1] = (gchar*) progname;
+  args[1] = (gchar*) prg_name;
   args[2] = buf;
 
-  switch (method)
+  pid = fork ();
+  if (pid == 0)
     {
-    case INTERACTIVE:
-      fprintf (stdout, "pid: %s\n", buf);
-      break;
-    case STACK_TRACE:
-      pid = fork ();
-      if (pid == 0)
-       {
-         stack_trace (args);
-         _exit (0);
-       }
-      else if (pid == (pid_t) -1)
-       {
-         perror ("could not fork");
-         return;
-       }
-      break;
+      stack_trace (args);
+      _exit (0);
     }
-
-  x = 1;
-  while (x)
+  else if (pid == (pid_t) -1)
+    {
+      perror ("unable to fork gdb");
+      return;
+    }
+  
+  while (glib_on_error_halt)
     ;
+  glib_on_error_halt = TRUE;
+}
+
+static gboolean stack_trace_done = FALSE;
+
+static void
+stack_trace_sigchld (int signum)
+{
+  stack_trace_done = TRUE;
 }
 
 static void
@@ -167,12 +165,12 @@ stack_trace (char **args)
   char buffer[256];
   char c;
 
-  stack_trace_done = 0;
+  stack_trace_done = FALSE;
   signal (SIGCHLD, stack_trace_sigchld);
 
   if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
     {
-      perror ("could open pipe");
+      perror ("unable to open pipe");
       _exit (0);
     }
 
@@ -189,7 +187,7 @@ stack_trace (char **args)
     }
   else if (pid == (pid_t) -1)
     {
-      perror ("could not fork");
+      perror ("unable to fork");
       _exit (0);
     }
 
@@ -252,9 +250,3 @@ stack_trace (char **args)
   close (out_fd[1]);
   _exit (0);
 }
-
-static void
-stack_trace_sigchld (int signum)
-{
-  stack_trace_done = 1;
-}
diff --git a/glib.h b/glib.h
index 8dacdf1..62ade5d 100644 (file)
--- a/glib.h
+++ b/glib.h
 #define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
 
 
+/* Define G_VA_COPY() to do the right thing for copying va_list variables.
+ * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy.
+ */
+#if !defined (G_VA_COPY)
+#  if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
+#  define G_VA_COPY(ap1, ap2)     (*(ap1) = *(ap2))
+#  elif defined (G_VA_COPY_AS_ARRAY)
+#  define G_VA_COPY(ap1, ap2)     g_memmove ((ap1), (ap2), sizeof (va_list))
+#  else /* va_list is a pointer */
+#  define G_VA_COPY(ap1, ap2)     ((ap1) = (ap2))
+#  endif /* va_list is a pointer */
+#endif /* !G_VA_COPY */
+
+
 /* Provide simple enum value macro wrappers that ease automated
  * enum value stringification code. [abandoned]
  */
@@ -926,13 +940,17 @@ GNode*     g_node_last_sibling     (GNode           *node);
                                         ((GNode*) (node))->children : NULL)
 
 
-/* Fatal error handlers
+/* Fatal error handlers.
+ * g_on_error_query() will prompt the user to either
+ * [E]xit, [H]alt, [P]roceed or show [S]tack trace.
+ * g_on_error_stack_trace() invokes gdb, which attaches to the current
+ * process and shows a stack trace.
+ * These function may cause different actions on non-unix platforms.
+ * The prg_name arg is required by gdb to find the executable, if it is
+ * passed as NULL, g_on_error_query() will try g_get_prgname().
  */
-void g_attach_process (const gchar *progname,
-                      gboolean     query);
-void g_debug         (const gchar *progname);
-void g_stack_trace    (const gchar *progname,
-                      gboolean     query);
+void g_on_error_query (const gchar *prg_name);
+void g_on_error_stack_trace (const gchar *prg_name);
 
 
 /* Logging mechanism
@@ -955,8 +973,7 @@ void                g_log                   (const gchar    *log_domain,
 void           g_logv                  (const gchar    *log_domain,
                                         GLogLevelFlags  log_level,
                                         const gchar    *format,
-                                        va_list        *args1,
-                                        va_list        *args2);
+                                        va_list         args);
 GLogLevelFlags g_log_set_fatal_mask    (const gchar    *log_domain,
                                         GLogLevelFlags  fatal_mask);
 GLogLevelFlags g_log_set_always_fatal  (GLogLevelFlags  fatal_mask);
@@ -978,28 +995,28 @@ static inline void
 g_error (const gchar *format,
         ...)
 {
-  va_list arg_list1, arg_list2;
-  va_start (arg_list1, format); va_start (arg_list2, format);
-  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, &arg_list1, &arg_list2);
-  va_end (arg_list2); va_end (arg_list1);
+  va_list args;
+  va_start (args, format);
+  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, args);
+  va_end (args);
 }
 static inline void
 g_message (const gchar *format,
           ...)
 {
-  va_list arg_list1, arg_list2;
-  va_start (arg_list1, format); va_start (arg_list2, format);
-  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, &arg_list1, &arg_list2);
-  va_end (arg_list2); va_end (arg_list1);
+  va_list args;
+  va_start (args, format);
+  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, args);
+  va_end (args);
 }
 static inline void
 g_warning (const gchar *format,
           ...)
 {
-  va_list arg_list1, arg_list2;
-  va_start (arg_list1, format); va_start (arg_list2, format);
-  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, &arg_list1, &arg_list2);
-  va_end (arg_list2); va_end (arg_list1);
+  va_list args;
+  va_start (args, format);
+  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, args);
+  va_end (args);
 }
 #endif /* !__GNUC__ */
 
@@ -1106,6 +1123,10 @@ void     g_strdelimit            (gchar       *string,
                                 const gchar *delimiters,
                                 gchar        new_delimiter);
 gchar* g_strdup                (const gchar *str);
+gchar* g_strdup_printf         (const gchar *format,
+                                ...) G_GNUC_PRINTF (1, 2);
+gchar* g_strdup_vprintf        (const gchar *format,
+                                va_list      args);
 gchar* g_strndup               (const gchar *str,
                                 gulong n);
 gchar* g_strconcat             (const gchar *string1,
@@ -1120,6 +1141,11 @@ void     g_strdown               (gchar       *string);
 void   g_strup                 (gchar       *string);
 void   g_strreverse            (gchar       *string);
 
+/* calculate a string size, guarranteed to fit format + args.
+ */
+guint  g_printf_string_upper_bound (const gchar* format,
+                                    va_list      args);
+
 
 /* Retrive static string info
  */
@@ -1143,8 +1169,7 @@ gint      g_snprintf              (gchar       *string,
 gint   g_vsnprintf             (gchar       *string,
                                 gulong       n,
                                 gchar const *format,
-                                va_list     *args1,
-                                va_list     *args2);
+                                va_list      args);
 gchar* g_basename              (const gchar *file_name);
 
 /* strings are newly allocated with g_malloc() */
index cff505b..b2834b2 100644 (file)
@@ -36,9 +36,6 @@
 #include <string.h> /* for bzero on BSD systems */
 #endif
 
-#define INTERACTIVE 0
-#define STACK_TRACE 1
-
 
 #ifndef NO_FD_SET
 #  define SELECT_MASK fd_set
 #endif
 
 
-static int  do_query (char *prompt);
-static void debug (const gchar *progname, int method);
-static void stack_trace (char **);
-static void stack_trace_sigchld (int);
-
+static void stack_trace (char **args);
 
-static int stack_trace_done;
+extern volatile gboolean glib_on_error_halt;
+volatile gboolean glib_on_error_halt = TRUE;
 
 void
-g_debug (const gchar *progname)
+g_on_error_query (const gchar *prg_name)
 {
-  char buf[32];
-
-  fprintf (stdout, "[n]othing, [e]xit, [s]tack trace, [a]ttach to process: ");
+  static const gchar *query1 = "[E]xit, [H]alt";
+  static const gchar *query2 = ", show [S]tack trace";
+  static const gchar *query3 = " or [P]roceed";
+  gchar buf[16];
+
+  if (!prg_name)
+    prg_name = g_get_prgname ();
+  
+ retry:
+  
+  if (prg_name)
+    fprintf (stdout,
+            "%s (pid:%u): %s%s%s: ",
+            prg_name,
+            (guint) getpid (),
+            query1,
+            query2,
+            query3);
+  else
+    fprintf (stdout,
+            "(process:%u): %s%s: ",
+            (guint) getpid (),
+            query1,
+            query3);
   fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if (strcmp (buf, "n\n") == 0)
+  
+  fgets (buf, 8, stdin);
+
+  if ((buf[0] == 'E' || buf[0] == 'e')
+      && buf[1] == '\n')
+    _exit (0);
+  else if ((buf[0] == 'P' || buf[0] == 'p')
+          && buf[1] == '\n')
     return;
-  else if (strcmp (buf, "s\n") == 0)
-    debug (progname, STACK_TRACE);
-  else if (strcmp (buf, "a\n") == 0)
-    debug (progname, INTERACTIVE);
+  else if (prg_name
+          && (buf[0] == 'S' || buf[0] == 's')
+          && buf[1] == '\n')
+    {
+      g_on_error_stack_trace (prg_name);
+      goto retry;
+    }
+  else if ((buf[0] == 'H' || buf[0] == 'h')
+          && buf[1] == '\n')
+    {
+      while (glib_on_error_halt)
+       ;
+      glib_on_error_halt = TRUE;
+      return;
+    }
   else
-    exit (0);
-}
-
-void
-g_attach_process (const gchar *progname,
-                 gboolean     query)
-{
-  if (!query || do_query ("attach to process"))
-    debug (progname, INTERACTIVE);
+    goto retry;
 }
 
 void
-g_stack_trace (const gchar *progname,
-              gboolean     query)
-{
-  if (!query || do_query ("print stack trace"))
-    debug (progname, STACK_TRACE);
-}
-
-static int
-do_query (char *prompt)
-{
-  char buf[32];
-
-  fprintf (stdout, "%s (y/n) ", prompt);
-  fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if ((strcmp (buf, "yes\n") == 0) ||
-      (strcmp (buf, "y\n") == 0) ||
-      (strcmp (buf, "YES\n") == 0) ||
-      (strcmp (buf, "Y\n") == 0))
-    return TRUE;
-
-  return FALSE;
-}
-
-static void
-debug (const char *progname,
-       int   method)
+g_on_error_stack_trace (const gchar *prg_name)
 {
   pid_t pid;
-  char buf[16];
-  char *args[4] = { "gdb", NULL, NULL, NULL };
-  volatile int x;
+  gchar buf[16];
+  gchar *args[4] = { "gdb", NULL, NULL, NULL };
+
+  if (!prg_name)
+    return;
 
-  sprintf (buf, "%d", (int) getpid ());
+  sprintf (buf, "%u", (guint) getpid ());
 
-  args[1] = (gchar*) progname;
+  args[1] = (gchar*) prg_name;
   args[2] = buf;
 
-  switch (method)
+  pid = fork ();
+  if (pid == 0)
     {
-    case INTERACTIVE:
-      fprintf (stdout, "pid: %s\n", buf);
-      break;
-    case STACK_TRACE:
-      pid = fork ();
-      if (pid == 0)
-       {
-         stack_trace (args);
-         _exit (0);
-       }
-      else if (pid == (pid_t) -1)
-       {
-         perror ("could not fork");
-         return;
-       }
-      break;
+      stack_trace (args);
+      _exit (0);
     }
-
-  x = 1;
-  while (x)
+  else if (pid == (pid_t) -1)
+    {
+      perror ("unable to fork gdb");
+      return;
+    }
+  
+  while (glib_on_error_halt)
     ;
+  glib_on_error_halt = TRUE;
+}
+
+static gboolean stack_trace_done = FALSE;
+
+static void
+stack_trace_sigchld (int signum)
+{
+  stack_trace_done = TRUE;
 }
 
 static void
@@ -167,12 +165,12 @@ stack_trace (char **args)
   char buffer[256];
   char c;
 
-  stack_trace_done = 0;
+  stack_trace_done = FALSE;
   signal (SIGCHLD, stack_trace_sigchld);
 
   if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
     {
-      perror ("could open pipe");
+      perror ("unable to open pipe");
       _exit (0);
     }
 
@@ -189,7 +187,7 @@ stack_trace (char **args)
     }
   else if (pid == (pid_t) -1)
     {
-      perror ("could not fork");
+      perror ("unable to fork");
       _exit (0);
     }
 
@@ -252,9 +250,3 @@ stack_trace (char **args)
   close (out_fd[1]);
   _exit (0);
 }
-
-static void
-stack_trace_sigchld (int signum)
-{
-  stack_trace_done = 1;
-}
index cff505b..b2834b2 100644 (file)
@@ -36,9 +36,6 @@
 #include <string.h> /* for bzero on BSD systems */
 #endif
 
-#define INTERACTIVE 0
-#define STACK_TRACE 1
-
 
 #ifndef NO_FD_SET
 #  define SELECT_MASK fd_set
 #endif
 
 
-static int  do_query (char *prompt);
-static void debug (const gchar *progname, int method);
-static void stack_trace (char **);
-static void stack_trace_sigchld (int);
-
+static void stack_trace (char **args);
 
-static int stack_trace_done;
+extern volatile gboolean glib_on_error_halt;
+volatile gboolean glib_on_error_halt = TRUE;
 
 void
-g_debug (const gchar *progname)
+g_on_error_query (const gchar *prg_name)
 {
-  char buf[32];
-
-  fprintf (stdout, "[n]othing, [e]xit, [s]tack trace, [a]ttach to process: ");
+  static const gchar *query1 = "[E]xit, [H]alt";
+  static const gchar *query2 = ", show [S]tack trace";
+  static const gchar *query3 = " or [P]roceed";
+  gchar buf[16];
+
+  if (!prg_name)
+    prg_name = g_get_prgname ();
+  
+ retry:
+  
+  if (prg_name)
+    fprintf (stdout,
+            "%s (pid:%u): %s%s%s: ",
+            prg_name,
+            (guint) getpid (),
+            query1,
+            query2,
+            query3);
+  else
+    fprintf (stdout,
+            "(process:%u): %s%s: ",
+            (guint) getpid (),
+            query1,
+            query3);
   fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if (strcmp (buf, "n\n") == 0)
+  
+  fgets (buf, 8, stdin);
+
+  if ((buf[0] == 'E' || buf[0] == 'e')
+      && buf[1] == '\n')
+    _exit (0);
+  else if ((buf[0] == 'P' || buf[0] == 'p')
+          && buf[1] == '\n')
     return;
-  else if (strcmp (buf, "s\n") == 0)
-    debug (progname, STACK_TRACE);
-  else if (strcmp (buf, "a\n") == 0)
-    debug (progname, INTERACTIVE);
+  else if (prg_name
+          && (buf[0] == 'S' || buf[0] == 's')
+          && buf[1] == '\n')
+    {
+      g_on_error_stack_trace (prg_name);
+      goto retry;
+    }
+  else if ((buf[0] == 'H' || buf[0] == 'h')
+          && buf[1] == '\n')
+    {
+      while (glib_on_error_halt)
+       ;
+      glib_on_error_halt = TRUE;
+      return;
+    }
   else
-    exit (0);
-}
-
-void
-g_attach_process (const gchar *progname,
-                 gboolean     query)
-{
-  if (!query || do_query ("attach to process"))
-    debug (progname, INTERACTIVE);
+    goto retry;
 }
 
 void
-g_stack_trace (const gchar *progname,
-              gboolean     query)
-{
-  if (!query || do_query ("print stack trace"))
-    debug (progname, STACK_TRACE);
-}
-
-static int
-do_query (char *prompt)
-{
-  char buf[32];
-
-  fprintf (stdout, "%s (y/n) ", prompt);
-  fflush (stdout);
-
-  fgets (buf, 32, stdin);
-  if ((strcmp (buf, "yes\n") == 0) ||
-      (strcmp (buf, "y\n") == 0) ||
-      (strcmp (buf, "YES\n") == 0) ||
-      (strcmp (buf, "Y\n") == 0))
-    return TRUE;
-
-  return FALSE;
-}
-
-static void
-debug (const char *progname,
-       int   method)
+g_on_error_stack_trace (const gchar *prg_name)
 {
   pid_t pid;
-  char buf[16];
-  char *args[4] = { "gdb", NULL, NULL, NULL };
-  volatile int x;
+  gchar buf[16];
+  gchar *args[4] = { "gdb", NULL, NULL, NULL };
+
+  if (!prg_name)
+    return;
 
-  sprintf (buf, "%d", (int) getpid ());
+  sprintf (buf, "%u", (guint) getpid ());
 
-  args[1] = (gchar*) progname;
+  args[1] = (gchar*) prg_name;
   args[2] = buf;
 
-  switch (method)
+  pid = fork ();
+  if (pid == 0)
     {
-    case INTERACTIVE:
-      fprintf (stdout, "pid: %s\n", buf);
-      break;
-    case STACK_TRACE:
-      pid = fork ();
-      if (pid == 0)
-       {
-         stack_trace (args);
-         _exit (0);
-       }
-      else if (pid == (pid_t) -1)
-       {
-         perror ("could not fork");
-         return;
-       }
-      break;
+      stack_trace (args);
+      _exit (0);
     }
-
-  x = 1;
-  while (x)
+  else if (pid == (pid_t) -1)
+    {
+      perror ("unable to fork gdb");
+      return;
+    }
+  
+  while (glib_on_error_halt)
     ;
+  glib_on_error_halt = TRUE;
+}
+
+static gboolean stack_trace_done = FALSE;
+
+static void
+stack_trace_sigchld (int signum)
+{
+  stack_trace_done = TRUE;
 }
 
 static void
@@ -167,12 +165,12 @@ stack_trace (char **args)
   char buffer[256];
   char c;
 
-  stack_trace_done = 0;
+  stack_trace_done = FALSE;
   signal (SIGCHLD, stack_trace_sigchld);
 
   if ((pipe (in_fd) == -1) || (pipe (out_fd) == -1))
     {
-      perror ("could open pipe");
+      perror ("unable to open pipe");
       _exit (0);
     }
 
@@ -189,7 +187,7 @@ stack_trace (char **args)
     }
   else if (pid == (pid_t) -1)
     {
-      perror ("could not fork");
+      perror ("unable to fork");
       _exit (0);
     }
 
@@ -252,9 +250,3 @@ stack_trace (char **args)
   close (out_fd[1]);
   _exit (0);
 }
-
-static void
-stack_trace_sigchld (int signum)
-{
-  stack_trace_done = 1;
-}
index 8dacdf1..62ade5d 100644 (file)
 #define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
 
 
+/* Define G_VA_COPY() to do the right thing for copying va_list variables.
+ * glibconfig.h may have already defined G_VA_COPY as va_copy or __va_copy.
+ */
+#if !defined (G_VA_COPY)
+#  if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
+#  define G_VA_COPY(ap1, ap2)     (*(ap1) = *(ap2))
+#  elif defined (G_VA_COPY_AS_ARRAY)
+#  define G_VA_COPY(ap1, ap2)     g_memmove ((ap1), (ap2), sizeof (va_list))
+#  else /* va_list is a pointer */
+#  define G_VA_COPY(ap1, ap2)     ((ap1) = (ap2))
+#  endif /* va_list is a pointer */
+#endif /* !G_VA_COPY */
+
+
 /* Provide simple enum value macro wrappers that ease automated
  * enum value stringification code. [abandoned]
  */
@@ -926,13 +940,17 @@ GNode*     g_node_last_sibling     (GNode           *node);
                                         ((GNode*) (node))->children : NULL)
 
 
-/* Fatal error handlers
+/* Fatal error handlers.
+ * g_on_error_query() will prompt the user to either
+ * [E]xit, [H]alt, [P]roceed or show [S]tack trace.
+ * g_on_error_stack_trace() invokes gdb, which attaches to the current
+ * process and shows a stack trace.
+ * These function may cause different actions on non-unix platforms.
+ * The prg_name arg is required by gdb to find the executable, if it is
+ * passed as NULL, g_on_error_query() will try g_get_prgname().
  */
-void g_attach_process (const gchar *progname,
-                      gboolean     query);
-void g_debug         (const gchar *progname);
-void g_stack_trace    (const gchar *progname,
-                      gboolean     query);
+void g_on_error_query (const gchar *prg_name);
+void g_on_error_stack_trace (const gchar *prg_name);
 
 
 /* Logging mechanism
@@ -955,8 +973,7 @@ void                g_log                   (const gchar    *log_domain,
 void           g_logv                  (const gchar    *log_domain,
                                         GLogLevelFlags  log_level,
                                         const gchar    *format,
-                                        va_list        *args1,
-                                        va_list        *args2);
+                                        va_list         args);
 GLogLevelFlags g_log_set_fatal_mask    (const gchar    *log_domain,
                                         GLogLevelFlags  fatal_mask);
 GLogLevelFlags g_log_set_always_fatal  (GLogLevelFlags  fatal_mask);
@@ -978,28 +995,28 @@ static inline void
 g_error (const gchar *format,
         ...)
 {
-  va_list arg_list1, arg_list2;
-  va_start (arg_list1, format); va_start (arg_list2, format);
-  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, &arg_list1, &arg_list2);
-  va_end (arg_list2); va_end (arg_list1);
+  va_list args;
+  va_start (args, format);
+  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, format, args);
+  va_end (args);
 }
 static inline void
 g_message (const gchar *format,
           ...)
 {
-  va_list arg_list1, arg_list2;
-  va_start (arg_list1, format); va_start (arg_list2, format);
-  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, &arg_list1, &arg_list2);
-  va_end (arg_list2); va_end (arg_list1);
+  va_list args;
+  va_start (args, format);
+  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, args);
+  va_end (args);
 }
 static inline void
 g_warning (const gchar *format,
           ...)
 {
-  va_list arg_list1, arg_list2;
-  va_start (arg_list1, format); va_start (arg_list2, format);
-  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, &arg_list1, &arg_list2);
-  va_end (arg_list2); va_end (arg_list1);
+  va_list args;
+  va_start (args, format);
+  g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, format, args);
+  va_end (args);
 }
 #endif /* !__GNUC__ */
 
@@ -1106,6 +1123,10 @@ void     g_strdelimit            (gchar       *string,
                                 const gchar *delimiters,
                                 gchar        new_delimiter);
 gchar* g_strdup                (const gchar *str);
+gchar* g_strdup_printf         (const gchar *format,
+                                ...) G_GNUC_PRINTF (1, 2);
+gchar* g_strdup_vprintf        (const gchar *format,
+                                va_list      args);
 gchar* g_strndup               (const gchar *str,
                                 gulong n);
 gchar* g_strconcat             (const gchar *string1,
@@ -1120,6 +1141,11 @@ void     g_strdown               (gchar       *string);
 void   g_strup                 (gchar       *string);
 void   g_strreverse            (gchar       *string);
 
+/* calculate a string size, guarranteed to fit format + args.
+ */
+guint  g_printf_string_upper_bound (const gchar* format,
+                                    va_list      args);
+
 
 /* Retrive static string info
  */
@@ -1143,8 +1169,7 @@ gint      g_snprintf              (gchar       *string,
 gint   g_vsnprintf             (gchar       *string,
                                 gulong       n,
                                 gchar const *format,
-                                va_list     *args1,
-                                va_list     *args2);
+                                va_list      args);
 gchar* g_basename              (const gchar *file_name);
 
 /* strings are newly allocated with g_malloc() */
index f8271af..12a2c59 100644 (file)
@@ -43,12 +43,6 @@ struct _GLogHandler
 };
 
 
-/* --- prototypes --- */
-extern gchar* g_vsprintf (const gchar *fmt,
-                         va_list     *args,
-                         va_list     *args2);
-
-
 /* --- variables --- */
 const gchar         *g_log_domain_glib = "GLib";
 static GLogDomain    *g_log_domains = NULL;
@@ -258,9 +252,9 @@ void
 g_logv (const gchar    *log_domain,
        GLogLevelFlags  log_level,
        const gchar    *format,
-       va_list        *args1,
-       va_list        *args2)
+       va_list         args1)
 {
+  va_list args2;
   gchar buffer[1025];
   register gint i;
   
@@ -269,9 +263,23 @@ g_logv (const gchar    *log_domain,
     return;
   
   /* we use a stack buffer of fixed size, because we might get called
-   * recursively, and we can also be out of memory.
+   * recursively.
    */
-  g_vsnprintf (buffer, 1025, format, args1, args2);
+  G_VA_COPY (args2, args1);
+  if (g_printf_string_upper_bound (format, args1) < 1024)
+    vsprintf (buffer, format, args2);
+  else
+    {
+      /* since we might be out of memory, we can't use g_vsnprintf(). */
+#ifdef  HAVE_VSNPRINTF
+      vsnprintf (buffer, 1024, format, args2);
+#else  /* !HAVE_VSNPRINTF */
+      /* we are out of luck here */
+      strncpy (buffer, format, 1024);
+#endif /* !HAVE_VSNPRINTF */
+      buffer[1024] = 0;
+    }
+  va_end (args2);
   
   for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
     {
@@ -312,13 +320,11 @@ g_log (const gchar    *log_domain,
        const gchar    *format,
        ...)
 {
-  va_list arg_list1, arg_list2;
+  va_list args;
   
-  va_start (arg_list1, format);
-  va_start (arg_list2, format);
-  g_logv (log_domain, log_level, format, &arg_list1, &arg_list2);
-  va_end (arg_list2);
-  va_end (arg_list1);
+  va_start (args, format);
+  g_logv (log_domain, log_level, format, args);
+  va_end (args);
 }
 
 void
@@ -523,30 +529,23 @@ void
 g_print (const gchar *format,
         ...)
 {
-  va_list args, args2;
-  char *buf;
+  va_list args;
+  gchar *string;
   
   g_return_if_fail (format != NULL);
   
   va_start (args, format);
-  va_start (args2, format);
-  buf = g_vsprintf (format, &args, &args2);
+  string = g_strdup_vprintf (format, args);
   va_end (args);
-  va_end (args2);
   
   if (glib_print_func)
-    {
-      gchar *string;
-      
-      string = g_strdup (buf);
-      glib_print_func (string);
-      g_free (string);
-    }
+    glib_print_func (string);
   else
     {
-      fputs (buf, stdout);
+      fputs (string, stdout);
       fflush (stdout);
     }
+  g_free (string);
 }
 
 GPrintFunc
@@ -564,30 +563,23 @@ void
 g_printerr (const gchar *format,
            ...)
 {
-  va_list args, args2;
-  char *buf;
+  va_list args;
+  gchar *string;
   
   g_return_if_fail (format != NULL);
   
   va_start (args, format);
-  va_start (args2, format);
-  buf = g_vsprintf (format, &args, &args2);
+  string = g_strdup_vprintf (format, args);
   va_end (args);
-  va_end (args2);
   
   if (glib_printerr_func)
-    {
-      gchar *string;
-      
-      string = g_strdup (buf);
-      glib_printerr_func (string);
-      g_free (string);
-    }
+    glib_printerr_func (string);
   else
     {
-      fputs (buf, stderr);
+      fputs (string, stderr);
       fflush (stderr);
     }
+  g_free (string);
 }
 
 /* compatibility code */
index aa02395..f25b11d 100644 (file)
@@ -102,7 +102,6 @@ static      GScannerConfig  g_scanner_config_template =
 
 
 /* --- prototypes --- */
-extern char* g_vsprintf (gchar *fmt, va_list *args, va_list *args2);
 static inline
 gint           g_scanner_char_2_num      (guchar        c,
                                           guchar        base);
@@ -271,16 +270,12 @@ g_scanner_error (GScanner *scanner,
   
   if (scanner->msg_handler)
     {
-      va_list args, args2;
+      va_list args;
       gchar *string;
       
       va_start (args, format);
-      va_start (args2, format);
-      string = g_vsprintf ((gchar*) format, &args, &args2);
+      string = g_strdup_vprintf (format, args);
       va_end (args);
-      va_end (args2);
-      
-      string = g_strdup (string);
       
       scanner->msg_handler (scanner, string, TRUE);
       
@@ -298,16 +293,12 @@ g_scanner_warn (GScanner       *scanner,
   
   if (scanner->msg_handler)
     {
-      va_list args, args2;
+      va_list args;
       gchar *string;
       
       va_start (args, format);
-      va_start (args2, format);
-      string = g_vsprintf ((gchar*) format, &args, &args2);
+      string = g_strdup_vprintf (format, args);
       va_end (args);
-      va_end (args2);
-      
-      string = g_strdup (string);
       
       scanner->msg_handler (scanner, string, FALSE);
       
index 187e5d3..46234dc 100644 (file)
@@ -59,6 +59,37 @@ g_strndup (const gchar *str, gulong n)
 }
 
 gchar*
+g_strdup_vprintf (const gchar *format,
+                 va_list      args1)
+{
+  gchar *buffer;
+  va_list args2;
+
+  G_VA_COPY (args2, args1);
+
+  buffer = g_new (gchar, g_printf_string_upper_bound (format, args1));
+
+  vsprintf (buffer, format, args2);
+  va_end (args2);
+
+  return buffer;
+}
+
+gchar*
+g_strdup_printf (const gchar *format,
+                ...)
+{
+  gchar *buffer;
+  va_list args;
+
+  va_start (args, format);
+  buffer = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  return buffer;
+}
+
+gchar*
 g_strconcat (const gchar *string1, ...)
 {
   guint          l;
@@ -681,6 +712,143 @@ g_strsignal (gint signum)
   return msg;
 }
 
+guint
+g_printf_string_upper_bound (const gchar* format,
+                            va_list      args)
+{
+  guint len = 1;
+  
+  while (*format)
+    {
+      gboolean long_int = FALSE;
+      gboolean extra_long = FALSE;
+      gchar c;
+      
+      c = *format++;
+      
+      if (c == '%')
+       {
+         gboolean done = FALSE;
+         
+         while (*format && !done)
+           {
+             switch (*format++)
+               {
+                 gchar *string_arg;
+                 
+               case '*':
+                 len += va_arg (args, int);
+                 break;
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                 /* add specified format length, since it might exceed the
+                  * size we assume it to have.
+                  */
+                 format -= 1;
+                 len += strtol (format, (char**) &format, 10);
+                 break;
+               case 'h':
+                 /* ignore short int flag, since all args have at least the
+                  * same size as an int
+                  */
+                 break;
+               case 'l':
+                 if (long_int)
+                   extra_long = TRUE; /* linux specific */
+                 else
+                   long_int = TRUE;
+                 break;
+               case 'q':
+               case 'L':
+                 long_int = TRUE;
+                 extra_long = TRUE;
+                 break;
+               case 's':
+                 string_arg = va_arg (args, char *);
+                 if (string_arg)
+                   len += strlen (string_arg);
+                 else
+                   {
+                     /* add enough padding to hold "(null)" identifier */
+                     len += 16;
+                   }
+                 done = TRUE;
+                 break;
+               case 'd':
+               case 'i':
+               case 'o':
+               case 'u':
+               case 'x':
+               case 'X':
+#ifdef HAVE_GINT64
+                 if (extra_long)
+                   (void) va_arg (args, gint64);
+                 else
+#endif /* HAVE_GINT64 */
+                   {
+                     if (long_int)
+                       (void) va_arg (args, long);
+                     else
+                       (void) va_arg (args, int);
+                   }
+                 len += extra_long ? 64 : 32;
+                 done = TRUE;
+                 break;
+               case 'D':
+               case 'O':
+               case 'U':
+                 (void) va_arg (args, long);
+                 len += 32;
+                 done = TRUE;
+                 break;
+               case 'e':
+               case 'E':
+               case 'f':
+               case 'g':
+#ifdef HAVE_LONG_DOUBLE
+                 if (extra_long)
+                   (void) va_arg (args, long double);
+                 else
+#endif /* HAVE_LONG_DOUBLE */
+                   (void) va_arg (args, double);
+                 len += extra_long ? 64 : 32;
+                 done = TRUE;
+                 break;
+               case 'c':
+                 (void) va_arg (args, int);
+                 len += 1;
+                 done = TRUE;
+                 break;
+               case 'p':
+               case 'n':
+                 (void) va_arg (args, void*);
+                 len += 32;
+                 done = TRUE;
+                 break;
+               case '%':
+                 len += 1;
+                 done = TRUE;
+                 break;
+               default:
+                 /* ignore unknow/invalid flags */
+                 break;
+               }
+           }
+       }
+      else
+       len += 1;
+    }
+  
+  return len;
+}
+
 void
 g_strdown (gchar  *string)
 {
index 3454e8f..39e43e2 100644 (file)
@@ -466,152 +466,16 @@ g_string_up (GString *fstring)
   return fstring;
 }
 
-static int
-get_length_upper_bound (const gchar* fmt, va_list *args)
-{
-  int len = 0;
-  int short_int;
-  int long_int;
-  int done;
-  char *tmp;
-
-  while (*fmt)
-    {
-      char c = *fmt++;
-
-      short_int = FALSE;
-      long_int = FALSE;
-
-      if (c == '%')
-       {
-         done = FALSE;
-         while (*fmt && !done)
-           {
-             switch (*fmt++)
-               {
-               case '*':
-                 len += va_arg(*args, int);
-                 break;
-               case '1':
-               case '2':
-               case '3':
-               case '4':
-               case '5':
-               case '6':
-               case '7':
-               case '8':
-               case '9':
-                 fmt -= 1;
-                 len += strtol (fmt, (char **)&fmt, 10);
-                 break;
-               case 'h':
-                 short_int = TRUE;
-                 break;
-               case 'l':
-                 long_int = TRUE;
-                 break;
-
-                 /* I ignore 'q' and 'L', they're not portable anyway. */
-
-               case 's':
-                 tmp = va_arg(*args, char *);
-                 if(tmp)
-                   len += strlen (tmp);
-                 else
-                   len += strlen ("(null)");
-                 done = TRUE;
-                 break;
-               case 'd':
-               case 'i':
-               case 'o':
-               case 'u':
-               case 'x':
-               case 'X':
-                 if (long_int)
-                   (void)va_arg (*args, long);
-                 else if (short_int)
-                   (void)va_arg (*args, int);
-                 else
-                   (void)va_arg (*args, int);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case 'D':
-               case 'O':
-               case 'U':
-                 (void)va_arg (*args, long);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case 'e':
-               case 'E':
-               case 'f':
-               case 'g':
-                 (void)va_arg (*args, double);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case 'c':
-                 (void)va_arg (*args, int);
-                 len += 1;
-                 done = TRUE;
-                 break;
-               case 'p':
-               case 'n':
-                 (void)va_arg (*args, void*);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case '%':
-                 len += 1;
-                 done = TRUE;
-                 break;
-               default:
-                 break;
-               }
-           }
-       }
-      else
-       len += 1;
-    }
-
-  return len;
-}
-
-extern gchar* g_vsprintf (const gchar *fmt, va_list *args, va_list *args2);
-gchar*
-g_vsprintf (const gchar *fmt,
-           va_list     *args,
-           va_list     *args2)
-{
-  static gchar *buf = NULL;
-  static guint  alloc = 0;
-  guint len;
-
-  len = get_length_upper_bound (fmt, args);
-
-  if (len >= alloc)
-    {
-      if (buf)
-       g_free (buf);
-
-      alloc = nearest_pow (MAX (len + 1, 1024 + 1));
-
-      buf = g_new (gchar, alloc);
-    }
-
-  vsprintf (buf, fmt, *args2);
-
-  return buf;
-}
-
 static void
-g_string_sprintfa_int (GString *string,
+g_string_sprintfa_int (GString     *string,
                       const gchar *fmt,
-                      va_list *args,
-                      va_list *args2)
+                      va_list      args)
 {
-  g_string_append (string, g_vsprintf (fmt, args, args2));
+  gchar *buffer;
+
+  buffer = g_strdup_vprintf (fmt, args);
+  g_string_append (string, buffer);
+  g_free (buffer);
 }
 
 void
@@ -619,17 +483,13 @@ g_string_sprintf (GString *string,
                  const gchar *fmt,
                  ...)
 {
-  va_list args, args2;
-
-  va_start(args, fmt);
-  va_start(args2, fmt);
+  va_list args;
 
   g_string_truncate (string, 0);
 
-  g_string_sprintfa_int (string, fmt, &args, &args2);
-
-  va_end(args);
-  va_end(args2);
+  va_start (args, fmt);
+  g_string_sprintfa_int (string, fmt, args);
+  va_end (args);
 }
 
 void
@@ -637,13 +497,9 @@ g_string_sprintfa (GString *string,
                   const gchar *fmt,
                   ...)
 {
-  va_list args, args2;
-
-  va_start(args, fmt);
-  va_start(args2, fmt);
-
-  g_string_sprintfa_int (string, fmt, &args, &args2);
+  va_list args;
 
-  va_end(args);
-  va_end(args2);
+  va_start (args, fmt);
+  g_string_sprintfa_int (string, fmt, args);
+  va_end (args);
 }
index c4f49b5..d58b447 100644 (file)
@@ -32,7 +32,6 @@ const guint glib_micro_version = GLIB_MICRO_VERSION;
 const guint glib_interface_age = GLIB_INTERFACE_AGE;
 const guint glib_binary_age = GLIB_BINARY_AGE;
 
-extern char* g_vsprintf (const gchar *fmt, va_list *args, va_list *args2);
 
 gint
 g_snprintf (gchar      *str,
@@ -51,17 +50,16 @@ g_snprintf (gchar   *str,
   return retval;
 #else  /* !HAVE_VSNPRINTF */
   gchar *printed;
-  va_list args, args2;
+  va_list args;
   
   va_start (args, fmt);
-  va_start (args2, fmt);
+  printed = g_strdup_vprintf (fmt, args);
+  va_end (args);
   
-  printed = g_vsprintf (fmt, &args, &args2);
   strncpy (str, printed, n);
   str[n-1] = '\0';
-  
-  va_end (args2);
-  va_end (args);
+
+  g_free (printed);
   
   return strlen (str);
 #endif /* !HAVE_VSNPRINTF */
@@ -71,21 +69,22 @@ gint
 g_vsnprintf (gchar      *str,
             gulong       n,
             gchar const *fmt,
-            va_list     *args1,
-            va_list     *args2)
+            va_list      args)
 {
 #ifdef HAVE_VSNPRINTF
   gint retval;
   
-  retval = vsnprintf (str, n, fmt, *args1);
+  retval = vsnprintf (str, n, fmt, args);
   
   return retval;
 #else  /* !HAVE_VSNPRINTF */
   gchar *printed;
   
-  printed = g_vsprintf (fmt, args1, args2);
+  printed = g_strdup_vprintf (fmt, args);
   strncpy (str, printed, n);
   str[n-1] = '\0';
+
+  g_free (printed);
   
   return strlen (str);
 #endif /* !HAVE_VSNPRINTF */
index 1c71232..09ab327 100644 (file)
@@ -37,6 +37,9 @@
 #undef NO_SYS_ERRLIST
 #undef NO_SYS_SIGLIST
 
+#undef G_VA_COPY
+#undef G_VA_COPY_AS_ARRAY
+
 #undef GLIB_MAJOR_VERSION
 #undef GLIB_MINOR_VERSION
 #undef GLIB_MICRO_VERSION
index f8271af..12a2c59 100644 (file)
@@ -43,12 +43,6 @@ struct _GLogHandler
 };
 
 
-/* --- prototypes --- */
-extern gchar* g_vsprintf (const gchar *fmt,
-                         va_list     *args,
-                         va_list     *args2);
-
-
 /* --- variables --- */
 const gchar         *g_log_domain_glib = "GLib";
 static GLogDomain    *g_log_domains = NULL;
@@ -258,9 +252,9 @@ void
 g_logv (const gchar    *log_domain,
        GLogLevelFlags  log_level,
        const gchar    *format,
-       va_list        *args1,
-       va_list        *args2)
+       va_list         args1)
 {
+  va_list args2;
   gchar buffer[1025];
   register gint i;
   
@@ -269,9 +263,23 @@ g_logv (const gchar    *log_domain,
     return;
   
   /* we use a stack buffer of fixed size, because we might get called
-   * recursively, and we can also be out of memory.
+   * recursively.
    */
-  g_vsnprintf (buffer, 1025, format, args1, args2);
+  G_VA_COPY (args2, args1);
+  if (g_printf_string_upper_bound (format, args1) < 1024)
+    vsprintf (buffer, format, args2);
+  else
+    {
+      /* since we might be out of memory, we can't use g_vsnprintf(). */
+#ifdef  HAVE_VSNPRINTF
+      vsnprintf (buffer, 1024, format, args2);
+#else  /* !HAVE_VSNPRINTF */
+      /* we are out of luck here */
+      strncpy (buffer, format, 1024);
+#endif /* !HAVE_VSNPRINTF */
+      buffer[1024] = 0;
+    }
+  va_end (args2);
   
   for (i = g_bit_nth_msf (log_level, -1); i >= 0; i = g_bit_nth_msf (log_level, i))
     {
@@ -312,13 +320,11 @@ g_log (const gchar    *log_domain,
        const gchar    *format,
        ...)
 {
-  va_list arg_list1, arg_list2;
+  va_list args;
   
-  va_start (arg_list1, format);
-  va_start (arg_list2, format);
-  g_logv (log_domain, log_level, format, &arg_list1, &arg_list2);
-  va_end (arg_list2);
-  va_end (arg_list1);
+  va_start (args, format);
+  g_logv (log_domain, log_level, format, args);
+  va_end (args);
 }
 
 void
@@ -523,30 +529,23 @@ void
 g_print (const gchar *format,
         ...)
 {
-  va_list args, args2;
-  char *buf;
+  va_list args;
+  gchar *string;
   
   g_return_if_fail (format != NULL);
   
   va_start (args, format);
-  va_start (args2, format);
-  buf = g_vsprintf (format, &args, &args2);
+  string = g_strdup_vprintf (format, args);
   va_end (args);
-  va_end (args2);
   
   if (glib_print_func)
-    {
-      gchar *string;
-      
-      string = g_strdup (buf);
-      glib_print_func (string);
-      g_free (string);
-    }
+    glib_print_func (string);
   else
     {
-      fputs (buf, stdout);
+      fputs (string, stdout);
       fflush (stdout);
     }
+  g_free (string);
 }
 
 GPrintFunc
@@ -564,30 +563,23 @@ void
 g_printerr (const gchar *format,
            ...)
 {
-  va_list args, args2;
-  char *buf;
+  va_list args;
+  gchar *string;
   
   g_return_if_fail (format != NULL);
   
   va_start (args, format);
-  va_start (args2, format);
-  buf = g_vsprintf (format, &args, &args2);
+  string = g_strdup_vprintf (format, args);
   va_end (args);
-  va_end (args2);
   
   if (glib_printerr_func)
-    {
-      gchar *string;
-      
-      string = g_strdup (buf);
-      glib_printerr_func (string);
-      g_free (string);
-    }
+    glib_printerr_func (string);
   else
     {
-      fputs (buf, stderr);
+      fputs (string, stderr);
       fflush (stderr);
     }
+  g_free (string);
 }
 
 /* compatibility code */
index 06d9cf5..71e1ed9 100644 (file)
@@ -169,7 +169,8 @@ main (int   arg,
 #if 0
   g_log_set_fatal_mask ("GModule", G_LOG_FATAL_MASK|G_LOG_LEVEL_WARNING);
   g_module_symbol (0, 0, 0);
-  g_warning("jahoooo");
+  g_warning("jahooo");
+  g_on_error_query (".libs/testgmodule");
 #endif
   
   return 0;
index aa02395..f25b11d 100644 (file)
@@ -102,7 +102,6 @@ static      GScannerConfig  g_scanner_config_template =
 
 
 /* --- prototypes --- */
-extern char* g_vsprintf (gchar *fmt, va_list *args, va_list *args2);
 static inline
 gint           g_scanner_char_2_num      (guchar        c,
                                           guchar        base);
@@ -271,16 +270,12 @@ g_scanner_error (GScanner *scanner,
   
   if (scanner->msg_handler)
     {
-      va_list args, args2;
+      va_list args;
       gchar *string;
       
       va_start (args, format);
-      va_start (args2, format);
-      string = g_vsprintf ((gchar*) format, &args, &args2);
+      string = g_strdup_vprintf (format, args);
       va_end (args);
-      va_end (args2);
-      
-      string = g_strdup (string);
       
       scanner->msg_handler (scanner, string, TRUE);
       
@@ -298,16 +293,12 @@ g_scanner_warn (GScanner       *scanner,
   
   if (scanner->msg_handler)
     {
-      va_list args, args2;
+      va_list args;
       gchar *string;
       
       va_start (args, format);
-      va_start (args2, format);
-      string = g_vsprintf ((gchar*) format, &args, &args2);
+      string = g_strdup_vprintf (format, args);
       va_end (args);
-      va_end (args2);
-      
-      string = g_strdup (string);
       
       scanner->msg_handler (scanner, string, FALSE);
       
index 187e5d3..46234dc 100644 (file)
@@ -59,6 +59,37 @@ g_strndup (const gchar *str, gulong n)
 }
 
 gchar*
+g_strdup_vprintf (const gchar *format,
+                 va_list      args1)
+{
+  gchar *buffer;
+  va_list args2;
+
+  G_VA_COPY (args2, args1);
+
+  buffer = g_new (gchar, g_printf_string_upper_bound (format, args1));
+
+  vsprintf (buffer, format, args2);
+  va_end (args2);
+
+  return buffer;
+}
+
+gchar*
+g_strdup_printf (const gchar *format,
+                ...)
+{
+  gchar *buffer;
+  va_list args;
+
+  va_start (args, format);
+  buffer = g_strdup_vprintf (format, args);
+  va_end (args);
+
+  return buffer;
+}
+
+gchar*
 g_strconcat (const gchar *string1, ...)
 {
   guint          l;
@@ -681,6 +712,143 @@ g_strsignal (gint signum)
   return msg;
 }
 
+guint
+g_printf_string_upper_bound (const gchar* format,
+                            va_list      args)
+{
+  guint len = 1;
+  
+  while (*format)
+    {
+      gboolean long_int = FALSE;
+      gboolean extra_long = FALSE;
+      gchar c;
+      
+      c = *format++;
+      
+      if (c == '%')
+       {
+         gboolean done = FALSE;
+         
+         while (*format && !done)
+           {
+             switch (*format++)
+               {
+                 gchar *string_arg;
+                 
+               case '*':
+                 len += va_arg (args, int);
+                 break;
+               case '1':
+               case '2':
+               case '3':
+               case '4':
+               case '5':
+               case '6':
+               case '7':
+               case '8':
+               case '9':
+                 /* add specified format length, since it might exceed the
+                  * size we assume it to have.
+                  */
+                 format -= 1;
+                 len += strtol (format, (char**) &format, 10);
+                 break;
+               case 'h':
+                 /* ignore short int flag, since all args have at least the
+                  * same size as an int
+                  */
+                 break;
+               case 'l':
+                 if (long_int)
+                   extra_long = TRUE; /* linux specific */
+                 else
+                   long_int = TRUE;
+                 break;
+               case 'q':
+               case 'L':
+                 long_int = TRUE;
+                 extra_long = TRUE;
+                 break;
+               case 's':
+                 string_arg = va_arg (args, char *);
+                 if (string_arg)
+                   len += strlen (string_arg);
+                 else
+                   {
+                     /* add enough padding to hold "(null)" identifier */
+                     len += 16;
+                   }
+                 done = TRUE;
+                 break;
+               case 'd':
+               case 'i':
+               case 'o':
+               case 'u':
+               case 'x':
+               case 'X':
+#ifdef HAVE_GINT64
+                 if (extra_long)
+                   (void) va_arg (args, gint64);
+                 else
+#endif /* HAVE_GINT64 */
+                   {
+                     if (long_int)
+                       (void) va_arg (args, long);
+                     else
+                       (void) va_arg (args, int);
+                   }
+                 len += extra_long ? 64 : 32;
+                 done = TRUE;
+                 break;
+               case 'D':
+               case 'O':
+               case 'U':
+                 (void) va_arg (args, long);
+                 len += 32;
+                 done = TRUE;
+                 break;
+               case 'e':
+               case 'E':
+               case 'f':
+               case 'g':
+#ifdef HAVE_LONG_DOUBLE
+                 if (extra_long)
+                   (void) va_arg (args, long double);
+                 else
+#endif /* HAVE_LONG_DOUBLE */
+                   (void) va_arg (args, double);
+                 len += extra_long ? 64 : 32;
+                 done = TRUE;
+                 break;
+               case 'c':
+                 (void) va_arg (args, int);
+                 len += 1;
+                 done = TRUE;
+                 break;
+               case 'p':
+               case 'n':
+                 (void) va_arg (args, void*);
+                 len += 32;
+                 done = TRUE;
+                 break;
+               case '%':
+                 len += 1;
+                 done = TRUE;
+                 break;
+               default:
+                 /* ignore unknow/invalid flags */
+                 break;
+               }
+           }
+       }
+      else
+       len += 1;
+    }
+  
+  return len;
+}
+
 void
 g_strdown (gchar  *string)
 {
index 3454e8f..39e43e2 100644 (file)
--- a/gstring.c
+++ b/gstring.c
@@ -466,152 +466,16 @@ g_string_up (GString *fstring)
   return fstring;
 }
 
-static int
-get_length_upper_bound (const gchar* fmt, va_list *args)
-{
-  int len = 0;
-  int short_int;
-  int long_int;
-  int done;
-  char *tmp;
-
-  while (*fmt)
-    {
-      char c = *fmt++;
-
-      short_int = FALSE;
-      long_int = FALSE;
-
-      if (c == '%')
-       {
-         done = FALSE;
-         while (*fmt && !done)
-           {
-             switch (*fmt++)
-               {
-               case '*':
-                 len += va_arg(*args, int);
-                 break;
-               case '1':
-               case '2':
-               case '3':
-               case '4':
-               case '5':
-               case '6':
-               case '7':
-               case '8':
-               case '9':
-                 fmt -= 1;
-                 len += strtol (fmt, (char **)&fmt, 10);
-                 break;
-               case 'h':
-                 short_int = TRUE;
-                 break;
-               case 'l':
-                 long_int = TRUE;
-                 break;
-
-                 /* I ignore 'q' and 'L', they're not portable anyway. */
-
-               case 's':
-                 tmp = va_arg(*args, char *);
-                 if(tmp)
-                   len += strlen (tmp);
-                 else
-                   len += strlen ("(null)");
-                 done = TRUE;
-                 break;
-               case 'd':
-               case 'i':
-               case 'o':
-               case 'u':
-               case 'x':
-               case 'X':
-                 if (long_int)
-                   (void)va_arg (*args, long);
-                 else if (short_int)
-                   (void)va_arg (*args, int);
-                 else
-                   (void)va_arg (*args, int);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case 'D':
-               case 'O':
-               case 'U':
-                 (void)va_arg (*args, long);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case 'e':
-               case 'E':
-               case 'f':
-               case 'g':
-                 (void)va_arg (*args, double);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case 'c':
-                 (void)va_arg (*args, int);
-                 len += 1;
-                 done = TRUE;
-                 break;
-               case 'p':
-               case 'n':
-                 (void)va_arg (*args, void*);
-                 len += 32;
-                 done = TRUE;
-                 break;
-               case '%':
-                 len += 1;
-                 done = TRUE;
-                 break;
-               default:
-                 break;
-               }
-           }
-       }
-      else
-       len += 1;
-    }
-
-  return len;
-}
-
-extern gchar* g_vsprintf (const gchar *fmt, va_list *args, va_list *args2);
-gchar*
-g_vsprintf (const gchar *fmt,
-           va_list     *args,
-           va_list     *args2)
-{
-  static gchar *buf = NULL;
-  static guint  alloc = 0;
-  guint len;
-
-  len = get_length_upper_bound (fmt, args);
-
-  if (len >= alloc)
-    {
-      if (buf)
-       g_free (buf);
-
-      alloc = nearest_pow (MAX (len + 1, 1024 + 1));
-
-      buf = g_new (gchar, alloc);
-    }
-
-  vsprintf (buf, fmt, *args2);
-
-  return buf;
-}
-
 static void
-g_string_sprintfa_int (GString *string,
+g_string_sprintfa_int (GString     *string,
                       const gchar *fmt,
-                      va_list *args,
-                      va_list *args2)
+                      va_list      args)
 {
-  g_string_append (string, g_vsprintf (fmt, args, args2));
+  gchar *buffer;
+
+  buffer = g_strdup_vprintf (fmt, args);
+  g_string_append (string, buffer);
+  g_free (buffer);
 }
 
 void
@@ -619,17 +483,13 @@ g_string_sprintf (GString *string,
                  const gchar *fmt,
                  ...)
 {
-  va_list args, args2;
-
-  va_start(args, fmt);
-  va_start(args2, fmt);
+  va_list args;
 
   g_string_truncate (string, 0);
 
-  g_string_sprintfa_int (string, fmt, &args, &args2);
-
-  va_end(args);
-  va_end(args2);
+  va_start (args, fmt);
+  g_string_sprintfa_int (string, fmt, args);
+  va_end (args);
 }
 
 void
@@ -637,13 +497,9 @@ g_string_sprintfa (GString *string,
                   const gchar *fmt,
                   ...)
 {
-  va_list args, args2;
-
-  va_start(args, fmt);
-  va_start(args2, fmt);
-
-  g_string_sprintfa_int (string, fmt, &args, &args2);
+  va_list args;
 
-  va_end(args);
-  va_end(args2);
+  va_start (args, fmt);
+  g_string_sprintfa_int (string, fmt, args);
+  va_end (args);
 }
index c4f49b5..d58b447 100644 (file)
--- a/gutils.c
+++ b/gutils.c
@@ -32,7 +32,6 @@ const guint glib_micro_version = GLIB_MICRO_VERSION;
 const guint glib_interface_age = GLIB_INTERFACE_AGE;
 const guint glib_binary_age = GLIB_BINARY_AGE;
 
-extern char* g_vsprintf (const gchar *fmt, va_list *args, va_list *args2);
 
 gint
 g_snprintf (gchar      *str,
@@ -51,17 +50,16 @@ g_snprintf (gchar   *str,
   return retval;
 #else  /* !HAVE_VSNPRINTF */
   gchar *printed;
-  va_list args, args2;
+  va_list args;
   
   va_start (args, fmt);
-  va_start (args2, fmt);
+  printed = g_strdup_vprintf (fmt, args);
+  va_end (args);
   
-  printed = g_vsprintf (fmt, &args, &args2);
   strncpy (str, printed, n);
   str[n-1] = '\0';
-  
-  va_end (args2);
-  va_end (args);
+
+  g_free (printed);
   
   return strlen (str);
 #endif /* !HAVE_VSNPRINTF */
@@ -71,21 +69,22 @@ gint
 g_vsnprintf (gchar      *str,
             gulong       n,
             gchar const *fmt,
-            va_list     *args1,
-            va_list     *args2)
+            va_list      args)
 {
 #ifdef HAVE_VSNPRINTF
   gint retval;
   
-  retval = vsnprintf (str, n, fmt, *args1);
+  retval = vsnprintf (str, n, fmt, args);
   
   return retval;
 #else  /* !HAVE_VSNPRINTF */
   gchar *printed;
   
-  printed = g_vsprintf (fmt, args1, args2);
+  printed = g_strdup_vprintf (fmt, args);
   strncpy (str, printed, n);
   str[n-1] = '\0';
+
+  g_free (printed);
   
   return strlen (str);
 #endif /* !HAVE_VSNPRINTF */