~ubuntu-branches/ubuntu/vivid/gzip/vivid

« back to all changes in this revision

Viewing changes to lib/msvc-inval.h

  • Committer: Steve Langasek
  • Date: 2012-06-29 02:07:40 UTC
  • mfrom: (4.1.9 sid)
  • Revision ID: steve.langasek@canonical.com-20120629020740-qqikrblzana08v2y
Merge version 1.5-1.1 from Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Invalid parameter handler for MSVC runtime libraries.
 
2
   Copyright (C) 2011-2012 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
#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
   <http://msdn.microsoft.com/en-us/library/het71c37.aspx>.
 
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
   <http://msdn.microsoft.com/en-us/library/s58ftw19.aspx>.
 
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 */