Re: Support of variable arguments: Re: [ROOT] Form on Alpha OSF

From: Masaharu Goto (MXJ02154@nifty.ne.jp)
Date: Sat Aug 24 2002 - 03:04:06 MEST


Hello Christian,

Thank you for sending me the header file. It turns out the same file
exists in my Linux machine too.  I'll try to implement va_arg support
for PowerPC in next release(5.15.54). However, I do not have
PowerPC , so please debug by yourself.  We need several iteration
debugging this. I'd appreciate your cooperation.

Masaharu Goto

----- Original Message -----
From: "cstrato" <cstrato@aon.at>
To: "Masaharu Goto" <MXJ02154@nifty.ne.jp>
Cc: "Jiri Masik" <masik@fzu.cz>; <roottalk@pcroot.cern.ch>
Sent: Friday, August 23, 2002 4:03 AM
Subject: Re: Support of variable arguments: Re: [ROOT] Form on Alpha OSF


> Dear Masaharu
>
> Thank you for your extensive answer.
> Enclosed I have attached the stdarg.h and va-ppc.h files
> for the Mac/IBM/PowerPC platform. It would be great, if
> CINT could support this platform.
>
> Thank you
> Christian
>
>
> Masaharu Goto wrote:
>
> > Hello Jiri and Christian,
> >
> > Support for variable arguments (between compiled code and interpreter)
> > depends on stack data alignment of specific CPU architecture. So far,
> > I investigated  Intel, HP-PA and Sparc.  It turned out passing
class/struct
> > object as value is a fundamental problem in HP-PA and Sparc. For those
> > CPUs, only fundamental type arguments can be passed.  Intel architecture
> > is fine for passing class/struct object as value.  I am not sure for
> > Mac/PowerPC platform.
> >
> > This is implemented in following locations in Cint source code.
> >
> > G__ci.h  line 1608-1633
> >   Define macro for turning on/off the vaarg feature depending on
> >   computer architecture.
> >
> > src/size.c line 1258-1266
> >   Implements vaarg byte alignment. You can add implementation
> >   for other platforms if you'd like. Normally, vaarg alignment rule is
> >   described in include/stdarg.h and in va_arg() macro. This macro
> >   is a really complicated beast, however, if you try hard, it tells you
> >   how variable arguments are implemented in your compiler.
> >
> > Probably, I can tell you a little more about Mac/PowerPC if you
> > send me include/stdarg.h.
> >
> > Thank you
> > Masaharu Goto
> >
> > ----- Original Message -----
> > From: "cstrato" <cstrato@aon.at>
> > To: "Jiri Masik" <masik@fzu.cz>
> > Cc: <roottalk@pcroot.cern.ch>
> > Sent: Thursday, August 22, 2002 4:00 AM
> > Subject: Support of variable arguments: Re: [ROOT] Form on Alpha OSF
> >
> >
> >
> >>Dear Rooters
> >>
> >>I am, too, missing support for variable arguments on the Mac,
> >>i.e. the PowerPC platform.
> >>Does anyone know if support is planned in the future?
> >>
> >>Best regards
> >>Christian
> >>_._._._._._._._._._._._._._._._
> >>C.h.i.s.t.i.a.n S.t.r.a.t.o.w.a
> >>V.i.e.n.n.a       A.u.s.t.r.i.a
> >>_._._._._._._._._._._._._._._._
> >>
> >>
> >>Jiri Masik wrote:
> >>
> >>
> >>>Thomas Bretz <tbretz@astro.uni-wuerzburg.de> writes:
> >>>
> >>>
> >>>
> >>>>Hi,
> >>>>
> >>>>what's the reason, that Form is not supported on Alphas in the
> >>>>
> > interpreter?
> >
> >>>>Thomas.
> >>>>
> >>>>
> >>>Hi Thomas,
> >>>
> >>>Form relies on the implementation of variable arguments functions in
> >>>Cint which is currently done only for Linux on ia32 and Win32 I think.
> >>>You can do grep -r G__VAARG * in Root tree to get an idea what is
> >>>needed.
> >>>
> >>>cheers
> >>>        Jiri
> >>>
> >>>
> >>>
> >>>
> >>
> >
> >
> >
>
>


----------------------------------------------------------------------------
----


> /* stdarg.h for GNU.
>    Note that the type used in va_arg is supposed to match the
>    actual type **after default promotions**.
>    Thus, va_arg (..., short) is not valid.  */
>
> #ifndef _STDARG_H
> #ifndef _ANSI_STDARG_H_
> #ifndef __need___va_list
> #define _STDARG_H
> #define _ANSI_STDARG_H_
> #endif /* not __need___va_list */
> #undef __need___va_list
>
> #ifdef __clipper__
> #include "va-clipper.h"
> #else
> #ifdef __m88k__
> #include "va-m88k.h"
> #else
> #ifdef __i860__
> #include "va-i860.h"
> #else
> #ifdef __hppa__
> #include "va-pa.h"
> #else
> #ifdef __mips__
> #include "va-mips.h"
> #else
> #ifdef __sparc__
> #include "va-sparc.h"
> #else
> #ifdef __i960__
> #include "va-i960.h"
> #else
> #ifdef __alpha__
> #include "va-alpha.h"
> #else
> #if defined (__H8300__) || defined (__H8300H__) || defined (__H8300S__)
> #include "va-h8300.h"
> #else
> #if defined (_AIX) || (defined (__ppc__) && defined (__APPLE__)) ||
(defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32)))
> #include "va-ppc.h"
> #else
> #ifdef __arc__
> #include "va-arc.h"
> #else
> #ifdef __M32R__
> #include "va-m32r.h"
> #else
> #ifdef __sh__
> #include "va-sh.h"
> #else
> #ifdef __mn10300__
> #include "va-mn10300.h"
> #else
> #ifdef __mn10200__
> #include "va-mn10200.h"
> #else
> #ifdef __v850__
> #include "va-v850.h"
> #else
> #if defined (_TMS320C4x) || defined (_TMS320C3x)
> #include <va-c4x.h>
> #else
>
> /* Define __gnuc_va_list.  */
>
> #ifndef __GNUC_VA_LIST
> #define __GNUC_VA_LIST
> #if defined(__svr4__) || defined(_AIX) || defined(_M_UNIX) ||
defined(__NetBSD__)
> typedef char *__gnuc_va_list;
> #else
> typedef void *__gnuc_va_list;
> #endif
> #endif
>
> /* Define the standard macros for the user,
>    if this invocation was from the user program.  */
> #ifdef _STDARG_H
>
> /* Amount of space required in an argument list for an arg of type TYPE.
>    TYPE may alternatively be an expression whose type is used.  */
>
> #if defined(sysV68)
> #define __va_rounded_size(TYPE)  \
>   (((sizeof (TYPE) + sizeof (short) - 1) / sizeof (short)) * sizeof
(short))
> #elif defined(_AIX)
> #define __va_rounded_size(TYPE)  \
>   (((sizeof (TYPE) + sizeof (long) - 1) / sizeof (long)) * sizeof (long))
> #else
> #define __va_rounded_size(TYPE)  \
>   (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
> #endif
>
> #define va_start(AP, LASTARG) \
>  (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG)))
>
> #undef va_end
> void va_end (__gnuc_va_list); /* Defined in libgcc.a */
> #define va_end(AP) ((void)0)
>
> /* We cast to void * and then to TYPE * because this avoids
>    a warning about increasing the alignment requirement.  */
>
> #if (defined (__arm__) && ! defined (__ARMEB__)) || defined (__i386__) ||
defined (__i860__) || defined (__ns32000__) || defined (__vax__)
> /* This is for little-endian machines; small args are padded upward.  */
> #define va_arg(AP, TYPE) \
>  (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
>   *((TYPE *) (void *) ((char *) (AP) - __va_rounded_size (TYPE))))
> #else /* big-endian */
> /* This is for big-endian machines; small args are padded downward.  */
> #define va_arg(AP, TYPE) \
>  (AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
>   *((TYPE *) (void *) ((char *) (AP) \
>        - ((sizeof (TYPE) < __va_rounded_size (char) \
>    ? sizeof (TYPE) : __va_rounded_size (TYPE))))))
> #endif /* big-endian */
>
> /* Copy __gnuc_va_list into another variable of this type.  */
> #define __va_copy(dest, src) (dest) = (src)
>
> #endif /* _STDARG_H */
>
> #endif /* not TMS320C3x or TMS320C4x */
> #endif /* not v850 */
> #endif /* not mn10200 */
> #endif /* not mn10300 */
> #endif /* not sh */
> #endif /* not m32r */
> #endif /* not arc */
> #endif /* not powerpc with V.4 calling sequence */
> #endif /* not h8300 */
> #endif /* not alpha */
> #endif /* not i960 */
> #endif /* not sparc */
> #endif /* not mips */
> #endif /* not hppa */
> #endif /* not i860 */
> #endif /* not m88k */
> #endif /* not clipper */
>
> #ifdef _STDARG_H
> /* Define va_list, if desired, from __gnuc_va_list. */
> /* We deliberately do not define va_list when called from
>    stdio.h, because ANSI C says that stdio.h is not supposed to define
>    va_list.  stdio.h needs to have access to that data type,
>    but must not use that name.  It should use the name __gnuc_va_list,
>    which is safe because it is reserved for the implementation.  */
>
> #ifdef _HIDDEN_VA_LIST  /* On OSF1, this means varargs.h is "half-loaded".
*/
> #undef _VA_LIST
> #endif
>
> #ifdef _BSD_VA_LIST
> #undef _BSD_VA_LIST
> #endif
>
> #if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST))
> /* SVR4.2 uses _VA_LIST for an internal alias for va_list,
>    so we must avoid testing it and setting it here.
>    SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
>    have no conflict with that.  */
> #ifndef _VA_LIST_
> #define _VA_LIST_
> #ifdef __i860__
> #ifndef _VA_LIST
> #define _VA_LIST va_list
> #endif
> #endif /* __i860__ */
> typedef __gnuc_va_list va_list;
> #ifdef _SCO_DS
> #define __VA_LIST
> #endif
> #endif /* _VA_LIST_ */
> #else /* not __svr4__ || _SCO_DS */
>
> /* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
>    But on BSD NET2 we must not test or define or undef it.
>    (Note that the comments in NET 2's ansi.h
>    are incorrect for _VA_LIST_--see stdio.h!)  */
> #if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined
(____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined
(__FreeBSD__) || defined(WINNT)
> /* The macro _VA_LIST_DEFINED is used in Windows NT 3.5  */
> #ifndef _VA_LIST_DEFINED
> /* The macro _VA_LIST is used in SCO Unix 3.2.  */
> #ifndef _VA_LIST
> /* The macro _VA_LIST_T_H is used in the Bull dpx2  */
> #ifndef _VA_LIST_T_H
> typedef __gnuc_va_list va_list;
> #endif /* not _VA_LIST_T_H */
> #endif /* not _VA_LIST */
> #endif /* not _VA_LIST_DEFINED */
> #if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined
(__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
> #define _VA_LIST_
> #endif
> #ifndef _VA_LIST
> #define _VA_LIST
> #endif
> #ifndef _VA_LIST_DEFINED
> #define _VA_LIST_DEFINED
> #endif
> #ifndef _VA_LIST_T_H
> #define _VA_LIST_T_H
> #endif
>
> #endif /* not _VA_LIST_, except on certain systems */
>
> #endif /* not __svr4__ */
>
> #endif /* _STDARG_H */
>
> #endif /* not _ANSI_STDARG_H_ */
> #endif /* not _STDARG_H */
>


----------------------------------------------------------------------------
----


> /* GNU C varargs support for the PowerPC with either the Apple/AIX, V.4 or
Windows NT calling sequences */
>
> #if defined(_AIX) || defined (__APPLE__)
> /* AIX support */
> /* Define __gnuc_va_list.  */
>
> #ifndef __GNUC_VA_LIST
> #define __GNUC_VA_LIST
> typedef char *__gnuc_va_list;
> #endif
>
> /* If this is for internal libc use, don't define anything but
>    __gnuc_va_list.  */
> #if defined (_STDARG_H) || defined (_VARARGS_H)
>
> #ifdef _STDARG_H /* stdarg.h support */
>
> /* Calling __builtin_next_arg gives the proper error message if LASTARG is
>    not indeed the last argument.  */
> #define va_start(AP, LASTARG) \
>  (AP = ((__gnuc_va_list) __builtin_next_arg (LASTARG)))
>
> #else /* varargs.h support */
>
> /* In GCC version 2, we want an ellipsis at the end of the declaration
>    of the argument list.  GCC version 1 can't parse it.  */
>
> #if __GNUC__ > 1
> #define __va_ellipsis ...
> #else
> #define __va_ellipsis
> #endif
>
> /* These macros implement traditional (non-ANSI) varargs
>    for GNU C.  */
>
> #define va_alist  __builtin_va_alist
> /* The ... causes current_function_varargs to be set in cc1.  */
> #define va_dcl    int __builtin_va_alist; __va_ellipsis
>
> #define va_start(AP)  AP=(char *) &__builtin_va_alist
>
> #endif /* _STDARG_H */
>
> #undef va_end
> void va_end (__gnuc_va_list); /* Defined in libgcc.a */
> #define va_end(AP) ((void)0)
>
> /* We cast to void * and then to TYPE * because this avoids
>    a warning about increasing the alignment requirement.  */
>
> #define __va_rounded_size(TYPE) ((sizeof (TYPE) + 3) & ~3)
> #define __va_align(AP, TYPE) \
>      ((((unsigned long)(AP)) + ((__alignof__ (TYPE) == 16) ? 15 : 3)) \
>       & ~((__alignof__ (TYPE) == 16) ? 15 : 3))
>
> #define va_arg(AP,TYPE) \
> ( *(TYPE *) (void *) ((AP = (char *) (__va_align(AP, TYPE) \
>     + __va_rounded_size(TYPE))) \
>     - __va_rounded_size(TYPE)))
>
> /* Copy __gnuc_va_list into another variable of this type.  */
> #define __va_copy(dest, src) (dest) = (src)
>
> #endif /* _STDARG_H */
>
>
> #else
> #ifndef _WIN32
> /* System V.4 support */
> /* Define __gnuc_va_list.  */
>
> #ifndef __GNUC_VA_LIST
> #define __GNUC_VA_LIST
>
> #ifndef _SYS_VA_LIST_H
> #define _SYS_VA_LIST_H /* Solaris sys/va_list.h */
>
> /* Solaris decided to rename overflow_arg_area to input_arg_area,
>    so handle it via a macro.  */
> #define __va_overflow(AP) (AP)->overflow_arg_area
>
> /* Note that the names in this structure are in the user's namespace, but
>    that the V.4 abi explicitly states that these names should be used.  */
> typedef struct __va_list_tag {
>   unsigned char gpr; /* index into the array of 8 GPRs stored in the
>    register save area gpr=0 corresponds to r3,
>    gpr=1 to r4, etc. */
>   unsigned char fpr; /* index into the array of 8 FPRs stored in the
>    register save area fpr=0 corresponds to f1,
>    fpr=1 to f2, etc. */
>   char *overflow_arg_area; /* location on stack that holds the next
>    overflow argument */
>   char *reg_save_area; /* where r3:r10 and f1:f8, if saved are stored */
> } __va_list[1], __gnuc_va_list[1];
>
> #else /* _SYS_VA_LIST */
>
> typedef __va_list __gnuc_va_list;
> #define __va_overflow(AP) (AP)->input_arg_area
>
> #endif /* not _SYS_VA_LIST */
> #endif /* not __GNUC_VA_LIST */
>
> /* If this is for internal libc use, don't define anything but
>    __gnuc_va_list.  */
> #if defined (_STDARG_H) || defined (_VARARGS_H)
>
> /* Register save area located below the frame pointer */
> #ifndef __VA_PPC_H__
> #define __VA_PPC_H__
> typedef struct {
>   long   __gp_save[8]; /* save area for GP registers */
>   double __fp_save[8]; /* save area for FP registers */
> } __va_regsave_t;
>
> /* Macros to access the register save area */
> /* We cast to void * and then to TYPE * because this avoids
>    a warning about increasing the alignment requirement.  */
> #define __VA_FP_REGSAVE(AP,OFS,TYPE) \
>   ((TYPE *) (void *) (&(((__va_regsave_t *) \
> (AP)->reg_save_area)->__fp_save[OFS])))
>
> #define __VA_GP_REGSAVE(AP,OFS,TYPE) \
>   ((TYPE *) (void *) (&(((__va_regsave_t *) \
> (AP)->reg_save_area)->__gp_save[OFS])))
>
> /* Common code for va_start for both varargs and stdarg.  This depends
>    on the format of rs6000_args in rs6000.h.  The fields used are:
>
>    #0 GWORDS # words used for GP registers
>    #1 FREGNO next available FP register
>    #2 NARGS_PROTOTYPE # args left in the current prototype
>    #3 ORIG_NARGS original value of NARGS_PROTOTYPE
>    #4 VARARGS_OFFSET offset from frame pointer of varargs area */
>
> #define __va_gwords __builtin_args_info (0)
> #define __va_fregno __builtin_args_info (1)
> #define __va_nargs __builtin_args_info (2)
> #define __va_orig_nargs __builtin_args_info (3)
> #define __va_varargs_offset __builtin_args_info (4)
>
> #define __va_start_common(AP, LASTARG, FAKE) \
> __extension__ ({ \
>    register int __gwords = __va_gwords - FAKE; \
> \
>    (AP)->gpr = (__gwords < 8) ? __gwords : 8; \
>    (AP)->fpr = __va_fregno - 33; \
>    (AP)->reg_save_area = (((char *) __builtin_frame_address (0)) \
>   + __va_varargs_offset); \
>    __va_overflow(AP) = __builtin_next_arg(LASTARG) - FAKE * sizeof (int);
\
>    (void)0; \
> })
>
> #ifdef _STDARG_H /* stdarg.h support */
>
> /* Calling __builtin_next_arg gives the proper error message if LASTARG is
>    not indeed the last argument.  */
> #define va_start(AP,LASTARG) __va_start_common (AP, LASTARG, 0)
>
> #else /* varargs.h support */
>
> #define va_start(AP) __va_start_common (AP, __va_1st_arg, 1)
> #define va_alist __va_1st_arg
> #define va_dcl register int va_alist; ...
>
> #endif /* _STDARG_H */
>
> #ifdef _SOFT_FLOAT
> #define __va_float_p(TYPE) 0
> #else
> #define __va_float_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == 8)
> #endif
>
> #define __va_vector_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == -2)
>
> #define __va_longlong_p(TYPE) \
>   ((__builtin_classify_type(*(TYPE *)0) == 1) && (sizeof(TYPE) == 8))
>
> #define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12)
> #define __va_size(TYPE) ((sizeof(TYPE) + sizeof (long) - 1) / sizeof
(long))
>
> /* This symbol isn't defined.  It is used to flag type promotion
violations
>    at link time.  We can only do this when optimizing.  Use __builtin_trap
>    instead of abort so that we don't require a prototype for abort.
>
>    __builtin_trap stuff is not available on the gcc-2.95 branch, so we
just
>    avoid calling it for now.  */
>
> #ifdef __OPTIMIZE__
> extern void __va_arg_type_violation(void) __attribute__((__noreturn__));
> #else
> #define __va_arg_type_violation()
> #endif
>
> #define va_arg(AP,TYPE)    \
> __extension__ (*({    \
>   register TYPE *__ptr;    \
>    \
>   if (__va_vector_p (TYPE))    \
>     {    \
>       __va_overflow(AP) = (char*)(((long)(__va_overflow(AP)) + 15) & ~15);
\
>       __ptr = (TYPE *) (void *) (__va_overflow(AP));    \
>       __va_overflow(AP) += __va_size (TYPE) * sizeof (long);    \
>     }    \
>   else \
>   if (__va_float_p (TYPE) && sizeof (TYPE) < 16)    \
>     {    \
>       unsigned char __fpr = (AP)->fpr;    \
>       if (__fpr < 8)    \
> {    \
>   __ptr = __VA_FP_REGSAVE (AP, __fpr, TYPE);    \
>   (AP)->fpr = __fpr + 1;    \
> }    \
>       else if (sizeof (TYPE) == 8)    \
> {    \
>   unsigned long __addr = (unsigned long) (__va_overflow (AP));    \
>   __ptr = (TYPE *)((__addr + 7) & -8);    \
>   __va_overflow (AP) = (char *)(__ptr + 1);    \
> }    \
>       else    \
> {    \
>   /* float is promoted to double.  */    \
>   __va_arg_type_violation ();    \
> }    \
>     }    \
>    \
>   /* Aggregates and long doubles are passed by reference.  */    \
>   else if (__va_aggregate_p (TYPE) || __va_float_p (TYPE))    \
>     {    \
>       unsigned char __gpr = (AP)->gpr;    \
>       if (__gpr < 8)    \
> {    \
>   __ptr = * __VA_GP_REGSAVE (AP, __gpr, TYPE *);    \
>   (AP)->gpr = __gpr + 1;    \
> }    \
>       else    \
> {    \
>   TYPE **__pptr = (TYPE **) (__va_overflow (AP));    \
>   __ptr = * __pptr;    \
>   __va_overflow (AP) = (char *) (__pptr + 1);    \
> }    \
>     }    \
>    \
>   /* Only integrals remaining.  */    \
>   else    \
>     {    \
>       /* longlong is aligned.  */    \
>       if (sizeof (TYPE) == 8)    \
> {    \
>   unsigned char __gpr = (AP)->gpr;    \
>   if (__gpr < 7)    \
>     {    \
>       __gpr += __gpr & 1;    \
>       __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE);    \
>       (AP)->gpr = __gpr + 2;    \
>     }    \
>   else    \
>     {    \
>       unsigned long __addr = (unsigned long) (__va_overflow (AP)); \
>       __ptr = (TYPE *)((__addr + 7) & -8);    \
>       (AP)->gpr = 8;    \
>       __va_overflow (AP) = (char *)(__ptr + 1);    \
>     }    \
> }    \
>       else if (sizeof (TYPE) == 4)    \
> {    \
>   unsigned char __gpr = (AP)->gpr;    \
>   if (__gpr < 8)    \
>     {    \
>       __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE);    \
>       (AP)->gpr = __gpr + 1;    \
>     }    \
>   else    \
>     {    \
>       __ptr = (TYPE *) __va_overflow (AP);    \
>       __va_overflow (AP) = (char *)(__ptr + 1);    \
>     }    \
> }    \
>       else    \
> {    \
>   /* Everything else was promoted to int.  */    \
>   __va_arg_type_violation ();    \
> }    \
>     }    \
>   __ptr;    \
> }))
>
> #define va_end(AP) ((void)0)
>
> /* Copy __gnuc_va_list into another variable of this type.  */
> #define __va_copy(dest, src) *(dest) = *(src)
>
> #endif /* __VA_PPC_H__ */
> #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
>
>
> #else
> /* Windows NT */
> /* Define __gnuc_va_list.  */
>
> #ifndef __GNUC_VA_LIST
> #define __GNUC_VA_LIST
> typedef char *__gnuc_va_list;
> #endif /* not __GNUC_VA_LIST */
>
> /* If this is for internal libc use, don't define anything but
>    __gnuc_va_list.  */
> #if defined (_STDARG_H) || defined (_VARARGS_H)
>
> #define __va_start_common(AP, LASTARG, FAKE) \
>   ((__builtin_saveregs ()), ((AP) = ((char *) &LASTARG) +
__va_rounded_size (AP)), 0)
>
> #ifdef _STDARG_H /* stdarg.h support */
>
> /* Calling __builtin_next_arg gives the proper error message if LASTARG is
>    not indeed the last argument.  */
> #define va_start(AP,LASTARG) \
>   (__builtin_saveregs (), \
>    (AP) = __builtin_next_arg (LASTARG), \
>    0)
>
> #else /* varargs.h support */
>
> #define va_start(AP) \
>   (__builtin_saveregs (), \
>    (AP) = __builtin_next_arg (__va_1st_arg) - sizeof (int), \
>    0)
>
> #define va_alist __va_1st_arg
> #define va_dcl register int __va_1st_arg; ...
>
> #endif /* _STDARG_H */
>
> #define __va_rounded_size(TYPE) ((sizeof (TYPE) + 3) & ~3)
> #define __va_align(AP, TYPE) \
>      ((((unsigned long)(AP)) + ((sizeof (TYPE) >= 8) ? 7 : 3)) \
>       & ~((sizeof (TYPE) >= 8) ? 7 : 3))
>
> #define va_arg(AP,TYPE) \
> ( *(TYPE *)((AP = (char *) (__va_align(AP, TYPE) \
>     + __va_rounded_size(TYPE))) \
>     - __va_rounded_size(TYPE)))
>
> #define va_end(AP) ((void)0)
>
> /* Copy __gnuc_va_list into another variable of this type.  */
> #define __va_copy(dest, src) (dest) = (src)
>
> #endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
> #endif /* Windows NT */
> #endif /* not _AIX */
>



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:51:05 MET