diff options
author | Tim Janik <timj@gtk.org> | 1998-08-24 05:26:53 +0000 |
---|---|---|
committer | Tim Janik <timj@src.gnome.org> | 1998-08-24 05:26:53 +0000 |
commit | b420fa84187d9cb2f89ab8b3dd2040eab24742af (patch) | |
tree | ea25b72d953340a62d7c777b4db8a088777ca90a | |
parent | 0b870ec357a266b5e7faa9a96310dd89503660f9 (diff) |
removed this function which was not publically exported in glib.h. to
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.
-rw-r--r-- | ChangeLog | 49 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 49 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 49 | ||||
-rw-r--r-- | ChangeLog.pre-2-12 | 49 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 49 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 49 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 49 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 49 | ||||
-rw-r--r-- | NEWS | 9 | ||||
-rw-r--r-- | acconfig.h | 3 | ||||
-rw-r--r-- | configure.in | 81 | ||||
-rw-r--r-- | gbacktrace.c | 174 | ||||
-rw-r--r-- | gerror.c | 174 | ||||
-rw-r--r-- | glib.h | 69 | ||||
-rw-r--r-- | glib/gbacktrace.c | 174 | ||||
-rw-r--r-- | glib/gerror.c | 174 | ||||
-rw-r--r-- | glib/glib.h | 69 | ||||
-rw-r--r-- | glib/gmessages.c | 76 | ||||
-rw-r--r-- | glib/gscanner.c | 17 | ||||
-rw-r--r-- | glib/gstrfuncs.c | 168 | ||||
-rw-r--r-- | glib/gstring.c | 174 | ||||
-rw-r--r-- | glib/gutils.c | 21 | ||||
-rw-r--r-- | glibconfig.h.in | 3 | ||||
-rw-r--r-- | gmessages.c | 76 | ||||
-rw-r--r-- | gmodule/testgmodule.c | 3 | ||||
-rw-r--r-- | gscanner.c | 17 | ||||
-rw-r--r-- | gstrfuncs.c | 168 | ||||
-rw-r--r-- | gstring.c | 174 | ||||
-rw-r--r-- | gutils.c | 21 |
29 files changed, 1377 insertions, 860 deletions
@@ -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/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 256ebca3b..4d42396ea 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -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/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 256ebca3b..4d42396ea 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -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/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 256ebca3b..4d42396ea 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -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/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 256ebca3b..4d42396ea 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -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/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 256ebca3b..4d42396ea 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -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/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 256ebca3b..4d42396ea 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -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/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 256ebca3b..4d42396ea 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -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 @@ -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: diff --git a/acconfig.h b/acconfig.h index e5fd43b7f..9c4e45f24 100644 --- a/acconfig.h +++ b/acconfig.h @@ -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 diff --git a/configure.in b/configure.in index 6b1d68490..533bda84d 100644 --- a/configure.in +++ b/configure.in @@ -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 *********************** diff --git a/gbacktrace.c b/gbacktrace.c index cff505b65..b2834b289 100644 --- a/gbacktrace.c +++ b/gbacktrace.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 @@ -54,104 +51,105 @@ #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; -} @@ -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 @@ -54,104 +51,105 @@ #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; -} @@ -125,6 +125,20 @@ #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() */ diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c index cff505b65..b2834b289 100644 --- a/glib/gbacktrace.c +++ b/glib/gbacktrace.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 @@ -54,104 +51,105 @@ #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/gerror.c b/glib/gerror.c index cff505b65..b2834b289 100644 --- a/glib/gerror.c +++ b/glib/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 @@ -54,104 +51,105 @@ #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/glib.h b/glib/glib.h index 8dacdf134..62ade5dcb 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -125,6 +125,20 @@ #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() */ diff --git a/glib/gmessages.c b/glib/gmessages.c index f8271afd3..12a2c59b1 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -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 */ diff --git a/glib/gscanner.c b/glib/gscanner.c index aa0239554..f25b11d0c 100644 --- a/glib/gscanner.c +++ b/glib/gscanner.c @@ -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); diff --git a/glib/gstrfuncs.c b/glib/gstrfuncs.c index 187e5d32f..46234dcc2 100644 --- a/glib/gstrfuncs.c +++ b/glib/gstrfuncs.c @@ -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) { diff --git a/glib/gstring.c b/glib/gstring.c index 3454e8fdb..39e43e21c 100644 --- a/glib/gstring.c +++ b/glib/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); } diff --git a/glib/gutils.c b/glib/gutils.c index c4f49b5e1..d58b44797 100644 --- a/glib/gutils.c +++ b/glib/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 */ diff --git a/glibconfig.h.in b/glibconfig.h.in index 1c7123222..09ab3271e 100644 --- a/glibconfig.h.in +++ b/glibconfig.h.in @@ -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 diff --git a/gmessages.c b/gmessages.c index f8271afd3..12a2c59b1 100644 --- a/gmessages.c +++ b/gmessages.c @@ -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 */ diff --git a/gmodule/testgmodule.c b/gmodule/testgmodule.c index 06d9cf509..71e1ed9f8 100644 --- a/gmodule/testgmodule.c +++ b/gmodule/testgmodule.c @@ -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; diff --git a/gscanner.c b/gscanner.c index aa0239554..f25b11d0c 100644 --- a/gscanner.c +++ b/gscanner.c @@ -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); diff --git a/gstrfuncs.c b/gstrfuncs.c index 187e5d32f..46234dcc2 100644 --- a/gstrfuncs.c +++ b/gstrfuncs.c @@ -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) { @@ -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); } @@ -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 */ |