/* The header is ANSI's way to handle variable numbers of params. * Some programming languages require a function that is declared with n * parameters to be called with n parameters. C does not. A function may * called with more parameters than it is declared with. The well-known * printf function, for example, may have arbitrarily many parameters. * The question arises how one can access all the parameters in a portable * way. The C standard defines three macros that programs can use to * advance through the parameter list. The definition of these macros for * MINIX are given in this file. The three macros are: * * va_start(ap, parmN) prepare to access parameters * va_arg(ap, type) get next parameter value and type * va_end(ap) access is finished * * Ken Thompson's famous line from V6 UNIX is equally applicable to this file: * * "You are not expected to understand this" * */ #ifndef _STDARG_H #define _STDARG_H #ifdef __GNUC__ /* The GNU C-compiler uses its own, but similar varargs mechanism. */ typedef char *va_list; /* Amount of space required in an argument list for an arg of type TYPE. * TYPE may alternatively be an expression whose type is used. */ #define __va_rounded_size(TYPE) \ (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) #if __GNUC__ < 2 #ifndef __sparc__ #define va_start(AP, LASTARG) \ (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) #else #define va_start(AP, LASTARG) \ (__builtin_saveregs (), \ AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG))) #endif void va_end (va_list); /* Defined in gnulib */ #define va_end(AP) #define va_arg(AP, TYPE) \ (AP += __va_rounded_size (TYPE), \ *((TYPE *) (AP - __va_rounded_size (TYPE)))) #else /* __GNUC__ >= 2 */ #ifndef __sparc__ #define va_start(AP, LASTARG) \ (AP = ((char *) __builtin_next_arg ())) #else #define va_start(AP, LASTARG) \ (__builtin_saveregs (), AP = ((char *) __builtin_next_arg ())) #endif void va_end (va_list); /* Defined in libgcc.a */ #define va_end(AP) #define va_arg(AP, TYPE) \ (AP = ((char *) (AP)) += __va_rounded_size (TYPE), \ *((TYPE *) ((char *) (AP) - __va_rounded_size (TYPE)))) #endif /* __GNUC__ >= 2 */ #else /* not __GNUC__ */ typedef char *va_list; #define __vasz(x) ((sizeof(x)+sizeof(int)-1) & ~(sizeof(int) -1)) #define va_start(ap, parmN) ((ap) = (va_list)&parmN + __vasz(parmN)) #define va_arg(ap, type) \ (*((type *)((va_list)((ap) = (void *)((va_list)(ap) + __vasz(type))) \ - __vasz(type)))) #define va_end(ap) #endif /* __GNUC__ */ #endif /* _STDARG_H */