• C

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!! )
RUNAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.