Annotation of embedaddon/libiconv/srclib/msvc-inval.h, revision 1.1.1.1

1.1       misho       1: /* Invalid parameter handler for MSVC runtime libraries.
                      2:    Copyright (C) 2011-2019 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 <https://www.gnu.org/licenses/>.  */
                     16: 
                     17: #ifndef _MSVC_INVAL_H
                     18: #define _MSVC_INVAL_H
                     19: 
                     20: /* With MSVC runtime libraries with the "invalid parameter handler" concept,
                     21:    functions like fprintf(), dup2(), or close() crash when the caller passes
                     22:    an invalid argument.  But POSIX wants error codes (such as EINVAL or EBADF)
                     23:    instead.
                     24:    This file defines macros that turn such an invalid parameter notification
                     25:    into a non-local exit.  An error code can then be produced at the target
                     26:    of this exit.  You can thus write code like
                     27: 
                     28:      TRY_MSVC_INVAL
                     29:        {
                     30:          <Code that can trigger an invalid parameter notification
                     31:           but does not do 'return', 'break', 'continue', nor 'goto'.>
                     32:        }
                     33:      CATCH_MSVC_INVAL
                     34:        {
                     35:          <Code that handles an invalid parameter notification
                     36:           but does not do 'return', 'break', 'continue', nor 'goto'.>
                     37:        }
                     38:      DONE_MSVC_INVAL;
                     39: 
                     40:    This entire block expands to a single statement.
                     41: 
                     42:    The handling of invalid parameters can be done in three ways:
                     43: 
                     44:      * The default way, which is reasonable for programs (not libraries):
                     45:        AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [DEFAULT_HANDLING])
                     46: 
                     47:      * The way for libraries that make "hairy" calls (like close(-1), or
                     48:        fclose(fp) where fileno(fp) is closed, or simply getdtablesize()):
                     49:        AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [HAIRY_LIBRARY_HANDLING])
                     50: 
                     51:      * The way for libraries that make no "hairy" calls:
                     52:        AC_DEFINE([MSVC_INVALID_PARAMETER_HANDLING], [SANE_LIBRARY_HANDLING])
                     53:  */
                     54: 
                     55: #define DEFAULT_HANDLING       0
                     56: #define HAIRY_LIBRARY_HANDLING 1
                     57: #define SANE_LIBRARY_HANDLING  2
                     58: 
                     59: #if HAVE_MSVC_INVALID_PARAMETER_HANDLER \
                     60:     && !(MSVC_INVALID_PARAMETER_HANDLING == SANE_LIBRARY_HANDLING)
                     61: /* A native Windows platform with the "invalid parameter handler" concept,
                     62:    and either DEFAULT_HANDLING or HAIRY_LIBRARY_HANDLING.  */
                     63: 
                     64: # if MSVC_INVALID_PARAMETER_HANDLING == DEFAULT_HANDLING
                     65: /* Default handling.  */
                     66: 
                     67: #  ifdef __cplusplus
                     68: extern "C" {
                     69: #  endif
                     70: 
                     71: /* Ensure that the invalid parameter handler in installed that just returns.
                     72:    Because we assume no other part of the program installs a different
                     73:    invalid parameter handler, this solution is multithread-safe.  */
                     74: extern void gl_msvc_inval_ensure_handler (void);
                     75: 
                     76: #  ifdef __cplusplus
                     77: }
                     78: #  endif
                     79: 
                     80: #  define TRY_MSVC_INVAL \
                     81:      do                                                                        \
                     82:        {                                                                       \
                     83:          gl_msvc_inval_ensure_handler ();                                      \
                     84:          if (1)
                     85: #  define CATCH_MSVC_INVAL \
                     86:          else
                     87: #  define DONE_MSVC_INVAL \
                     88:        }                                                                       \
                     89:      while (0)
                     90: 
                     91: # else
                     92: /* Handling for hairy libraries.  */
                     93: 
                     94: #  include <excpt.h>
                     95: 
                     96: /* Gnulib can define its own status codes, as described in the page
                     97:    "Raising Software Exceptions" on microsoft.com
                     98:    <https://docs.microsoft.com/en-us/cpp/cpp/raising-software-exceptions>.
                     99:    Our status codes are composed of
                    100:      - 0xE0000000, mandatory for all user-defined status codes,
                    101:      - 0x474E550, a API identifier ("GNU"),
                    102:      - 0, 1, 2, ..., used to distinguish different status codes from the
                    103:        same API.  */
                    104: #  define STATUS_GNULIB_INVALID_PARAMETER (0xE0000000 + 0x474E550 + 0)
                    105: 
                    106: #  if defined _MSC_VER
                    107: /* A compiler that supports __try/__except, as described in the page
                    108:    "try-except statement" on microsoft.com
                    109:    <https://docs.microsoft.com/en-us/cpp/cpp/try-except-statement>.
                    110:    With __try/__except, we can use the multithread-safe exception handling.  */
                    111: 
                    112: #   ifdef __cplusplus
                    113: extern "C" {
                    114: #   endif
                    115: 
                    116: /* Ensure that the invalid parameter handler in installed that raises a
                    117:    software exception with code STATUS_GNULIB_INVALID_PARAMETER.
                    118:    Because we assume no other part of the program installs a different
                    119:    invalid parameter handler, this solution is multithread-safe.  */
                    120: extern void gl_msvc_inval_ensure_handler (void);
                    121: 
                    122: #   ifdef __cplusplus
                    123: }
                    124: #   endif
                    125: 
                    126: #   define TRY_MSVC_INVAL \
                    127:       do                                                                       \
                    128:         {                                                                      \
                    129:           gl_msvc_inval_ensure_handler ();                                     \
                    130:           __try
                    131: #   define CATCH_MSVC_INVAL \
                    132:           __except (GetExceptionCode () == STATUS_GNULIB_INVALID_PARAMETER     \
                    133:                     ? EXCEPTION_EXECUTE_HANDLER                                \
                    134:                     : EXCEPTION_CONTINUE_SEARCH)
                    135: #   define DONE_MSVC_INVAL \
                    136:         }                                                                      \
                    137:       while (0)
                    138: 
                    139: #  else
                    140: /* Any compiler.
                    141:    We can only use setjmp/longjmp.  */
                    142: 
                    143: #   include <setjmp.h>
                    144: 
                    145: #   ifdef __cplusplus
                    146: extern "C" {
                    147: #   endif
                    148: 
                    149: struct gl_msvc_inval_per_thread
                    150: {
                    151:   /* The restart that will resume execution at the code between
                    152:      CATCH_MSVC_INVAL and DONE_MSVC_INVAL.  It is enabled only between
                    153:      TRY_MSVC_INVAL and CATCH_MSVC_INVAL.  */
                    154:   jmp_buf restart;
                    155: 
                    156:   /* Tells whether the contents of restart is valid.  */
                    157:   int restart_valid;
                    158: };
                    159: 
                    160: /* Ensure that the invalid parameter handler in installed that passes
                    161:    control to the gl_msvc_inval_restart if it is valid, or raises a
                    162:    software exception with code STATUS_GNULIB_INVALID_PARAMETER otherwise.
                    163:    Because we assume no other part of the program installs a different
                    164:    invalid parameter handler, this solution is multithread-safe.  */
                    165: extern void gl_msvc_inval_ensure_handler (void);
                    166: 
                    167: /* Return a pointer to the per-thread data for the current thread.  */
                    168: extern struct gl_msvc_inval_per_thread *gl_msvc_inval_current (void);
                    169: 
                    170: #   ifdef __cplusplus
                    171: }
                    172: #   endif
                    173: 
                    174: #   define TRY_MSVC_INVAL \
                    175:       do                                                                       \
                    176:         {                                                                      \
                    177:           struct gl_msvc_inval_per_thread *msvc_inval_current;                 \
                    178:           gl_msvc_inval_ensure_handler ();                                     \
                    179:           msvc_inval_current = gl_msvc_inval_current ();                       \
                    180:           /* First, initialize gl_msvc_inval_restart.  */                      \
                    181:           if (setjmp (msvc_inval_current->restart) == 0)                       \
                    182:             {                                                                  \
                    183:               /* Then, mark it as valid.  */                                   \
                    184:               msvc_inval_current->restart_valid = 1;
                    185: #   define CATCH_MSVC_INVAL \
                    186:               /* Execution completed.                                          \
                    187:                  Mark gl_msvc_inval_restart as invalid.  */                    \
                    188:               msvc_inval_current->restart_valid = 0;                           \
                    189:             }                                                                  \
                    190:           else                                                                 \
                    191:             {                                                                  \
                    192:               /* Execution triggered an invalid parameter notification.        \
                    193:                  Mark gl_msvc_inval_restart as invalid.  */                    \
                    194:               msvc_inval_current->restart_valid = 0;
                    195: #   define DONE_MSVC_INVAL \
                    196:             }                                                                  \
                    197:         }                                                                      \
                    198:       while (0)
                    199: 
                    200: #  endif
                    201: 
                    202: # endif
                    203: 
                    204: #else
                    205: /* A platform that does not need to the invalid parameter handler,
                    206:    or when SANE_LIBRARY_HANDLING is desired.  */
                    207: 
                    208: /* The braces here avoid GCC warnings like
                    209:    "warning: suggest explicit braces to avoid ambiguous 'else'".  */
                    210: # define TRY_MSVC_INVAL \
                    211:     do                                                                         \
                    212:       {                                                                        \
                    213:         if (1)
                    214: # define CATCH_MSVC_INVAL \
                    215:         else
                    216: # define DONE_MSVC_INVAL \
                    217:       }                                                                        \
                    218:     while (0)
                    219: 
                    220: #endif
                    221: 
                    222: #endif /* _MSVC_INVAL_H */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>