Annotation of embedaddon/libiconv/srclib/msvc-inval.h, revision 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>