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 */
|
---|