• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 417
  • Last Modified:

variable arguments

I would like to know if it is possible to copy the va_list stack. I know for solaris there is a va_copy extension of the stdarg.h, but I am looking for a solution that is available for other platforms.

The va_list stack needs to be copied because the vprintf statement will be processing at a delay.  Therefore I need to temporary copied the string format as well as the va_list stack within a separate structure to be used later.  If coping is not done, then the va_list stack would be reused by the system when another va_start() is called. ( and this is happening!! )
0
RUN
Asked:
RUN
1 Solution
 
ozoCommented:
You should parse the format string so you can va_arg through the list, copying them one at a time.
0
 
RUNAuthor Commented:
Parsing the format string is definitely an option. However, the number of arguments and the type of each argument is unpredictable.  Therefore there could potentially be an substantial overhead involved with this operation.  
Currently I can think of only 2 temporary solutions - either copying the va_list stack or simply resolving the string using vsprintf and passing the char* for future reference.

Any idea??
0
 
Anju111599Commented:
I've dealt with the same problem for software which had to be ported to HP-UX, AIX, Solaris, Sun-OS, SCO, UnixWare, IRIX, Linux, and DOS/Windows.  The only thing I found that worked reliably across platforms without a lot of preprocessor conditionals is your own suggestion #2:  use vsprintf and save the resulting string for later use.  

It's nasty if you later have to parse the string back into variables, but parsing the format string and storing each variable up front isn't any easier.  It's a choice between six of one or a half-dozen of the other.  If you do have to parse the string later, do yourself a favor and save both the result string and the format string.
0
 
mwimerCommented:
Glib does this test in its configure.in which is
used to create the ./configure script.

Here is the paste of the configure.in macros
used to genrerate all the tests:

dnl **********************
dnl *** va_copy checks ***
dnl **********************
dnl we currently check for all three va_copy possibilities, so we get
dnl all results in config.log for bug reports.
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)

and in the glib.h there is the addintional test of:
/* 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 */

BTW, this is LGPLed source code so you can link it
directly into your code if its in its own file.

By and large that is exactly how you do it so that
you have a protable va copy function for your code.

So yes, variadic aregs arn't any fun to make portable with is why you should be using something
like glib.
0

Featured Post

Will You Be GDPR Compliant by 5/28/2018?

GDPR? That's a regulation for the European Union. But, if you collect data from customers or employees within the EU, then you need to know about GDPR and make sure your organization is compliant by May 2018. Check out our preparation checklist to make sure you're on track today!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now