Mail Archives: djgpp/1993/12/20/23:12:03
I've had several requests for the critical error handler I mentioned, so here
it is. The basic idea is to allocate a small amount of DOS memory (one
paragraph suffices), copy the code for a critical error handler into this
memory, and tell DOS to use this handler. All the handler does is to save an
error code and tell DOS to fail the error. One thing it does not do is to
determine whether the error occurred on a block or character device. There
are alternative ways a critical error handler could be implemented, in
particular a real-mode callback could be used. I chose the method below
because it is a close match to what I was doing in DOS code. Comments on
this code are welcome.
A global header file which defines LOGICAL, TRUE and FALSE is omitted, as is
the error message printing routine inside the #ifdef DEBUG conditional.
There's also a global variable Hard_error which is left over from my DOS
critical error handler; it isn't actually needed here.
-----------
#include <dpmi.h>
#include <go32.h>
/* hardgcc - critical error handler for gcc
*/
static char handler[16] =
{
0x81, 0xe7, 0x7f, 0, /* and di,7f */
0x47, /* inc di */
0x2e, 0x89, 0x3e, 0xe, 0, /* mov cs:[0eh],di */
0xb8, 3, 0, /* mov ax,3 */
0xcf, /* iret */
0,0 /* storage for error code */
};
static LOGICAL handler_installed = FALSE;
static _go32_dpmi_seginfo new_handler_info, old_handler_info;
/* hardset - install the real-mode critical error handler
*/
void hardset(void)
{
/* On first call, allocate some DOS memory and copy the handler into it
*/
if(!handler_installed)
{
handler_installed = TRUE;
new_handler_info.size = old_handler_info.size = 1;
_go32_dpmi_allocate_dos_memory(&new_handler_info);
dosmemput(handler, 16, new_handler_info.rm_segment * 16);
#ifdef DEBUG
sprintf(Tempbuf, "Handler at segment %x", new_handler_info.rm_segment);
error_msg(Tempbuf, 0);
#endif
}
_go32_dpmi_get_real_mode_interrupt_vector(0x24, &old_handler_info);
_go32_dpmi_set_real_mode_interrupt_vector(0x24, &new_handler_info);
clear_hard_error();
return;
}
/* hardclear - switch back to old critical error handler
*/
void hardclear(void)
{
if(handler_installed)
_go32_dpmi_set_real_mode_interrupt_vector(0x24, &old_handler_info);
return;
}
/* clear_hard_error - clear any indication of a critical error
*/
void clear_hard_error(void)
{
short zero = 0;
if(handler_installed)
dosmemput(&zero, 2, new_handler_info.rm_segment * 16 + 14);
Hard_error = 0;
return;
}
/* test_hard_err - test whether a critical error has occurred and return
error code (0 if none or handler never installed).
*/
int test_hard_err(void)
{
short error_code;
if(handler_installed)
{
dosmemget(new_handler_info.rm_segment * 16 + 14, 2, &error_code);
#ifdef DEBUG
if(error_code)
{
sprintf(Tempbuf,"Critical error code is %d", error_code);
error_msg(Tempbuf,0);
}
#endif
return(error_code);
}
return(0);
}
- Raw text -