diff options
Diffstat (limited to 'gl/msvc-inval.c')
| -rw-r--r-- | gl/msvc-inval.c | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/gl/msvc-inval.c b/gl/msvc-inval.c new file mode 100644 index 00000000..396031e4 --- /dev/null +++ b/gl/msvc-inval.c | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | /* Invalid parameter handler for MSVC runtime libraries. | ||
| 2 | Copyright (C) 2011-2013 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This program is free software; you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation; either version 3, or (at your option) | ||
| 7 | any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License along | ||
| 15 | with this program; if not, see <http://www.gnu.org/licenses/>. */ | ||
| 16 | |||
| 17 | #include <config.h> | ||
| 18 | |||
| 19 | /* Specification. */ | ||
| 20 | #include "msvc-inval.h" | ||
| 21 | |||
| 22 | #if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ | ||
| 23 | && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) | ||
| 24 | |||
| 25 | /* Get _invalid_parameter_handler type and _set_invalid_parameter_handler | ||
| 26 | declaration. */ | ||
| 27 | # include <stdlib.h> | ||
| 28 | |||
| 29 | # if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING | ||
| 30 | |||
| 31 | static void __cdecl | ||
| 32 | gl_msvc_invalid_parameter_handler (const wchar_t *expression, | ||
| 33 | const wchar_t *function, | ||
| 34 | const wchar_t *file, | ||
| 35 | unsigned int line, | ||
| 36 | uintptr_t dummy) | ||
| 37 | { | ||
| 38 | } | ||
| 39 | |||
| 40 | # else | ||
| 41 | |||
| 42 | /* Get declarations of the native Windows API functions. */ | ||
| 43 | # define WIN32_LEAN_AND_MEAN | ||
| 44 | # include <windows.h> | ||
| 45 | |||
| 46 | # if defined _MSC_VER | ||
| 47 | |||
| 48 | static void __cdecl | ||
| 49 | gl_msvc_invalid_parameter_handler (const wchar_t *expression, | ||
| 50 | const wchar_t *function, | ||
| 51 | const wchar_t *file, | ||
| 52 | unsigned int line, | ||
| 53 | uintptr_t dummy) | ||
| 54 | { | ||
| 55 | RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); | ||
| 56 | } | ||
| 57 | |||
| 58 | # else | ||
| 59 | |||
| 60 | /* An index to thread-local storage. */ | ||
| 61 | static DWORD tls_index; | ||
| 62 | static int tls_initialized /* = 0 */; | ||
| 63 | |||
| 64 | /* Used as a fallback only. */ | ||
| 65 | static struct gl_msvc_inval_per_thread not_per_thread; | ||
| 66 | |||
| 67 | struct gl_msvc_inval_per_thread * | ||
| 68 | gl_msvc_inval_current (void) | ||
| 69 | { | ||
| 70 | if (!tls_initialized) | ||
| 71 | { | ||
| 72 | tls_index = TlsAlloc (); | ||
| 73 | tls_initialized = 1; | ||
| 74 | } | ||
| 75 | if (tls_index == TLS_OUT_OF_INDEXES) | ||
| 76 | /* TlsAlloc had failed. */ | ||
| 77 | return ¬_per_thread; | ||
| 78 | else | ||
| 79 | { | ||
| 80 | struct gl_msvc_inval_per_thread *pointer = | ||
| 81 | (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); | ||
| 82 | if (pointer == NULL) | ||
| 83 | { | ||
| 84 | /* First call. Allocate a new 'struct gl_msvc_inval_per_thread'. */ | ||
| 85 | pointer = | ||
| 86 | (struct gl_msvc_inval_per_thread *) | ||
| 87 | malloc (sizeof (struct gl_msvc_inval_per_thread)); | ||
| 88 | if (pointer == NULL) | ||
| 89 | /* Could not allocate memory. Use the global storage. */ | ||
| 90 | pointer = ¬_per_thread; | ||
| 91 | TlsSetValue (tls_index, pointer); | ||
| 92 | } | ||
| 93 | return pointer; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | static void __cdecl | ||
| 98 | gl_msvc_invalid_parameter_handler (const wchar_t *expression, | ||
| 99 | const wchar_t *function, | ||
| 100 | const wchar_t *file, | ||
| 101 | unsigned int line, | ||
| 102 | uintptr_t dummy) | ||
| 103 | { | ||
| 104 | struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); | ||
| 105 | if (current->restart_valid) | ||
| 106 | longjmp (current->restart, 1); | ||
| 107 | else | ||
| 108 | /* An invalid parameter notification from outside the gnulib code. | ||
| 109 | Give the caller a chance to intervene. */ | ||
| 110 | RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); | ||
| 111 | } | ||
| 112 | |||
| 113 | # endif | ||
| 114 | |||
| 115 | # endif | ||
| 116 | |||
| 117 | static int gl_msvc_inval_initialized /* = 0 */; | ||
| 118 | |||
| 119 | void | ||
| 120 | gl_msvc_inval_ensure_handler (void) | ||
| 121 | { | ||
| 122 | if (gl_msvc_inval_initialized == 0) | ||
| 123 | { | ||
| 124 | _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler); | ||
| 125 | gl_msvc_inval_initialized = 1; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | #endif | ||
