/*
Copyright (C) 2005-2009, Parrot Foundation.
$Id: test_c.in 46584 2010-05-13 11:33:53Z rblasch $

*/

#include <stdio.h>
#include <stdarg.h>

#if defined VA_TYPE_REGISTER
#  define PARROT_VA_TO_VAPTR(x) (x)
#endif
#if defined VA_TYPE_STACK
#  define PARROT_VA_TO_VAPTR(x) (&(x))
#endif

typedef struct a_t {
    void *args;
} arg;

static void
test2(arg *a) {

    va_list *ap = (va_list*)a->args;
    int i;
    double d;
    char *s;

    i = va_arg(*ap, int);
    d = va_arg(*ap, double);
    s = va_arg(*ap, char *);
    if (i == 42 && d == 2.0)
        printf("%s\n", s);
    else
        printf("nok\n");
}

static void
test1(va_list ap)
{
    arg a;
    a.args = PARROT_VA_TO_VAPTR(ap);
    test2(&a);
}

/*
 * Visual C++ dies with an Internal Compiler Error when compiling the
 * following function using -O2.  Don't know why, but maybe because of this:
 * https://connect.microsoft.com/VisualStudio/feedback/details/457892/internal-compiler-error
 * Disable optimizations for this function using a pragma.
 */
#if defined _MSC_VER
#  pragma optimize("t", off)
#endif
static void
test0(int n, ...)
{
    va_list ap;
    va_start(ap, n);
    test1(ap);
    va_end(ap);
}
#if defined _MSC_VER
#  pragma optimize("", on)
#endif

int
main(int argc, char *argv[])
{
    test0(3, 42, 2.0, "ok");
    return 0;
}

/*
 * Local variables:
 *   c-file-style: "parrot"
 * End:
 * vim: expandtab shiftwidth=4:
 */
