source: trunk/dll/error.c@ 736

Last change on this file since 736 was 689, checked in by Steven Levine, 18 years ago

Commit OpenWatcom compatibility updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: error.c 689 2007-06-15 06:33:24Z stevenhl $
5
6 Error reporting
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2004, 2007 Steven H. Levine
10
11 12 Aug 04 SHL Comments
12 23 May 05 SHL Move saymsg here
13 24 May 05 SHL Rename General_Error to more accurate Win_Error
14 24 May 05 SHL Rename saymsg to more accurate Misc_Error
15 24 May 05 SHL Rework Win_Error args and clean up logic
16 27 May 05 SHL Rework to use common showMsg
17 14 Aug 05 SHL showMsg: suppress write to stdout if not error message
18 13 Jul 06 SHL Add Runtime_Error
19 22 Jul 06 SHL Optimize calling sequences
20 26 Jul 06 SHL Add ..._Error2
21 16 Aug 06 SHL Tweak message formatting
22 07 Jan 07 GKY Move error strings etc. to string file
23 18 Apr 07 SHL showMsg: correct selective logging checks
24 19 Apr 07 SHL Add DbgMsg
25 20 Apr 07 SHL Correct IDS_GENERR1TEXT formatting
26 23 Apr 07 SHL Add Win_Error_NoMsgBox. Rework others
27
28***********************************************************************/
29
30#define INCL_DOS
31#define INCL_DOSERRORS
32#define INCL_WIN
33
34#include <os2.h>
35#include <stdlib.h>
36#include <stdio.h>
37#include <string.h>
38#include <stdarg.h>
39
40#include "fm3dll.h"
41#include "fm3str.h"
42
43#pragma data_seg(DATA1)
44#pragma alloc_text(FMINPUT,Win_Error,Dos_Error,saymsg,showMsg)
45
46static VOID formatWinError(PSZ pszBuf, UINT cBufBytes, HWND hwndErr, HWND hwndOwner,
47 PCSZ pszSrcFile, UINT uSrcLineNo,
48 PCSZ pszFmt, va_list pva);
49
50static APIRET showMsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog);
51
52//=== DbgMsg: output debug message stderr ===
53
54VOID DbgMsg(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
55{
56 va_list va;
57
58 // OK for source file name to be null
59 fprintf(stderr, "%s %u", pszSrcFile ? pszSrcFile : "n/a", uSrcLineNo);
60 // If format null want just file and line
61 if (pszFmt) {
62 fputc(' ', stderr);
63 va_start(va, pszFmt);
64 vfprintf(stderr, pszFmt, va);
65 va_end(va);
66 }
67 fputc('\n', stderr);
68 fflush(stderr);
69
70} // DbgMsg
71
72//== Dos_Error: report Dos...() error using passed message string ===
73
74INT Dos_Error(ULONG mb_type, ULONG ulRC, HWND hwndOwner,
75 PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
76{
77 CHAR szMsg[4096];
78 ULONG Class; // Error class
79 ULONG action; // Error action
80 ULONG Locus; // Error location
81 ULONG ulMsgLen;
82 CHAR *pszMsgStart;
83 CHAR *psz;
84 va_list va;
85
86 if (!ulRC)
87 return MBID_ENTER; // Should not have been called
88
89 // Format caller's message
90 va_start(va, pszFmt);
91 szMsg[sizeof(szMsg) - 1] = 0;
92 vsprintf(szMsg, pszFmt, va);
93 va_end(va);
94
95 if (szMsg[sizeof(szMsg) - 1]) {
96 fprintf(stderr, "Buffer overflow in Dos_Error - need %u bytes\n", strlen(szMsg) + 1);
97 fflush(stderr);
98 }
99
100 if (strchr(szMsg, ' ') == NULL)
101 strcat(szMsg, " failed"); // Assume simple function name
102
103 DosErrClass(ulRC, &Class, &action, &Locus);
104
105 sprintf(szMsg + strlen(szMsg),
106 GetPString(IDS_DOSERR1TEXT),
107 pszSrcFile,
108 uSrcLineNo,
109 ulRC,
110 GetPString(IDS_ERRCLASS1TEXT + (Class - 1)),
111 GetPString(IDS_ERRACTION1TEXT + (action - 1)),
112 GetPString(IDS_ERRLOCUS1TEXT + (Locus - 1)));
113 pszMsgStart = szMsg + strlen(szMsg) + 1;
114 // Get message leaving space for NL separator
115 if (!DosGetMessage
116 (NULL, 0L, (PCHAR) pszMsgStart + 1, 1024, ulRC, "OSO001.MSG", &ulMsgLen)
117 || !DosGetMessage(NULL, 0L, (PCHAR) pszMsgStart + 1, 1024, ulRC,
118 "OSO001H.MSG", &ulMsgLen)) {
119 // Got message
120 pszMsgStart[ulMsgLen + 1] = 0; // Terminate
121 *(pszMsgStart - 1) = '\n'; // Stuff NL before message text
122 *pszMsgStart = '\"'; // Prefix message text with quote
123
124 psz = pszMsgStart + ulMsgLen; // Point at last char
125 // Chop trailing NL CR TAB
126 while (*psz &&
127 (*psz == '\r' || *psz == '\n' || *psz == ' ' || *psz == '\t')) {
128 *psz-- = 0;
129 }
130 strcat(psz, "\""); // Append trailing quote
131
132 // Convert CR and NL combos to single space
133 psz = pszMsgStart;
134 while (*psz) {
135 if (*psz == '\n' || *psz == '\r') {
136 while (*(psz + 1) == '\n' || *(psz + 1) == '\r')
137 memmove(psz, psz + 1, strlen(psz));
138 *psz = ' ';
139 }
140 else
141 psz++;
142 }
143 }
144
145 return showMsg(mb_type | MB_ICONEXCLAMATION, hwndOwner, GetPString(IDS_DOSERR2TEXT),
146 szMsg, TRUE);
147
148} // Dos_Error
149
150//== Dos_Error2: report Dos...() error using passed message id ===
151
152INT Dos_Error2(ULONG mb_type, ULONG ulRC, HWND hwndOwner,
153 PCSZ pszSrcFile, UINT uSrcLineNo, UINT idMsg)
154{
155 return Dos_Error(mb_type, ulRC, hwndOwner, pszSrcFile, uSrcLineNo,
156 GetPString(idMsg));
157} // Dos_Error2
158
159/**
160 * Format last PM error into passed buffer
161 */
162
163static VOID formatWinError(PSZ pszBuf, UINT cBufBytes,
164 HWND hwndErr, HWND hwndOwner,
165 PCSZ pszSrcFile, UINT uSrcLineNo,
166 PCSZ pszFmt, va_list pva)
167{
168 PERRINFO pErrInfoBlk; /* Pointer to ERRINFO structure filled
169 by WinGetErrorInfo */
170 PSZ pszOffset; /* Pointer to current error message returned
171 by WinGetErrorInfo */
172 PSZ psz;
173 HAB hab;
174
175 if (hwndErr == NULLHANDLE)
176 hab = (HAB)0;
177 else
178 hab = WinQueryAnchorBlock(hwndErr);
179
180 // Format callers message
181 pszBuf[cBufBytes - 1] = 0;
182 vsprintf(pszBuf, pszFmt, pva);
183
184 if (pszBuf[cBufBytes - 1]) {
185 fprintf(stderr, "Buffer overflow in formatWinError - need %u bytes\n", strlen(pszBuf) + 1);
186 fflush(stderr);
187 }
188
189 if (strchr(pszBuf, ' ') == NULL)
190 strcat(pszBuf, " failed"); // Assume simple function name
191
192 // Append file name and line number and trailing space
193 sprintf(pszBuf + strlen(pszBuf),
194 GetPString(IDS_GENERR1TEXT), pszSrcFile, uSrcLineNo);
195
196 // Get last PM error for the current thread
197 pErrInfoBlk = WinGetErrorInfo(hab);
198 if (!pErrInfoBlk) {
199 psz = pszBuf + strlen(pszBuf);
200 strcpy(psz, "WinGetErrorInfo failed");
201 }
202 else {
203 if (!hwndOwner)
204 hwndOwner = HWND_DESKTOP;
205 /* Find message offset in array of message offsets
206 Assume 1 message - fixme?
207 */
208 pszOffset = ((PSZ) pErrInfoBlk) + pErrInfoBlk->offaoffszMsg;
209 /* Address error message in array of messages and
210 append error message to source code linenumber
211 */
212 psz = pszBuf + strlen(pszBuf);
213 sprintf(psz, "#0x%04x \"", ERRORIDERROR(pErrInfoBlk->idError));
214 psz += strlen(psz);
215 strcpy(psz, ((PSZ) pErrInfoBlk) + *(PSHORT) pszOffset);
216 psz += strlen(psz);
217 // Chop trailing mush
218 psz--;
219 while (*psz == '\r' || *psz == '\n' || *psz == ' ')
220 *psz-- = 0;
221 if (*psz)
222 psz++;
223 strcpy(psz, "\"");
224 WinFreeErrorInfo(pErrInfoBlk); // Free resource segment
225 }
226
227} // formatWinError
228
229//== Runtime_Error: report runtime library error using passed message string ===
230
231VOID Runtime_Error(PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
232{
233 CHAR szMsg[4096];
234 va_list va;
235
236 // Format caller's message
237 va_start(va, pszFmt);
238 szMsg[sizeof(szMsg) - 1] = 0;
239 vsprintf(szMsg, pszFmt, va);
240 va_end(va);
241
242 if (szMsg[sizeof(szMsg) - 1]) {
243 fprintf(stderr, "Buffer overflow in Runtime_Error - need %u bytes\n", strlen(szMsg) + 1);
244 fflush(stderr);
245 }
246
247 if (strchr(szMsg, ' ') == NULL)
248 strcat(szMsg, " failed"); // Assume simple function name
249
250 sprintf(szMsg + strlen(szMsg),
251 GetPString(IDS_GENERR1TEXT), pszSrcFile, uSrcLineNo);
252
253 showMsg(MB_ICONEXCLAMATION, HWND_DESKTOP, DEBUG_STRING, szMsg, TRUE);
254
255} // Runtime_Error
256
257//== Runtime_Error2: report runtime library error using passed message id ===
258
259VOID Runtime_Error2(PCSZ pszSrcFile, UINT uSrcLineNo, UINT idMsg)
260{
261 Runtime_Error(pszSrcFile, uSrcLineNo, GetPString(idMsg));
262
263} // Runtime_Error2
264
265// fixme to be rename to Misc_Error
266
267//=== saymsg: report misc error using passed message ===
268
269APIRET saymsg(ULONG mb_type, HWND hwnd, PCSZ pszTitle, PCSZ pszFmt, ...)
270{
271 CHAR szMsg[4096];
272 va_list va;
273
274 va_start(va, pszFmt);
275 szMsg[sizeof(szMsg) - 1] = 0;
276 vsprintf(szMsg, pszFmt, va);
277 va_end(va);
278
279 if (szMsg[sizeof(szMsg) - 1]) {
280 fprintf(stderr, "Buffer overflow in saymsg - need %u bytes\n", strlen(szMsg) + 1);
281 fflush(stderr);
282 }
283
284 return showMsg(mb_type, hwnd, pszTitle, szMsg, FALSE);
285
286} // saymsg
287
288//=== showMsg: display error popup ===
289
290static APIRET showMsg(ULONG mb_type, HWND hwndOwner,
291 PCSZ pszTitle, PCSZ pszMsg, BOOL wantLog)
292{
293 if (wantLog) {
294 fputs(pszMsg, stderr);
295 fputc('\n', stderr);
296 fputc('\n', stderr);
297 fflush(stderr);
298 }
299
300 if (!hwndOwner)
301 hwndOwner = HWND_DESKTOP;
302
303 DosBeep(250, 100);
304
305 return WinMessageBox(HWND_DESKTOP, // Parent
306 hwndOwner,
307 (PSZ) pszMsg, (PSZ) pszTitle, 0, // help id
308 mb_type | MB_MOVEABLE);
309} // showMsg
310
311//== Win_Error: report Win...() error using passed message string ===
312
313VOID Win_Error(HWND hwndErr, HWND hwndOwner,
314 PCSZ pszSrcFile, UINT uSrcLineNo,
315 PCSZ pszFmt, ...)
316{
317 CHAR szMsg[4096];
318 va_list va;
319
320 // Format callers message
321 va_start(va, pszFmt);
322 formatWinError(szMsg, sizeof(szMsg), hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, pszFmt, va);
323 va_end(va);
324
325 showMsg(MB_ENTER | MB_ICONEXCLAMATION, hwndOwner, GetPString(IDS_GENERR2TEXT),
326 szMsg, TRUE);
327
328} // Win_Error
329
330//== Win_Error2: report Win...() error using passed message id ===
331
332VOID Win_Error2(HWND hwndErr, HWND hwndOwner,
333 PCSZ pszSrcFile, UINT uSrcLineNo, UINT idMsg)
334{
335 Win_Error(hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, GetPString(idMsg));
336
337} // Win_Error2
338
339/**
340 * Output PM error messsage to stderr
341 * This does to same reporting as Win_Error, but bypasses the
342 * message box popup.
343 * Use this version when the popup would hang PM.
344 */
345
346VOID Win_Error_NoMsgBox(HWND hwndErr, HWND hwndOwner,
347 PCSZ pszSrcFile, UINT uSrcLineNo, PCSZ pszFmt, ...)
348{
349 CHAR szMsg[4096];
350 va_list va;
351
352 // Format callers message
353 va_start(va, pszFmt);
354 formatWinError(szMsg, sizeof(szMsg), hwndErr, hwndOwner, pszSrcFile, uSrcLineNo, pszFmt, va);
355 va_end(va);
356
357 fputs(szMsg, stderr);
358 fputc('\n', stderr);
359 fputc('\n', stderr);
360 fflush(stderr);
361
362 DosBeep(250, 100);
363
364} // Win_Error_NoMsgBox
Note: See TracBrowser for help on using the repository browser.