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__) 96 97 #if defined(MDE_CPU_X64) && !defined(NO_MSABI_VA_FUNCS) 98 // 99 // X64 only. Use MS ABI version of GCC built-in macros for variable argument lists. 100 // 101 /// 102 /// Both GCC and LLVM 3.8 for X64 support new variable argument intrinsics for Microsoft ABI 103 /// 104 105 /// 106 /// Variable used to traverse the list of arguments. This type can vary by 107 /// implementation and could be an array or structure. 108 /// 109 typedef __builtin_ms_va_list VA_LIST; 110 111 #define VA_START(Marker, Parameter) __builtin_ms_va_start (Marker, Parameter) 112 113 #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE))) 114 115 #define VA_END(Marker) __builtin_ms_va_end (Marker) 116 117 #define VA_COPY(Dest, Start) __builtin_ms_va_copy (Dest, Start) 118 119 #else 120 // 121 // Use GCC built-in macros for variable argument lists. 122 // 123 124 /// 125 /// Variable used to traverse the list of arguments. This type can vary by 126 /// implementation and could be an array or structure. 127 /// 128 typedef __builtin_va_list VA_LIST; 129 130 #define VA_START(Marker, Parameter) __builtin_va_start (Marker, Parameter) 131 132 #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker, TYPE))) 133 134 #define VA_END(Marker) __builtin_va_end (Marker) 135 136 #define VA_COPY(Dest, Start) __builtin_va_copy (Dest, Start) 137 138 #endif 139 140 #else 141 142 #ifndef VA_START 143 144 /// 145 /// Variable used to traverse the list of arguments. This type can vary by 146 /// implementation and could be an array or structure. 147 /// 148 typedef CHAR8 *VA_LIST; 149 150 /** 151 Retrieves a pointer to the beginning of a variable argument list, based on 152 the name of the parameter that immediately precedes the variable argument list. 153 154 This function initializes Marker to point to the beginning of the variable 155 argument list that immediately follows Parameter. The method for computing the 156 pointer to the next argument in the argument list is CPU-specific following the 157 EFIAPI ABI. 158 159 @param Marker The VA_LIST used to traverse the list of arguments. 160 @param Parameter The name of the parameter that immediately precedes 161 the variable argument list. 162 163 @return A pointer to the beginning of a variable argument list. 164 165 **/ 166 #define VA_START(Marker, Parameter) (Marker = (VA_LIST) ((UINTN) & (Parameter) + _INT_SIZE_OF (Parameter))) 167 168 /** 169 Returns an argument of a specified type from a variable argument list and updates 170 the pointer to the variable argument list to point to the next argument. 171 172 This function returns an argument of the type specified by TYPE from the beginning 173 of the variable argument list specified by Marker. Marker is then updated to point 174 to the next argument in the variable argument list. The method for computing the 175 pointer to the next argument in the argument list is CPU-specific following the EFIAPI ABI. 176 177 @param Marker VA_LIST used to traverse the list of arguments. 178 @param TYPE The type of argument to retrieve from the beginning 179 of the variable argument list. 180 181 @return An argument of the type specified by TYPE. 182 183 **/ 184 #define VA_ARG(Marker, TYPE) (*(TYPE *) ((Marker += _INT_SIZE_OF (TYPE)) - _INT_SIZE_OF (TYPE))) 185 186 /** 187 Terminates the use of a variable argument list. 188 189 This function initializes Marker so it can no longer be used with VA_ARG(). 190 After this macro is used, the only way to access the variable argument list is 191 by using VA_START() again. 192 193 @param Marker VA_LIST used to traverse the list of arguments. 194 195 **/ 196 #define VA_END(Marker) (Marker = (VA_LIST) 0) 197 198 #define VA_COPY(dest, src) ((void)((dest) = (src))) 199 200 #endif 201 202 #endif 203 204 #endif 205