Re: va_lists in glib/gtk and set/get(...) functions



On Sat, 22 Aug 1998, Tor Lillqvist wrote:

> > i'll therefore go through gtk and glib and change the
> > void func ([some args], va_list *args1, va_list *args2)
> > {
> > }
> > prototypes to
> > void func ([some args], va_list args1)
> > {
> >   va_list arg2 = args1;
> > }
> 
> Not so fast... This will not compile if va_list is defined as: 
>  typedef char *va_list[0] .
> 
> In that case you would have to use the (totally implementation-dependent) 
>  char  **arg2 = args1;
> 
> But hmm, I'm not 100% sure if that will have the desired effect.
> (Well, when I changed gtk like this, at least I don't get the invalid
> cast etc warnings any more.)
> 
> Maybe it's better to bite the bullet and define some macros, and
> document what effect they should product. Something like 
> 
> #ifndef __WATCOMC__
> #define VA_REF(ap) &ap
> #define VA_PTR(ap) *ap
> #define VA_PTR_DEREF(ap) (*ap)
> #else
> #define VA_REF(ap) ap
> #define VA_PTR(ap) ap
> #define VA_PTR_DEREF(ap) ap
> #endif
> 
> and modify gtk sources accordingly, ie where now the address of an
> va_list is passed to a function, use VA_REF. In a function prototype
> that now has va_list *, use VA_PTR, and when using that parameter, use
> VA_PTR_DEREF.
> 
> This leaves gtk_args_collect where var_args_p comes in as a gpointer,
> and is assigned to a va_list *. Here I used the
> implementation-dependent hack char **var_args = var_args_p.

the c9x draft clearly states:
       195. It is permitted to create a pointer to  a  va_list  and
           pass that pointer to another function, in which case the
           original function may make further use of  the  original
           list after the other function returns.

but as we already figured, this is not the case for some windows compilers,
and the va-ppc.h shipped with current GNUC distributions.
however, the above mentioned behaviour is only required if the caller
wants to process remaining arguments after a called function that got
the va_list variable passed by reference has processed the arg list only
partly. this is not the case with any of the functions that make use of
a va_list* pointer withing glib or gtk.
in order to get portable va_list behaviour, we currently need to work around
the ppc/watcom behaviour, threfore pass va_lists by value.
i've further digged through some mailing list archieves to gather
some information on the va_copy behaviour, that is actually also newly
introduce by the c9x draft.
recent GNUC compilers (>=2.8.0) provide either __va_copy() or va_copy()
implementations, and i guess this will also be the case for other platforms
with reasonably new compilers.

the best way to get portable va_copy() behaviour is probably to first
have a configure check for va_copy(), __va_copy() and va_list implemented
as an array and if that fails, provide platform/compiler specific
implementations:

#if	defined (HAVE_VA_COPY)
#define	G_VA_COPY(ap1, ap2)	va_copy (ap1, ap2)
#elif	defined (HAVE___VA_COPY)
#define	G_VA_COPY(ap1, ap2)	__va_copy (ap1, ap2)
#elif	defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
#define G_VA_COPY(ap1, ap2)	*(ap1) = *(ap2)
#elif	defined (HAVE_VA_LIST_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 */

tor, could you try this out with watcom?

> 
> --tml
> 
> 

---
ciaoTJ



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]