From 7e0f021a9aec35fd8e6725e87e3313b101d26f5e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 27 Jan 2008 11:37:44 +0100 Subject: Initial import (2.0.2-6) --- reference/C/CONTRIB/SNIP/except.doc | 184 ++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100755 reference/C/CONTRIB/SNIP/except.doc (limited to 'reference/C/CONTRIB/SNIP/except.doc') diff --git a/reference/C/CONTRIB/SNIP/except.doc b/reference/C/CONTRIB/SNIP/except.doc new file mode 100755 index 0000000..4e501b5 --- /dev/null +++ b/reference/C/CONTRIB/SNIP/except.doc @@ -0,0 +1,184 @@ +USER-GENERATED EXCEPTIONS IN GENERAL +------------------------------------ + +MS-DOS users can generate exceptions by means of two separate +mechanisms, Ctrl-C and Ctrl-Break. Although these are often treated +the same, they are actually handled in subtly different manners. The +difference in the way these are processed allows a great deal of +flexibility in allowing users to interrupt an executing program. + +When a program is executed, the Ctrl-C Interrupt 23h is set up to +point to a default error handler. This handler is called whenever a +Ctrl-C character is detected in the keyboard input buffer. When a +program terminates in any way, MS-DOS resets the Interrupt 23h vector +to its default state. Note that the Ctrl-C character in the input +buffer is only recognized - and an Interrupt 23h generated - when +retrieving characters from the buffer and if BREAK ON is set. + +The Ctrl-Break Interrupt 1Bh works somewhat differently, though +usually in concert with Interrupt 23h. Whenever the ROM BIOS detects +the Ctrl-Break key combination, the keyboard buffer is flushed and a +Ctrl-C key combination is stuffed in place of the previous contents. +This Ctrl-C will later be detected and processed by Interrupt 23h. +Ctrl-Break processing therefore offers more immediate response than +Ctrl-C processing if the default action is overridden. + +Several caveats are in order here, however. First is the fact that, +unlike Interrupt 23h, MS-DOS does not restore the default state of +Interrupt 1Bh upon program termination. Second is that while Ctrl-C +processing is standardized among the various machines utilizing both +MS-DOS and PC-DOS, Ctrl-Break processing is much less standardized. +Finally, since processing either ultimately relies on trapping +Ctrl-C, either may be ignored for a long period because of the way +that Ctrl-C is detected. + + +HANDLING USER-GENERATED EXCEPTIONS +---------------------------------- + +DOS's default Ctrl-C handler is triggered whenever the Ctrl-C +character is detected in the input buffer. DOS's response is to +simply close all files which were opened using handle functions and +to terminate the program. The limitations of this approach and the +desirability of providing your own exception processing is obvious. + +An equally obvious solution to the default Ctrl-C handler's problems +is to explicitly do your own Ctrl-C exception processing. CCTRAP.ASM +installs and de-installs you own customized exception handler. Note +that the code is written to accept the address of a function specified +with an explicit segment and offset. + +Also note that an explicit de-installation function is provided +despite the fact that DOS restores the default Int 23h vector upon +program termination. The reason this is provided is that you should +always de-install a Ctrl-C interrupt trap before you spawn a child +process. Within your program, if you need to spawn such a process +through any mechanism other than spawning a subordinate shell (more +on this in a second), you should explicitly de-install your interrupt +handlers and re-install them when the subordinate process returns. As +noted, this is unnecessary when the subordinate process is a DOS +shell such as COMMAND.COM, since the shell will reset the interrupts +to their defaults during execution. + +Ctrl-Break processing is much more problematical, though potentially +more powerful. The first problem to deal with is how to assure that +the default Int 1Bh Ctrl-Break handler will be restored upon program +termination. The de-installation function therefore becomes mandatory +in this context rather than optional as in the case of the Int 23h +handler. CBTRAP.ASM shows a sample Ctrl-Break handler. Since Ctrl-Break +processing is much less standardized than Ctrl-C processing, the +safest way to deal with it is to simply set a flag, "cbrcvd", which +informs your program that a Ctrl-Break has been received. Your +program may then poll this flag and take appropriate actions at +"safe" times within your program. + + +WHERE THE CARET-C COMES FROM +---------------------------- + +There's still nothing new here and nothing to prevent the ugly "^C" +being printed to the screen. This is because it is actually printed +by the BIOS during Int 9 processing, long before DOS ever sees it. +What this means is that even though the code in CCTRAP.ASM and +CBTRAP.ASM is fine, it still only provides a framework for solving +our problem. + +TRAPFLAG.ASM is the final trick to banish the "^C". The actual ISR +has to muck around quite a bit with the keyboard hardware, as is to +be expected of an Int 09h replacement. Whenever a Ctrl-C or Ctrl- +Break is detected, it is trapped, and our exception handler called in +place of the original Int 09h handler, after discarding the trapped +key codes. + +Referring to TRAPFLAG.ASM, note that since I need to trap both Ctrl-C +and Ctrl-Break, I adopt the flag approach introduced in CBTRAP.ASM +for dealing with both Ctrl-C and Ctrl-Break processing. Now, rather +than supplying an explicit exception vector, I merely set a global +flag to inform me if either exception has occurred and accept the +responsibility of processing the exceptions within the body of my +program. I've added an extra bit of versatility here by posting +different non-zero values to the flag, "ccrcvd" depending on whether +the exception was a Ctrl-C or Ctrl-Break. + +TRAPDEMO.C is a short C program demonstrating the use of the combined +Ctrl-C/Ctrl-Break handler. Using this approach, your carefully +crafted screens need never more be cluttered with the "^C" uglies. + + +SYSTEM-GENERATED EXCEPTIONS +--------------------------- + +It's usually desirable, in any professional-looking program, to +explicitly trap the Int 24h critical error interrupt to process +system-generated exceptions. CERRINST.ASM is a portable critical +error handler installation program functionally equivalent to the +[_]hardxxx() package in Borland C++ and Microsoft C++ compilers, and +the ceror_xxx() package in Zortech C++. + +It's obvious that writing code to intercept DOS critical error +exceptions is just as simple as intercepting Ctrl-C or Ctrl-Break +exceptions. The real challenge in writing critical error handlers is +in interpretation of the nature of the exception. + +The critical error handler requires more information in order to +decide what action to take than does a Ctrl-C handler. All of this +information is passed in the CPU's registers. Just like a typical +compiler vendor's critical error handler, CERRINST.ASM will simply +pass these registers and leave their interpretation to you. In +CERRINST.ASM, the information required for intelligent critical error +processing is posted in 4 global variables, cedevdvr, cetype, +ceerror, and cereturn. + +Next you need to determine what your program requires of a critical +error handler. CERRTRAP.ASM is a skeletal, yet robust critical error +function which may be called from the handler in CERRINST.ASM. +CERRTRAP.ASM assumes you have set up the following specific error +handlers in the global variables provided: + +FAT error (*FAT_err)(); +Disk read error (*read_err)() +Disk write error (*write_err)() +Terminal error (*term_err)(), +Printer out of paper (*no_paper)(), +All other errors (*fixup_ret)(), + +In the case of an unrecognized error, fixup_ret() is called. A simple +skeleton for this function would be: + +#include /* for _osmajor */ +extern int exerr; /* DOS extended error posted by CERRTRAP.ASM */ +extern int rmvbl; /* removable media flag posted by CERRTRAP.ASM */ +extern int locus; /* extened error locus posted by CERRTRAP.ASM */ +extern int class; /* extened error class posted by CERRTRAP.ASM */ +extern int suggest; /* suggested action posted by CERRTRAP.ASM */ + +int fixup_ret(void) +{ + if (2 < _osmajor) + { + /* analyze DOS extended error information */ + + return appropriate_error_code; + } + + /* cleanup */ + + return 2; /* abort */ +} + +In customing your specific critical error handler functions, there +are several important restrictions to keep in mind. The first is that +no DOS system services may be requested other than Interrupt 21h +functions 01h-0Ch (character I/O), 30h (get DOS version number), and +59h (get extended error information). All registers except AL must be +preserved since DOS sets them up for processing Retry returns prior +to invoking the critical error interrupt. + +Finally, the handler must return with an IRET instruction, passing a +return code in AL to tell DOS what to do next. The available codes +and their actions under various DOS versions are: + + 0 - Ignore + 1 - Retry + 2 - Abort + 3 - Fail (DOS 3.3 and later) -- cgit v1.2.3-54-g00ecf