source: branches/branch-1-0/include/helpers/except.h@ 473

Last change on this file since 473 was 431, checked in by rlwalsh, 8 years ago

exception handler: update exception report to show function that set
the handler; optionally, print a debug message with up to 4 arguments

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 12.6 KB
Line 
1
2/*
3 *@@sourcefile except.h:
4 * header file for except.c. See remarks there.
5 *
6 * Note: Version numbering in this file relates to XWorkplace version
7 * numbering.
8 *
9 *@@include #define INCL_DOSEXCEPTIONS
10 *@@include #define INCL_DOSPROCESS
11 *@@include #include <os2.h>
12 *@@include #include <stdio.h>
13 *@@include #include <setjmp.h>
14 *@@include #include "helpers\except.h"
15 */
16
17/*
18 * Copyright (C) 1999-2000 Ulrich M”ller.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation, in version 2 as it comes in the COPYING
22 * file of the XFolder main distribution.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 */
28
29#if __cplusplus
30extern "C" {
31#endif
32
33#ifndef EXCEPT_HEADER_INCLUDED
34 #define EXCEPT_HEADER_INCLUDED
35
36 #if defined __IBMCPP__ || defined __IBMC__
37 #ifndef INCL_DOSEXCEPTIONS
38 #error except.h requires INCL_DOSEXCEPTIONS to be defined.
39 #endif
40 #ifndef INCL_DOSPROCESS
41 #error except.h requires INCL_DOSPROCESS to be defined.
42 #endif
43
44 #ifndef __stdio_h
45 #error except.h requires stdio.h to be included.
46 #endif
47 #ifndef __setjmp_h
48 #error except.h requires setjmp.h to be included.
49 #endif
50 #endif
51
52 /********************************************************************
53 *
54 * Declarations
55 *
56 ********************************************************************/
57
58 // forward declaration
59 typedef struct _EXCEPTIONREGISTRATIONRECORD2 *PEXCEPTIONREGISTRATIONRECORD2;
60
61 // "OnKill" function prototype for EXCEPTIONREGISTRATIONRECORD2
62 // added V0.9.0 (99-10-22) [umoeller]
63 // removed V0.9.7 (2000-12-08) [umoeller]
64 // typedef VOID APIENTRY FNEXCONKILL(PEXCEPTIONREGISTRATIONRECORD2);
65 // typedef FNEXCONKILL *PFNEXCONKILL;
66
67 /*
68 *@@ EXCEPTIONREGISTRATIONRECORD2:
69 * replacement EXCEPTIONREGISTRATIONRECORD
70 * struct for thread exception handling.
71 *
72 * Note: code within a TRY{}CATCH block can change
73 * pszFmt and ulArgX whenever needed to help identify
74 * the cause of an exception
75 */
76
77 typedef struct _EXCEPTIONREGISTRATIONRECORD2
78 {
79 PVOID pNext; // as in EXCEPTIONREGISTRATIONRECORD
80 PFN pfnHandler; // as in EXCEPTIONREGISTRATIONRECORD
81 jmp_buf jmpThread; // additional buffer for setjmp
82 EXCEPTIONREPORTRECORD err; // exception handlers copy the report rec here
83 PVOID pvUser; // user ptr - set to &pszSetBy by TRY_V2
84 PSZ pszSetBy; // the file & function that set the handler
85 PSZ pszFmt; // format string for fprintf() - can be null
86 ULONG ulArg1; // arg1 for pszFmt
87 ULONG ulArg2; // arg2 for pszFmt
88 ULONG ulArg3; // arg3 for pszFmt
89 ULONG ulArg4; // arg4 for pszFmt
90 } EXCEPTIONREGISTRATIONRECORD2;
91
92 /*
93 *@@ EXCEPTSTRUCT:
94 * structure used with TRY_xxx macros.
95 */
96
97 typedef struct _EXCEPTSTRUCT
98 {
99 EXCEPTIONREGISTRATIONRECORD2 RegRec2;
100 ULONG ulExcpt; // != NULL if exception caught
101 APIRET arc; // rc of DosSetExceptionHandler
102 } EXCEPTSTRUCT, *PEXCEPTSTRUCT;
103
104 // function prototypes for exception hooks (V0.9.0)
105
106 // "open traplog file" hook
107 typedef FILE* APIENTRY FNEXCOPENFILE(VOID);
108 typedef FNEXCOPENFILE *PFNEXCOPENFILE;
109
110 // "exception" hook
111 typedef VOID APIENTRY FNEXCHOOK(FILE*, PTIB, ULONG); // V0.9.16 (2001-12-02) [pr]
112 typedef FNEXCHOOK *PFNEXCHOOK;
113
114 // "error" hook
115 typedef VOID APIENTRY FNEXCHOOKERROR(const char *pcszFile,
116 ULONG ulLine,
117 const char *pcszFunction,
118 APIRET arc);
119 typedef FNEXCHOOKERROR *PFNEXCHOOKERROR;
120
121 /********************************************************************
122 *
123 * Prototypes
124 *
125 ********************************************************************/
126
127 VOID _Optlink excExplainException(FILE *file,
128 PSZ pszHandlerName,
129 PEXCEPTIONREPORTRECORD pReportRec,
130 PCONTEXTRECORD pContextRec);
131
132 VOID _Optlink excExplainException2(FILE *file,
133 PSZ pszHandlerName,
134 PEXCEPTIONREPORTRECORD pReportRec,
135 PCONTEXTRECORD pContextRec,
136 PEXCEPTIONREGISTRATIONRECORD2 pRegRec2);
137
138 VOID excRegisterHooks(PFNEXCOPENFILE pfnExcOpenFileNew,
139 PFNEXCHOOK pfnExcHookNew,
140 PFNEXCHOOKERROR pfnExcHookError,
141 BOOL fBeepOnExceptionNew);
142
143 ULONG _System excHandlerLoud(PEXCEPTIONREPORTRECORD pReportRec,
144 PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
145 PCONTEXTRECORD pContextRec,
146 PVOID pv);
147
148 ULONG _System excHandlerQuiet(PEXCEPTIONREPORTRECORD pReportRec,
149 PEXCEPTIONREGISTRATIONRECORD2 pRegRec2,
150 PCONTEXTRECORD pContextRec,
151 PVOID pv);
152
153 extern PFNEXCHOOKERROR G_pfnExcHookError;
154
155 extern ULONG G_ulExplainExceptionRunning;
156
157 /********************************************************************
158 *
159 * Macros
160 *
161 ********************************************************************/
162
163 /* See except.c for explanations how to use these. */
164
165 #ifdef __NO_EXCEPTION_HANDLERS__
166 // exception handlers can completely be disabled
167 #define TRY_LOUD6(excptstruct, fmt, arg1, arg2, arg3, arg4)
168 #define TRY_LOUD(excptstruct)
169 #define FMT_WNDPROC
170 #else
171 // avoid problems if header and source are different versions
172 #define TRY_V2 1
173
174 #ifdef __NO_LOUD_EXCEPTION_HANDLERS__
175 #define TRY_LOUD6 TRY_QUIET6
176 #else // __NO_LOUD_EXCEPTION_HANDLERS__
177 #define TRY_LOUD6(excptstruct, fmt, arg1, arg2, arg3, arg4) \
178 { \
179 EXCEPTSTRUCT excptstruct = {0}; \
180 excptstruct.RegRec2.pfnHandler = (PFN)excHandlerLoud; \
181 excptstruct.RegRec2.pvUser = &excptstruct.RegRec2.pszSetBy; \
182 excptstruct.RegRec2.pszSetBy = __FILE__##"::"##__FUNCTION__##"()"; \
183 excptstruct.RegRec2.pszFmt = fmt; \
184 excptstruct.RegRec2.ulArg1 = (ULONG)arg1; \
185 excptstruct.RegRec2.ulArg2 = (ULONG)arg2; \
186 excptstruct.RegRec2.ulArg3 = (ULONG)arg3; \
187 excptstruct.RegRec2.ulArg4 = (ULONG)arg4; \
188 excptstruct.arc = DosSetExceptionHandler( \
189 (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \
190 if (excptstruct.arc) \
191 if (G_pfnExcHookError) \
192 G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, excptstruct.arc); \
193 else \
194 DosBeep(1000, 1000); \
195 excptstruct.ulExcpt = setjmp(excptstruct.RegRec2.jmpThread); \
196 if (excptstruct.ulExcpt == 0) \
197 {
198
199 #endif // __NO_LOUD_EXCEPTION_HANDLERS__
200
201 #define TRY_LOUD(excptstruct) \
202 TRY_LOUD6(excptstruct, 0, 0, 0, 0, 0)
203
204 #define TRY_LOUD2(excptstruct, fmt) \
205 TRY_LOUD6(excptstruct, fmt, 0, 0, 0, 0)
206
207 #define TRY_LOUD3(excptstruct, fmt, arg1) \
208 TRY_LOUD6(excptstruct, fmt, arg1, 0, 0, 0)
209
210 #define TRY_LOUD4(excptstruct, fmt, arg1, arg2) \
211 TRY_LOUD6(excptstruct, fmt, arg1, arg2, 0, 0)
212
213 #define TRY_LOUD5(excptstruct, fmt, arg1, arg2, arg3) \
214 TRY_LOUD6(excptstruct, fmt, arg1, arg2, arg3, 0)
215
216 #define TRY_WNDPROC_FMT "hwnd= %08x msg= %04x mp1= %08x mp2= %08x\n"
217
218 #define TRY_WNDPROC(excptstruct, hwd) \
219 TRY_LOUD6(excptstruct, TRY_WNDPROC_FMT, hwd, msg, mp1, mp2)
220
221 #endif
222
223 #ifdef __NO_EXCEPTION_HANDLERS__
224 // exception handlers can completely be disabled
225 #define TRY_QUIET6(excptstruct, fmt, arg1, arg2, arg3, arg4)
226 #define TRY_QUIET(excptstruct)
227 #else
228 #define TRY_QUIET6(excptstruct, fmt, arg1, arg2, arg3, arg4) \
229 { \
230 EXCEPTSTRUCT excptstruct = {0}; \
231 excptstruct.RegRec2.pfnHandler = (PFN)excHandlerQuiet; \
232 excptstruct.RegRec2.pvUser = &excptstruct.RegRec2.pszSetBy; \
233 excptstruct.RegRec2.pszSetBy = __FILE__##"::"##__FUNCTION__##"()"; \
234 excptstruct.RegRec2.pszFmt = fmt; \
235 excptstruct.RegRec2.ulArg1 = arg1; \
236 excptstruct.RegRec2.ulArg2 = arg2; \
237 excptstruct.RegRec2.ulArg3 = arg3; \
238 excptstruct.RegRec2.ulArg4 = arg4; \
239 excptstruct.arc = DosSetExceptionHandler( \
240 (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \
241 if (excptstruct.arc) \
242 if (G_pfnExcHookError) \
243 G_pfnExcHookError(__FILE__, __LINE__, __FUNCTION__, excptstruct.arc); \
244 else \
245 DosBeep(1000, 1000); \
246 excptstruct.ulExcpt = setjmp(excptstruct.RegRec2.jmpThread); \
247 if (excptstruct.ulExcpt == 0) \
248 {
249
250 #define TRY_QUIET(excptstruct) \
251 TRY_QUIET6(excptstruct, 0, 0, 0, 0, 0)
252
253 #endif
254
255 #ifdef __NO_EXCEPTION_HANDLERS__
256 // exception handlers can completely be disabled
257 #define CATCH(excptstruct) if (FALSE) {
258 #else
259 #define CATCH(excptstruct) \
260 DosUnsetExceptionHandler( \
261 (PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2)); \
262 } /* end of TRY block */ \
263 else \
264 { /* exception occurred: */ \
265 DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)&(excptstruct.RegRec2));
266 #endif
267
268 #ifdef __NO_EXCEPTION_HANDLERS__
269 // exception handlers can completely be disabled
270 #define END_CATCH() }
271 #else
272 #define END_CATCH() \
273 } /* end of exception-occurred block */ \
274 }
275 #endif
276
277 /*
278 * CRASH:
279 * this macro is helpful for testing
280 * the exception handlers.
281 * This is not for general use. ;-)
282 */
283
284 #define CRASH {PSZ p = NULL; *p = 'a'; }
285
286#endif // EXCEPT_HEADER_INCLUDED
287
288#if __cplusplus
289}
290#endif
291
Note: See TracBrowser for help on using the repository browser.