xref: /netbsd-src/external/gpl3/gdb/dist/gnulib/import/msvc-inval.c (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
18dffb485Schristos /* Invalid parameter handler for MSVC runtime libraries.
2*4b169a6bSchristos    Copyright (C) 2011-2022 Free Software Foundation, Inc.
38dffb485Schristos 
4*4b169a6bSchristos    This file is free software: you can redistribute it and/or modify
5*4b169a6bSchristos    it under the terms of the GNU Lesser General Public License as
6*4b169a6bSchristos    published by the Free Software Foundation; either version 2.1 of the
7*4b169a6bSchristos    License, or (at your option) any later version.
88dffb485Schristos 
9*4b169a6bSchristos    This file is distributed in the hope that it will be useful,
108dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
118dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*4b169a6bSchristos    GNU Lesser General Public License for more details.
138dffb485Schristos 
14*4b169a6bSchristos    You should have received a copy of the GNU Lesser General Public License
15*4b169a6bSchristos    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
168dffb485Schristos 
178dffb485Schristos #include <config.h>
188dffb485Schristos 
198dffb485Schristos /* Specification.  */
208dffb485Schristos #include "msvc-inval.h"
218dffb485Schristos 
228dffb485Schristos #if HAVE_MSVC_INVALID_PARAMETER_HANDLER \
238dffb485Schristos     && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING)
248dffb485Schristos 
258dffb485Schristos /* Get _invalid_parameter_handler type and _set_invalid_parameter_handler
268dffb485Schristos    declaration.  */
278dffb485Schristos # include <stdlib.h>
288dffb485Schristos 
298dffb485Schristos # if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING
308dffb485Schristos 
318dffb485Schristos 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)328dffb485Schristos gl_msvc_invalid_parameter_handler (const wchar_t *expression,
338dffb485Schristos                                    const wchar_t *function,
348dffb485Schristos                                    const wchar_t *file,
358dffb485Schristos                                    unsigned int line,
368dffb485Schristos                                    uintptr_t dummy)
378dffb485Schristos {
388dffb485Schristos }
398dffb485Schristos 
408dffb485Schristos # else
418dffb485Schristos 
428dffb485Schristos /* Get declarations of the native Windows API functions.  */
438dffb485Schristos #  define WIN32_LEAN_AND_MEAN
448dffb485Schristos #  include <windows.h>
458dffb485Schristos 
468dffb485Schristos #  if defined _MSC_VER
478dffb485Schristos 
488dffb485Schristos 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)498dffb485Schristos gl_msvc_invalid_parameter_handler (const wchar_t *expression,
508dffb485Schristos                                    const wchar_t *function,
518dffb485Schristos                                    const wchar_t *file,
528dffb485Schristos                                    unsigned int line,
538dffb485Schristos                                    uintptr_t dummy)
548dffb485Schristos {
558dffb485Schristos   RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL);
568dffb485Schristos }
578dffb485Schristos 
588dffb485Schristos #  else
598dffb485Schristos 
608dffb485Schristos /* An index to thread-local storage.  */
618dffb485Schristos static DWORD tls_index;
628dffb485Schristos static int tls_initialized /* = 0 */;
638dffb485Schristos 
648dffb485Schristos /* Used as a fallback only.  */
658dffb485Schristos static struct gl_msvc_inval_per_thread not_per_thread;
668dffb485Schristos 
678dffb485Schristos struct gl_msvc_inval_per_thread *
gl_msvc_inval_current(void)688dffb485Schristos gl_msvc_inval_current (void)
698dffb485Schristos {
708dffb485Schristos   if (!tls_initialized)
718dffb485Schristos     {
728dffb485Schristos       tls_index = TlsAlloc ();
738dffb485Schristos       tls_initialized = 1;
748dffb485Schristos     }
758dffb485Schristos   if (tls_index == TLS_OUT_OF_INDEXES)
768dffb485Schristos     /* TlsAlloc had failed.  */
778dffb485Schristos     return &not_per_thread;
788dffb485Schristos   else
798dffb485Schristos     {
808dffb485Schristos       struct gl_msvc_inval_per_thread *pointer =
818dffb485Schristos         (struct gl_msvc_inval_per_thread *) TlsGetValue (tls_index);
828dffb485Schristos       if (pointer == NULL)
838dffb485Schristos         {
848dffb485Schristos           /* First call.  Allocate a new 'struct gl_msvc_inval_per_thread'.  */
858dffb485Schristos           pointer =
868dffb485Schristos             (struct gl_msvc_inval_per_thread *)
878dffb485Schristos             malloc (sizeof (struct gl_msvc_inval_per_thread));
888dffb485Schristos           if (pointer == NULL)
898dffb485Schristos             /* Could not allocate memory.  Use the global storage.  */
908dffb485Schristos             pointer = &not_per_thread;
918dffb485Schristos           TlsSetValue (tls_index, pointer);
928dffb485Schristos         }
938dffb485Schristos       return pointer;
948dffb485Schristos     }
958dffb485Schristos }
968dffb485Schristos 
978dffb485Schristos 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)988dffb485Schristos gl_msvc_invalid_parameter_handler (const wchar_t *expression,
998dffb485Schristos                                    const wchar_t *function,
1008dffb485Schristos                                    const wchar_t *file,
1018dffb485Schristos                                    unsigned int line,
1028dffb485Schristos                                    uintptr_t dummy)
1038dffb485Schristos {
1048dffb485Schristos   struct gl_msvc_inval_per_thread *current = gl_msvc_inval_current ();
1058dffb485Schristos   if (current->restart_valid)
1068dffb485Schristos     longjmp (current->restart, 1);
1078dffb485Schristos   else
1088dffb485Schristos     /* An invalid parameter notification from outside the gnulib code.
1098dffb485Schristos        Give the caller a chance to intervene.  */
1108dffb485Schristos     RaiseException (STATUS_GNULIB_INVALID_PARAMETER, 0, 0, NULL);
1118dffb485Schristos }
1128dffb485Schristos 
1138dffb485Schristos #  endif
1148dffb485Schristos 
1158dffb485Schristos # endif
1168dffb485Schristos 
1178dffb485Schristos static int gl_msvc_inval_initialized /* = 0 */;
1188dffb485Schristos 
1198dffb485Schristos void
gl_msvc_inval_ensure_handler(void)1208dffb485Schristos gl_msvc_inval_ensure_handler (void)
1218dffb485Schristos {
1228dffb485Schristos   if (gl_msvc_inval_initialized == 0)
1238dffb485Schristos     {
1248dffb485Schristos       _set_invalid_parameter_handler (gl_msvc_invalid_parameter_handler);
1258dffb485Schristos       gl_msvc_inval_initialized = 1;
1268dffb485Schristos     }
1278dffb485Schristos }
1288dffb485Schristos 
1298dffb485Schristos #endif
130