[4] | 1 | /* The <stdarg.h> header is ANSI's way to handle variable numbers of params.
|
---|
| 2 | * Some programming languages require a function that is declared with n
|
---|
| 3 | * parameters to be called with n parameters. C does not. A function may
|
---|
| 4 | * called with more parameters than it is declared with. The well-known
|
---|
| 5 | * printf function, for example, may have arbitrarily many parameters.
|
---|
| 6 | * The question arises how one can access all the parameters in a portable
|
---|
| 7 | * way. The C standard defines three macros that programs can use to
|
---|
| 8 | * advance through the parameter list. The definition of these macros for
|
---|
| 9 | * MINIX are given in this file. The three macros are:
|
---|
| 10 | *
|
---|
| 11 | * va_start(ap, parmN) prepare to access parameters
|
---|
| 12 | * va_arg(ap, type) get next parameter value and type
|
---|
| 13 | * va_end(ap) access is finished
|
---|
| 14 | *
|
---|
| 15 | * Ken Thompson's famous line from V6 UNIX is equally applicable to this file:
|
---|
| 16 | *
|
---|
| 17 | * "You are not expected to understand this"
|
---|
| 18 | *
|
---|
| 19 | */
|
---|
| 20 |
|
---|
| 21 | #ifndef _STDARG_H
|
---|
| 22 | #define _STDARG_H
|
---|
| 23 |
|
---|
| 24 | #ifdef __GNUC__
|
---|
| 25 | /* The GNU C-compiler uses its own, but similar varargs mechanism. */
|
---|
| 26 |
|
---|
| 27 | typedef char *va_list;
|
---|
| 28 |
|
---|
| 29 | /* Amount of space required in an argument list for an arg of type TYPE.
|
---|
| 30 | * TYPE may alternatively be an expression whose type is used.
|
---|
| 31 | */
|
---|
| 32 |
|
---|
| 33 | #define __va_rounded_size(TYPE) \
|
---|
| 34 | (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
|
---|
| 35 |
|
---|
| 36 | #if __GNUC__ < 2
|
---|
| 37 |
|
---|
| 38 | #ifndef __sparc__
|
---|
| 39 | #define va_start(AP, LASTARG) \
|
---|
| 40 | (AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
|
---|
| 41 | #else
|
---|
| 42 | #define va_start(AP, LASTARG) \
|
---|
| 43 | (__builtin_saveregs (), \
|
---|
| 44 | AP = ((char *) &(LASTARG) + __va_rounded_size (LASTARG)))
|
---|
| 45 | #endif
|
---|
| 46 |
|
---|
| 47 | void va_end (va_list); /* Defined in gnulib */
|
---|
| 48 | #define va_end(AP)
|
---|
| 49 |
|
---|
| 50 | #define va_arg(AP, TYPE) \
|
---|
| 51 | (AP += __va_rounded_size (TYPE), \
|
---|
| 52 | *((TYPE *) (AP - __va_rounded_size (TYPE))))
|
---|
| 53 |
|
---|
| 54 | #else /* __GNUC__ >= 2 */
|
---|
| 55 |
|
---|
| 56 | #ifndef __sparc__
|
---|
| 57 | #define va_start(AP, LASTARG) \
|
---|
| 58 | (AP = ((char *) __builtin_next_arg ()))
|
---|
| 59 | #else
|
---|
| 60 | #define va_start(AP, LASTARG) \
|
---|
| 61 | (__builtin_saveregs (), AP = ((char *) __builtin_next_arg ()))
|
---|
| 62 | #endif
|
---|
| 63 |
|
---|
| 64 | void va_end (va_list); /* Defined in libgcc.a */
|
---|
| 65 | #define va_end(AP)
|
---|
| 66 |
|
---|
| 67 | #define va_arg(AP, TYPE) \
|
---|
| 68 | (AP = ((char *) (AP)) += __va_rounded_size (TYPE), \
|
---|
| 69 | *((TYPE *) ((char *) (AP) - __va_rounded_size (TYPE))))
|
---|
| 70 |
|
---|
| 71 | #endif /* __GNUC__ >= 2 */
|
---|
| 72 |
|
---|
| 73 | #else /* not __GNUC__ */
|
---|
| 74 |
|
---|
| 75 | typedef char *va_list;
|
---|
| 76 |
|
---|
| 77 | #define __vasz(x) ((sizeof(x)+sizeof(int)-1) & ~(sizeof(int) -1))
|
---|
| 78 |
|
---|
| 79 | #define va_start(ap, parmN) ((ap) = (va_list)&parmN + __vasz(parmN))
|
---|
| 80 | #define va_arg(ap, type) \
|
---|
| 81 | (*((type *)((va_list)((ap) = (void *)((va_list)(ap) + __vasz(type))) \
|
---|
| 82 | - __vasz(type))))
|
---|
| 83 | #define va_end(ap)
|
---|
| 84 |
|
---|
| 85 | #endif /* __GNUC__ */
|
---|
| 86 |
|
---|
| 87 | #endif /* _STDARG_H */
|
---|