1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
/*
* Copyright 1995-2018 Bruno Haible <bruno@clisp.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include "vacall-internal.h"
/* This is the implementation of the library API.
The symbols that the linker sees are all prefixed with 'vacall',
to avoid potential collisions with other libraries. */
#ifndef REENTRANT
/* This is the function pointer vacall(). A function pointer indirection is
needed because gcc-3.4 generates invalid code when the address of a symbol
is casted to a function pointer with different return type.
(https://gcc.gnu.org/ml/gcc-patches/2003-12/msg01767.html) */
#ifdef __cplusplus
extern "C" void vacall_receiver (); /* the return type is variable, not void! */
#else
extern void vacall_receiver (); /* the return type is variable, not void! */
#endif
void (*vacall) () = vacall_receiver;
/* This is the function called by vacall(). */
void (* vacall_function) (va_alist);
#endif
/* Room for returning structs according to the Sun C non-reentrant struct return convention. */
typedef union { __vaword room[__VA_ALIST_WORDS]; double align; } __va_struct_buffer_t;
static __va_struct_buffer_t vacall_struct_buffer;
static _Noreturn void
vacall_error_type_mismatch (enum __VAtype start_type, enum __VAtype return_type)
{
/* If you see this, fix your code. */
fprintf (stderr, "vacall: va_start type %d and va_return type %d disagree.\n",
(int)start_type, (int)return_type);
abort();
}
static _Noreturn void
vacall_error_struct_too_large (unsigned int size)
{
/* If you see this, increase __VA_ALIST_WORDS: */
fprintf (stderr, "vacall: struct of size %u too large for Sun C struct return.\n",
size);
abort();
}
void vacall_start (va_alist list, int rettype, int flags)
{
__va_start(list,rettype,flags);
}
void vacall_start_struct (va_alist list, size_t type_size, size_t type_align, int type_splittable, int flags)
{
__va_start_struct(list,type_size,type_align,type_splittable,flags);
}
char vacall_arg_char (va_alist list)
{
return _va_arg_char(list);
}
signed char vacall_arg_schar (va_alist list)
{
return _va_arg_schar(list);
}
unsigned char vacall_arg_uchar (va_alist list)
{
return _va_arg_uchar(list);
}
short vacall_arg_short (va_alist list)
{
return _va_arg_short(list);
}
unsigned short vacall_arg_ushort (va_alist list)
{
return _va_arg_ushort(list);
}
int vacall_arg_int (va_alist list)
{
return _va_arg_int(list);
}
unsigned int vacall_arg_uint (va_alist list)
{
return _va_arg_uint(list);
}
long vacall_arg_long (va_alist list)
{
return _va_arg_long(list);
}
unsigned long vacall_arg_ulong (va_alist list)
{
return _va_arg_ulong(list);
}
long long vacall_arg_longlong (va_alist list)
{
return _va_arg_longlong(list);
}
unsigned long long vacall_arg_ulonglong (va_alist list)
{
return _va_arg_ulonglong(list);
}
float vacall_arg_float (va_alist list)
{
return _va_arg_float(list);
}
double vacall_arg_double (va_alist list)
{
return _va_arg_double(list);
}
void* vacall_arg_ptr (va_alist list)
{
return _va_arg_ptr(list);
}
void* vacall_arg_struct (va_alist list, size_t type_size, size_t type_align)
{
return __va_arg_struct(list,type_size,type_align);
}
void vacall_return_void (va_alist list)
{
_va_return_void(list);
}
void vacall_return_char (va_alist list, char val)
{
_va_return_char(list,val);
}
void vacall_return_schar (va_alist list, signed char val)
{
_va_return_schar(list,val);
}
void vacall_return_uchar (va_alist list, unsigned char val)
{
_va_return_uchar(list,val);
}
void vacall_return_short (va_alist list, short val)
{
_va_return_short(list,val);
}
void vacall_return_ushort (va_alist list, unsigned short val)
{
_va_return_ushort(list,val);
}
void vacall_return_int (va_alist list, int val)
{
_va_return_int(list,val);
}
void vacall_return_uint (va_alist list, unsigned int val)
{
_va_return_uint(list,val);
}
void vacall_return_long (va_alist list, long val)
{
_va_return_long(list,val);
}
void vacall_return_ulong (va_alist list, unsigned long val)
{
_va_return_ulong(list,val);
}
void vacall_return_longlong (va_alist list, long long val)
{
_va_return_longlong(list,val);
}
void vacall_return_ulonglong (va_alist list, unsigned long long val)
{
_va_return_ulonglong(list,val);
}
void vacall_return_float (va_alist list, float val)
{
_va_return_float(list,val);
}
void vacall_return_double (va_alist list, double val)
{
_va_return_double(list,val);
}
void vacall_return_ptr (va_alist list, void* val)
{
_va_return_ptr(list,val);
}
void vacall_return_struct (va_alist list, size_t type_size, size_t type_align, const void* val_addr)
{
__va_return_struct(list,type_size,type_align,val_addr);
}
|