1 /*++
2 
3 Copyright (c) 2004, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   EfiStdArg.h
15 
16 Abstract:
17 
18   Support for variable length argument lists using the ANSI standard.
19 
20   Since we are using the ANSI standard we used the standard nameing and
21   did not folow the coding convention
22 
23   VA_LIST  - typedef for argument list.
24   VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use.
25   VA_END (VA_LIST Marker) - Clear Marker
26   VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argumnet from
27     the ... list. You must know the size and pass it in this macro.
28 
29   example:
30 
31   UINTN
32   ExampleVarArg (
33     IN UINTN  NumberOfArgs,
34     ...
35     )
36   {
37     VA_LIST Marker;
38     UINTN   Index;
39     UINTN   Result;
40 
41     //
42     // Initialize the Marker
43     //
44     VA_START (Marker, NumberOfArgs);
45     for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) {
46       //
47       // The ... list is a series of UINTN values, so average them up.
48       //
49       Result += VA_ARG (Marker, UINTN);
50     }
51 
52     VA_END (Marker);
53     return Result
54   }
55 
56 --*/
57 
58 #ifndef _EFISTDARG_H_
59 #define _EFISTDARG_H_
60 
61 /**
62   Return the size of argument that has been aligned to sizeof (UINTN).
63 
64   @param  n    The parameter size to be aligned.
65 
66   @return The aligned size.
67 **/
68 #define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1))
69 
70 #if defined(__CC_ARM)
71 //
72 // RVCT ARM variable argument list support.
73 //
74 
75 ///
76 /// Variable used to traverse the list of arguments. This type can vary by
77 /// implementation and could be an array or structure.
78 ///
79 #ifdef __APCS_ADSABI
80   typedef int         *va_list[1];
81   #define VA_LIST     va_list
82 #else
83   typedef struct __va_list { void *__ap; } va_list;
84   #define VA_LIST                          va_list
85 #endif
86 
87 #define VA_START(Marker, Parameter)   __va_start(Marker, Parameter)
88 
89 #define VA_ARG(Marker, TYPE)          __va_arg(Marker, TYPE)
90 
91 #define VA_END(Marker)                ((void)0)
92 
93 #define VA_COPY(Dest, Start)          __va_copy (Dest, Start)
94 
95 #elif defined(__GNUC__) && !defined(NO_BUILTIN_VA_FUNCS)
96 //
97 // Use GCC built-in macros for variable argument lists.
98 //
99 
100 ///
101 /// Variable used to traverse the list of arguments. This type can vary by
102 /// implementation and could be an array or structure.
103 ///
104 typedef __builtin_va_list VA_LIST;
105 
106 #define VA_START(Marker, Parameter)  __builtin_va_start (Marker, Parameter)
107 
108 #define VA_ARG(Marker, TYPE)         ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE)))
109 
110 #define VA_END(Marker)               __builtin_va_end (Marker)
111 
112 #define VA_COPY(Dest, Start)         __builtin_va_copy (Dest, Start)
113 
114 #else
115 
116 #ifndef VA_START
117 
118 ///
119 /// Variable used to traverse the list of arguments. This type can vary by
120 /// implementation and could be an array or structure.
121 ///
122 typedef CHAR8 *VA_LIST;
123 
124 /**
125   Retrieves a pointer to the beginning of a variable argument list, based on
126   the name of the parameter that immediately precedes the variable argument list.
127 
128   This function initializes Marker to point to the beginning of the variable
129   argument list that immediately follows Parameter.  The method for computing the
130   pointer to the next argument in the argument list is CPU-specific following the
131   EFIAPI ABI.
132 
133   @param   Marker       The VA_LIST used to traverse the list of arguments.
134   @param   Parameter    The name of the parameter that immediately precedes
135                         the variable argument list.
136 
137   @return  A pointer to the beginning of a variable argument list.
138 
139 **/
140 #define VA_START(Marker, Parameter) (Marker = (VA_LIST) ((UINTN) & (Parameter) + _INT_SIZE_OF (Parameter)))
141 
142 /**
143   Returns an argument of a specified type from a variable argument list and updates
144   the pointer to the variable argument list to point to the next argument.
145 
146   This function returns an argument of the type specified by TYPE from the beginning
147   of the variable argument list specified by Marker.  Marker is then updated to point
148   to the next argument in the variable argument list.  The method for computing the
149   pointer to the next argument in the argument list is CPU-specific following the EFIAPI ABI.
150 
151   @param   Marker   VA_LIST used to traverse the list of arguments.
152   @param   TYPE     The type of argument to retrieve from the beginning
153                     of the variable argument list.
154 
155   @return  An argument of the type specified by TYPE.
156 
157 **/
158 #define VA_ARG(Marker, TYPE)   (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE)) - _INT_SIZE_OF (TYPE)))
159 
160 /**
161   Terminates the use of a variable argument list.
162 
163   This function initializes Marker so it can no longer be used with VA_ARG().
164   After this macro is used, the only way to access the variable argument list is
165   by using VA_START() again.
166 
167   @param   Marker   VA_LIST used to traverse the list of arguments.
168 
169 **/
170 #define VA_END(Marker)      (Marker = (VA_LIST) 0)
171 
172 #define VA_COPY(dest, src) ((void)((dest) = (src)))
173 
174 #endif
175 
176 #endif
177 
178 #endif
179