source: trunk/dll/error.c@ 787

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

Rework UM_FILLSETUPLIST IDM_SAVEDIRCNRSTATE and ..._setups() logic for ticket# 109 and #31
Add GetMSecTimer()
Use GetMSecTimer in DbgMsg
Tweak notebook.ipf scanning page
Move more #pragma alloc_text statements to end of files for OpenWatcom
Delete obsoletes
Revert ExpandAll() ShowTreeRec() DosSleeps to 0 - DosSleep(1) was slowing down inner loops
Drop afFilesToGet - use FilesToGet directly
Optimze ShowTreeRec() collapse logic - was really slow

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