Category : OS/2 Files
Archive   : ERRABORT.ZIP
Filename : ERRABORT.C

 
Output of file : ERRABORT.C contained in archive : ERRABORT.ZIP
/* errabort.c - A debugging tool for OS/2 programmers.
*
* This DLL is to be called after first calling any OS/2 function and
* testing for expected return codes. "Testing for expected return
* codes" means, for example, testing for zero (successful completion)
* IN EVERY CASE, and testing for errors that your program anticipates
* and has code to handle, such as "File not found" when calling
* 'DosOpen ()'.
*
* Any other error return presumably is one that your program did not
* anticipate and cannot properly handle. In that case, a call to this
* DLL will result in the display of an error message, and a termination
* of your program. The error message includes your program's name,
* the name of the function within your program that made the call to an
* OS/2 function, the line number where the call to this program originated
* (which should be the line immediately following the call to the OS/2
* function that returned an unexpected error code), the name of the OS/2
* function being called, the number of the error code, and a message
* associated with the error code.
*
* If you are not presently testing EVERY OS/2 function call's return
* value, then you may be surprised by some of the error messages (and
* program aborts) that calls to this program will give you. I have
* found return codes that are not documented as being among those
* returned by certain functions, for example. In other cases, return
* codes that I anticipated (such as 'ERROR_FILE_NOT_FOUND' and
* 'ERROR_PATH_NOT_FOUND' from 'DosFindFirst ()') were NOT returned;
* instead I got 'ERROR_NO_MORE_FILES' (it surprised me; maybe it
* wouldn't surprise you). Since this program is a DLL, it is certainly
* cheap enough to include a call to it after every OS/2 call, at least
* during debugging. I modify the ERRCHK macro (included as part of this
* package) to conditionally generate code depending on the state of a
* global debugging flag, which makes it easy to remove even the calls.
*
* This program with all its associated materials is explicitly placed into
* the public domain. Feel free to use it, modify it, or incorporate it
* into your own programs, whether for your own use or for sale; in short,
* enjoy. And if you have something of your own that is useful but was
* tedious to produce, share it with the rest of us.
*
* If you have questions or comments about this program, I am:
*
* Author: Wayne Kovsky BIX: wkovsky
* Pinnacle Software CompuServe: 76164,3504
* 299 Village Street
* Millis, MA 02054
*/

#define INCL_DOS

#include
#include
/* The '#include os2local.h' statement gets these items included in
* your program, in case you did not get that file when you got this
* program. Your programs that CALL 'errabort ()' will need the first
* two items as well.
*
* extern void EXPENTRY errabort (PSZ pszProgramName, PSZ pszFunctionName,
* PSZ pszCallerName, USHORT usLineNum, USHORT usReturn) ;
*
* #define ERRCHK(os2name) if (usRC != 0) { \
* errabort (pszProgramName, #os2name, pszFunctionName, __LINE__, usRC) ; \
* }
*
*
* #define STDIN 0
* #define STDOUT 1
* #define STDERR 2
*/

/* Since this is destined to be a DLL, we must provide our own versions
* of C library functions 'strlen ()' and 'itoa ()'.
*/
static USHORT FAR PASCAL mystrlen (PSZ pszString) ;
static void FAR PASCAL myitoa (USHORT usNumber, PSZ pszMessage) ;

int _acrtused = 0 ; /* Prevent C startup code being included. */

/* What follows is the error text for every documented error code I could
* find. It is a LOT of text, and it accounts for the majority of the
* bulk the finished DLL contains; there is very little executable code.
* It is for precisely this reason that this is a DLL: every program you
* are working on can use this single copy of all this bulk, and let OS/2
* manage the memory requirements.
*
* Most of these messages originated in the "BSEERR.H" file that is
* in "OS2TOOLS\INCLUDE" as part of the Microsoft OS/2
* Programmer's Toolkit. That include file has all error messages
* in terse upper case for use in C programs; I converted them to
* these more descriptive messages. In addition, there were a few
* duplicates (i.e., two different "#define" names for the same
* error code); in those cases I (arbitrarily) selected one and
* discarded the other.
*
* Some errors not documented in the "BSEERR.H" file were found in
* Ray Duncan's book "Advanced OS/2 Programming", first edition,
* published by Microsoft Press, 1989, ISBN 1-55615-045-8, in
* Appendix A, pp. 697-706. I requested and received Mr. Duncan's
* permission to include those here.
*
* Note that many error messages are simply "RESERVED". I have attempted
* to conserve space by leaving "holes" in this table of error messages
* wherever these "RESERVED" error numbers occur. This means we cannot
* use the error number as an index into this table, but instead must
* search the table for a match. Since this is an "Oh my God, something
* horrible must have happened!" kind of program, I have followed my
* long-standing rule to keep it as bulletproof as possible; thus, I have
* not even so much as done a binary search here. For a program that
* does so little and then kills your process, it seemed to me that
* performance was not much of an issue ... your mileage may vary.
*/
static struct ErrorList {
USHORT usErrorNum ;
PSZ pszErrorText ;
} ErrorArray [] = {
0, "No error", /* Note that this still ends in abort! */
1, "Invalid function number",
2, "File not found",
3, "Path not found",
4, "Too many open files",
5, "Access denied",
6, "Invalid handle",
7, "Memory control blocks destroyed",
8, "Not enough memory",
9, "Invalid memory block address",
10, "Invalid environment",
11, "Invalid format",
12, "Invalid access code",
13, "Invalid data",
14, "Unknown unit", /* From Duncan - but see error 20. */
15, "Invalid disk drive",
16, "Cannot remove current directory",
17, "Not same device",
18, "No more files",
19, "Disk write-protected",
20, "Invalid unit", /* From BSEERR.H - but see error 14. */
21, "Drive not ready",
22, "Unknown command",
23, "Data error (CRC)",
24, "Bad request structure length",
25, "Seek error",
26, "Not DOS disk",
27, "Sector not found",
28, "Printer out of paper",
29, "Write fault",
30, "Read fault",
31, "General failure",
32, "Sharing violation",
33, "Lock violation",
34, "Invalid disk change",
35, "FCB unavailable",
36, "Sharing buffer exceeded",
#if defined INCLUDE_RESERVED
37, "RESERVED",
38, "RESERVED",
39, "RESERVED",
40, "RESERVED",
41, "RESERVED",
42, "RESERVED",
43, "RESERVED",
44, "RESERVED",
45, "RESERVED",
46, "RESERVED",
47, "RESERVED",
48, "RESERVED",
49, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
50, "Unsupported network request",

/* Error codes from 51 through 72 from Ray Duncan's book cited above. */
51, "Remote machine not listening",
52, "Duplicate name on network",
53, "Network name not found",
54, "Network busy",
55, "Device no longer exists on network",
56, "NetBIOS command limit exceeded",
57, "Error in network adapter hardware",
58, "Incorrect response from network",
59, "Unexpected network error",
60, "Remote adapter incompatible",
61, "Print queue full",
62, "Insufficient memory for print file",
63, "Print file canceled",
64, "Network name deleted",
65, "Network access denied",
66, "Incorrect network device type",
67, "Network name not found",
68, "Network name limit exceeded",
69, "NetBIOS session limit exceeded",
70, "File sharing temporarily paused",
71, "Network request not accepted",
72, "Print or disk redirection paused",
#if defined INCLUDE_RESERVED
73, "RESERVED",
74, "RESERVED",
75, "RESERVED",
76, "RESERVED",
77, "RESERVED",
78, "RESERVED",
79, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
80, "File already exists",
81, "Duplicate FCB",
82, "Cannot make directory",
83, "Fail on INT 24H (critical error)",
84, "Out of structures (too many redirections)",
85, "Already assigned (duplicate redirection)",
86, "Invalid password",
87, "Invalid parameter",
88, "Network write fault",
89, "No process slots available",
90, "Not frozen",
91, "Timer service table overflow",
92, "Timer service table duplicate",
93, "No items to work on",
#if defined INCLUDE_RESERVED
94, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
95, "Interrupted system call",
#if defined INCLUDE_RESERVED
96, "RESERVED",
97, "RESERVED",
98, "RESERVED",
99, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
100, "Too many semaphores",
101, "Exclusive semaphore already owned",
102, "Semaphore is set",
103, "Too many exclusive semaphore requests",
104, "Operation invalid at interrupt time",
105, "Semaphore owner died",
106, "Semaphore user limit exceeded",
107, "Disk change (insert drive B disk into drive A)",
108, "Drive locked",
109, "Broken pipe (write on pipe with no reader)",
110, "Open failed due to explicit fail command",
111, "Buffer overflow",
112, "Disk full",
113, "No more search handles",
114, "Invalid target handle",
115, "Protection violation",
116, "Vio/Kbd request error",
117, "Invalid category",
118, "Invalid verify switch",
119, "Driver does not support DosDevIOCtl",
120, "Call not implemented",
121, "Semaphore timeout",
122, "Insufficient data in buffer",
123, "Invalid name",
124, "Invalid level",
125, "No volume label",
126, "Module not found",
127, "Procecure not found",
128, "Wait no children",
129, "Child not complete",
130, "Invalid handle for direct disk access",
131, "Negative seek",
132, "Seek on device or pipe",
133, "Drive has previously joined drives",
134, "Drive is already joined",
135, "Drive is already substituted",
136, "Drive is not joined",
137, "Drive is not substituted",
138, "Cannot join to joined drive",
139, "Cannot substitute to substituted drive",
140, "Cannot join to substituted drive",
141, "Cannot substitute to joined drive",
142, "Drive is busy",
143, "Cannot join or substitute to directory on same drive",
144, "Must be subdirectory of root",
145, "Joined directory must be empty",
146, "Path is already used in substitute",
147, "Path is already used in join",
148, "Path is being used by another process",
149, "Target directory is already substitute target",
150, "System trace error",
151, "Invalid event count",
152, "Too many DosMuxSemWait waiters",
153, "Invalid list format",
154, "Volume label too long",
155, "Too many TCBs",
156, "Signal refused",
157, "Segment is discarded",
158, "Segment was not locked",
159, "Bad thread ID address",
160, "Bad arguments",
161, "Bad pathname",
162, "Signal already pending",
163, "Uncertain media",
164, "No more threads available",
165, "Monitors not supported",
166, "UNC driver not installed",
167, "Lock failed",
168, "Swap I/O failed",
169, "Swapin failed",
170, "Busy",
#if defined INCLUDE_RESERVED
171, "RESERVED",
172, "RESERVED",
173, "RESERVED",
174, "RESERVED",
175, "RESERVED",
176, "RESERVED",
177, "RESERVED",
178, "RESERVED",
179, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
180, "Invalid segment number",
181, "Invalid call gate",
182, "Invalid ordinal",
183, "Already exists",
184, "No child process",
185, "Child process is still alive",
186, "Invalid flag number",
187, "Semaphore not found",
188, "Invalid starting code segment",
189, "Invalid stack segment",
190, "Invalid module type",
191, "Invalid EXE signature",
192, "EXE marked invalid",
193, "Invalid EXE format",
194, "Iterated data exceeds 64k",
195, "Invalid minimum allocation size",
196, "DYNLINK from invalid ring",
197, "IOPL not enabled in CONFIG.SYS",
198, "Invalid segment descriptor privilege level (SEGDPL)",
199, "Automatic data segment exceeds 64k",
200, "Ring 2 segment must be movable",
201, "Relocation chain exceeds segment limit",
202, "Infinite loop in relocation chain",
203, "Environment variable not found",
204, "Not current country",
205, "No signal sent",
206, "Filename exceeds size range",
207, "Ring 2 stack in use",
208, "Meta expansion too long",
209, "Invalid signal number",
210, "Thread 1 inactive",
211, "File system information not available",
212, "Locked",
213, "Bad dynamic link",
214, "Too many modules",
215, "Nesting not allowed",
216, "Cannot shrink Ring 2 stack", /* Duncan */
#if defined INCLUDE_RESERVED
217, "RESERVED",
218, "RESERVED",
219, "RESERVED",
220, "RESERVED",
221, "RESERVED",
222, "RESERVED",
223, "RESERVED",
224, "RESERVED",
225, "RESERVED",
226, "RESERVED",
227, "RESERVED",
228, "RESERVED",
229, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
230, "Bad pipe",
231, "Pipe busy",
232, "No data",
233, "Pipe not connected",
234, "More data",
#if defined INCLUDE_RESERVED
235, "RESERVED",
236, "RESERVED",
237, "RESERVED",
238, "RESERVED",
239, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
240, "Virtual circuit disconnected",
#if defined INCLUDE_RESERVED
241, "RESERVED",
242, "RESERVED",
243, "RESERVED",
244, "RESERVED",
245, "RESERVED",
246, "RESERVED",
247, "RESERVED",
248, "RESERVED",
249, "RESERVED",
250, "RESERVED",
251, "RESERVED",
252, "RESERVED",
253, "RESERVED",
254, "RESERVED",
255, "RESERVED",
256, "RESERVED",
257, "RESERVED",
258, "RESERVED",
259, "RESERVED",
260, "RESERVED",
261, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
262, "Stack too large", /* Duncan */
#if defined INCLUDE_RESERVED
263, "RESERVED",
264, "RESERVED",
265, "RESERVED",
266, "RESERVED",
267, "RESERVED",
268, "RESERVED",
269, "RESERVED",
270, "RESERVED",
271, "RESERVED",
272, "RESERVED",
273, "RESERVED",
274, "RESERVED",
275, "RESERVED",
276, "RESERVED",
277, "RESERVED",
278, "RESERVED",
279, "RESERVED",
281, "RESERVED",
282, "RESERVED",
283, "RESERVED",
284, "RESERVED",
285, "RESERVED",
286, "RESERVED",
287, "RESERVED",
288, "RESERVED",
289, "RESERVED",
290, "RESERVED",
291, "RESERVED",
292, "RESERVED",
293, "RESERVED",
294, "RESERVED",
295, "RESERVED",
296, "RESERVED",
297, "RESERVED",
298, "RESERVED",
299, "RESERVED",
300, "RESERVED",
301, "RESERVED",
302, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
303, "Invalid process ID",
304, "Invalid priority level delta",
305, "Not descendant",
306, "Requestor not Session Manager",
307, "Invalid priority class",
308, "Invalid scope",
309, "Invalid thread ID",
310, "Cannot shrink DosSubSet segment",
311, "Out of memory",
312, "Memory block overlap",
313, "Invalid size parameter",
314, "Invalid flag parameter",
315, "Invalid segment selector",
316, "Message too long",
317, "Message ID not found",
318, "Unable to access message file",
319, "Invalid message file format",
320, "Invalid insertion variable count",
321, "Unable to perform function",
322, "Unable to wakeup",
323, "Invalid system semaphore handle",
324, "No timers available",
#if defined INCLUDE_RESERVED
325, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
326, "Invalid timer handle",
327, "Invalid date/time",
328, "Internal system error",
329, "Current queue name does not exist",
330, "Currrent process not queue owner",
331, "Current process owns queue",
332, "Duplicate queue name",
333, "Queue element does not exist",
334, "Insufficient queue memory",
335, "Invalid queue name",
336, "Invalid queue priority",
337, "Invalid queue handle",
338, "Queue link not found",
339, "Queue memory error",
340, "Previous queue record was at end of queue",
341, "Process has no access to queues",
342, "Queue empty",
343, "Queue name does not exist",
344, "Queues not initialized",
345, "Unable to access queues",
346, "Unable to add new queue",
347, "Unable to initialize queues",
#if defined INCLUDE_RESERVED
348, "RESERVED",
#endif /* #if defined INCLUDE_RESERVED */
349, "Invalid mask",
350, "Invalid pointer to parameter",
351, "VIO aptr",
352, "VIO rptr",
353, "VIO cptr",
354, "VIO lptr",
355, "Unsupported video mode",
356, "Invalid cursor width value",
357, "Invalid attribute",
358, "Invalid row value",
359, "Invalid column value",
360, "Invalid top row value",
361, "Invalid bottom row value",
362, "Invalid right column value",
363, "Invalid left column value",
364, "SCS call",
365, "SCS value",
366, "Invalid wait flag setting",
367, "Screen not previously locked",
368, "SGS not Session Manager",

/* BSEERR.H has 2 definitions for 369 through 371. */
369, "Invalid session ID",
370, "No sessions available",
371, "Session not found",

372, "Title cannot be changed",
373, "Invalid parameter",
374, "No device",
375, "Invalid wait parameter",
376, "Invalid length",
377, "Invalid echo mode mask",
378, "Invalid input mode mask",
379, "Invalid monitor parameters",
380, "Invalid device name",
381, "Invalid device handle",
382, "Buffer too small",
383, "Buffer empty",
384, "Data record too large",
385, "No MOUSE device",
386, "Invalid handle",
387, "Invalid parameters",
388, "Can't reset",
389, "Invalid display parameters",
390, "Invalid module",
391, "Invalid entry point",
392, "Invalid function mask",
393, "No MOUSE no data",
394, "No MOUSE pointer drawn",
395, "Invalid frequency",
396, "Cannot find COUNTRY.SYS file",
397, "Cannot open COUNTRY.SYS file",

/* BSEERR.H has 2 definitions for 398. */
398, "No country or codepage",

399, "NLS table truncated",
400, "NLS invalid type",
401, "NLS type not found",
402, "Function for Task Manager only",
403, "Invalid ASCIIZ string",
404, "VioDeRegister not allowed",
405, "No pop-up screen allocated",
406, "Pop-up already on screen",
407, "Function for Task Manager only",
408, "Invalid ASCIIZ string",
409, "Invalid replacement mask",
410, "KbdRegister not allowed",
411, "KbdDeRegister not allowed",
412, "Function for Task Manager only",
413, "Invalid ASCIIZ string",
414, "Invalid replacement mask",
415, "MouRegister not allowed",
416, "MouDeRegister not allowed",
417, "Invalid action",
418, "INIT called more than once",
419, "Screen group not found",
420, "Caller is not shell",
421, "Invalid parameters",
422, "Save/restore function already owned",
423, "Thread unblock by VioModeUndo or VioSavRedrawUndo",
424, "Invalid function",
425, "Function for Task Manager only",
426, "VioRegister not allowed",
427, "No VioModeWait thread exists",
428, "No VioSavRedrawWait thread exists",
429, "Invalid in background",
430, "Illegal during popup",
431, "Caller not baseshell",
432, "Invalid status request",
433, "Invalid wait parameter",
434, "Cannot lock screen",
435, "Invalid wait parameter",
436, "Invalid handle",
437, "Illegal during lock",
438, "Invalid length",
439, "Invalid Kbd handle",
440, "No more Kbd handles",
441, "Cannot create logical keyboard",
442, "Code page load incomplete",
443, "Invalid codepage ID",
444, "No codepage support",
445, "Kbd focus required",
446, "Kbd focus already active",
447, "Keyboard subsystem busy",
448, "Invalid codepage",
449, "Cannot get Kbd focus",
450, "Session is not selectable",
451, "Session not in foreground",
452, "Session not parent of specified child",
453, "Invalid session start mode",
454, "Invalid session start option",
455, "Invalid session bonding option",
456, "Invalid session select option",
457, "Session started in background",
458, "Invalid session stop option",
459, "Reserved parameters not zero",
460, "Process not parent",
461, "Invalid data length",
462, "Parent session not bound",
463, "Retry request block allocation",
464, "Kbd unavailable for detached process",
465, "Vio unavailable for detached process",
466, "Mouse unavailable for detached process",
467, "No font available to support mode",
468, "User font active",
469, "Invalid codepage",
470, "System displays do not support codepage",
471, "Current display does not support codepage",
472, "Invalid code page",
473, "Codepage list is too small",
474, "Codepage not moved",
475, "Mode switch initialization error",
476, "Code page not found",
477, "Unexpected slot returned",
478, "Invalid trace option",
479, "Internal resource error",
480, "Shell initialization error",
481, "No Task Manager hard errors",
482, "Codepage switch incomplete",
483, "Error during transparent pop-up",
484, "Critical section overflow",
485, "Critical section underflow",
486, "Reserved parameter is not zero",
487, "Invalid address",
488, "Zero selectors requested",
489, "Not enough selectors available",
490, "Invalid selector",
491, "Invalid program type",
492, "Invalid program control",
493, "Invalid program inheritance option",
494, "Function not allowed in PM window",
495, "Function not allowed in non-PM screen group",
496, "Shield alreay owned",
497, "No more Vio handles",
498, "Vio error occurred, see error log",
499, "Invalid display context",
500, "No console",
501, "No console",
502, "Invalid Mouse handle",
503, "Invalid debugging parms",
504, "Function not allowed in PM window",
505, "Function not allowed in non-PM screen group",
506, "Invalid icon file"
} ;

/* Here are some messages that we will use to display the error. */
static UCHAR szUnexpectedMessage [] = "\r\n\aUnexpected error return " ;
static UCHAR szFromOS2Message [] = " from OS/2 function \"" ;
static UCHAR szParensMessage [] = " ()\".\r\n\"" ;
static UCHAR szProgramNameMsg [] = "\"\r\nCaller program: \"" ;
static UCHAR szPeriod [] = "\"." ;
static UCHAR szFunctionNameMsg [] = "\r\nCaller function: \"" ;
static UCHAR szNearMessage [] = "\r\nNear line number: " ;
static UCHAR szPeriod1 [] = ".\r\n" ;
static UCHAR szNoErrorText [] = "(No error text available)" ;



void EXPENTRY errabort (PSZ pszProgramName, PSZ pszFunctionName,
PSZ pszCallerName, USHORT usLineNum, USHORT usReturn)
{
USHORT cbChars ; /* Characters we asked 'DosWrite ()' to write. */
USHORT cbBytes ; /* Characters actually written by 'DosWrite ()'. */
USHORT i ;
UCHAR szMessage [20] ; /* A result buffer for 'myitoa ()'. */

/* Nothing much to do here, really. Just display some 'canned' text,
* adding caller-supplied text where appropriate, with the odd
* conversion (via 'myitoa ()') or strlen (via 'mystrlen ()').
*
* I decided to use 'DosWrite ()' instead of 'VioWrtTTY ()' so that
* these messages will be captured in the 'stderr' file even if it
* is redirected. Again, performance is believed (by me) not to be
* an issue in this program because of its nature, but NEVER missing
* a message generated by it IS rather important. If 'stderr' is not
* redirected (the usual case), OS/2 will convert these 'DosWrite ()'
* calls into 'VioWrtTTY ()' anyway.
*/
DosWrite (STDERR, szUnexpectedMessage, sizeof (szUnexpectedMessage) - 1,
&cbBytes) ;
myitoa (usReturn, szMessage) ;
if ((cbChars = mystrlen (szMessage)) > 0)
DosWrite (STDERR, szMessage, cbChars, &cbBytes) ;
DosWrite (STDERR, szFromOS2Message, sizeof (szFromOS2Message) - 1,
&cbBytes) ;
if ((cbChars = mystrlen (pszFunctionName)) > 0)
DosWrite (STDERR, pszFunctionName, cbChars, &cbBytes) ;
DosWrite (STDERR, szParensMessage, sizeof (szParensMessage) - 1,
&cbBytes) ;
for (i = 0 ; i <= sizeof (ErrorArray) ; ++i) {
if (ErrorArray [i].usErrorNum == usReturn) {
if ((cbChars = mystrlen (ErrorArray [i].pszErrorText)) > 0)
DosWrite (STDERR, ErrorArray [i].pszErrorText,
cbChars, &cbBytes) ;
break ;
}
else if (ErrorArray [i].usErrorNum > usReturn) {
DosWrite (STDERR, szNoErrorText, sizeof (szNoErrorText) - 1,
&cbBytes) ;
break ;
}
}
DosWrite (STDERR, szProgramNameMsg, sizeof (szProgramNameMsg) - 1,
&cbBytes) ;
if ((cbChars = mystrlen (pszProgramName)) > 0)
DosWrite (STDERR, pszProgramName, cbChars, &cbBytes) ;
DosWrite (STDERR, szPeriod, sizeof (szPeriod) - 1, &cbBytes) ;
DosWrite (STDERR, szFunctionNameMsg, sizeof (szFunctionNameMsg) - 1,
&cbBytes) ;
if ((cbChars = mystrlen (pszCallerName)) > 0)
DosWrite (STDERR, pszCallerName, cbChars, &cbBytes) ;
DosWrite (STDERR, szPeriod, sizeof (szPeriod) - 1, &cbBytes) ;
DosWrite (STDERR, szNearMessage, sizeof (szNearMessage) - 1,
&cbBytes) ;
myitoa (usLineNum, szMessage) ;
if ((cbChars = mystrlen (szMessage)) > 0)
DosWrite (STDERR, szMessage, cbChars, &cbBytes) ;
DosWrite (STDERR, szPeriod1, sizeof (szPeriod1) - 1, &cbBytes) ;
DosExit (EXIT_PROCESS, 1) ;
}


/* We don't want to include 'strlen ()', so we rolled our own.
* Of course, the astute and experienced reader will recognize the
* code as a variant of one of the three presented in the original
* edition of K&R; however, they won't admit it, as it will show
* their age ...
*/
static USHORT FAR PASCAL mystrlen (PSZ pszString)
{
USHORT cbCount = 0 ;

while (*pszString++) /* Count characters. */
++cbCount ;
return cbCount ;
}


/* This private version of 'itoa ()' is not strictly compatible with
* ANSI 'itoa ()', unlike the relationship between 'strlen ()' and
* 'mystrlen ()' above. If you ever decide to use the library
* version instead of this one, it is not as simple as just changing
* the name. Be sure you look up 'itoa ()' first.
*/
static void FAR PASCAL myitoa (USHORT usNumber, PSZ pszMessage)
{
USHORT usWork, i, j ;
UCHAR ucChar ;

usWork = usNumber ;
i = 0 ;
*pszMessage = '\0' ;

/* First, generate digits in reverse order. */
do {
pszMessage [++i] = (UCHAR) (usWork % 10) + '0' ;
} while ((usWork /= 10) != 0) ;

/* Now reverse the string to correct the order. */
usWork = i ;
for (j = 0 ; j < usWork ; ++j, --i) {
ucChar = pszMessage [i] ;
pszMessage [i] = pszMessage [j] ;
pszMessage [j] = ucChar ;
}
}


  3 Responses to “Category : OS/2 Files
Archive   : ERRABORT.ZIP
Filename : ERRABORT.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/