X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fmsvc-inval.c;h=1873e23be4c9d46d95a8b7bea7ea5a07db430829;hb=4779b635ef35c7b0bc4044fcb5bc746d06f158c4;hp=4618455fa3d61017648b67244474d5180e21bf97;hpb=07edb02c97efe29a68bf5acd6cc3fcb0f7e79582;p=gnulib.git diff --git a/lib/msvc-inval.c b/lib/msvc-inval.c index 4618455fa..1873e23be 100644 --- a/lib/msvc-inval.c +++ b/lib/msvc-inval.c @@ -1,5 +1,5 @@ /* Invalid parameter handler for MSVC runtime libraries. - Copyright (C) 2011 Free Software Foundation, Inc. + Copyright (C) 2011-2013 Free Software Foundation, Inc. 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 @@ -12,52 +12,106 @@ 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, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + with this program; if not, see . */ #include /* Specification. */ #include "msvc-inval.h" -#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER \ + && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING) -/* Get declarations of the Win32 API functions. */ -# define WIN32_LEAN_AND_MEAN -# include +/* Get _invalid_parameter_handler type and _set_invalid_parameter_handler + declaration. */ +# include -# if defined _MSC_VER +# if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING -static void cdecl +static void __cdecl gl_msvc_invalid_parameter_handler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t dummy) { - RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); } # else -jmp_buf gl_msvc_inval_restart; -int gl_msvc_inval_restart_valid; +/* Get declarations of the native Windows API functions. */ +# define WIN32_LEAN_AND_MEAN +# include + +# if defined _MSC_VER -static void cdecl +static void __cdecl gl_msvc_invalid_parameter_handler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t dummy) { - if (gl_msvc_inval_restart_valid) - longjmp (gl_msvc_inval_restart, 1); + RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); +} + +# else + +/* An index to thread-local storage. */ +static DWORD tls_index; +static int tls_initialized /* = 0 */; + +/* Used as a fallback only. */ +static struct gl_msvc_inval_per_thread not_per_thread; + +struct gl_msvc_inval_per_thread * +gl_msvc_inval_current (void) +{ + if (!tls_initialized) + { + tls_index = TlsAlloc (); + tls_initialized = 1; + } + if (tls_index == TLS_OUT_OF_INDEXES) + /* TlsAlloc had failed. */ + return ¬_per_thread; + else + { + struct gl_msvc_inval_per_thread *pointer = + (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index); + if (pointer == NULL) + { + /* First call. Allocate a new 'struct gl_msvc_inval_per_thread'. */ + pointer = + (struct gl_msvc_inval_per_thread *) + malloc (sizeof (struct gl_msvc_inval_per_thread)); + if (pointer == NULL) + /* Could not allocate memory. Use the global storage. */ + pointer = ¬_per_thread; + TlsSetValue (tls_index, pointer); + } + return pointer; + } +} + +static void __cdecl +gl_msvc_invalid_parameter_handler (const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t dummy) +{ + struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current (); + if (current->restart_valid) + longjmp (current->restart, 1); else /* An invalid parameter notification from outside the gnulib code. Give the caller a chance to intervene. */ RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL); } +# endif + # endif static int gl_msvc_inval_initialized /* = 0 */;