8dfc7699a6
reverse order to easily support variadic arguments. Thus, instead of using the proper stdarg.h macros (that nowadays are compiler-dependent), it may be tempting to directly take the address of the last argument and considering it as the start of an array. This is a shortcut that avoid looping to get all the arguments as the CPU already pushed them on the stack before the call to the function. Unfortunately, such an assumption is strictly compiler-dependent and compilers are free to move the last argument on the stack, as a local variable, and return the address of the location where the argument was stored, if asked for. This will break things as the rest of the array's argument are stored elsewhere (typically, a couple of words above the location where the argument was stored). This patch fixes the issue by allowing ACK to take the shortcut and enabling gcc/llvm-gcc to follow the right way.
78 lines
2.6 KiB
C
78 lines
2.6 KiB
C
/* The <stdarg.h> 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 */
|
|
|
|
#define va_start(ap, last) __builtin_va_start((ap), (last))
|
|
#define va_arg(ap, type) __builtin_va_arg((ap), type)
|
|
#define va_end(ap) __builtin_va_end(ap)
|
|
#define va_copy(dest, src) __builtin_va_copy((dest), (src))
|
|
|
|
#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_copy(ap2, ap) (ap2) = (ap)
|
|
#define va_end(ap)
|
|
|
|
#endif /* __GNUC__ */
|
|
|
|
#endif /* _STDARG_H */
|