www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1993/12/20/23:12:03

Date: Mon, 20 Dec 93 22:54:49 EST
From: peprbv AT cfa0 DOT harvard DOT edu (Bob Babcock)
To: djgpp AT sun DOT soe DOT clarkson DOT edu
Cc: peprbv AT cfa0 DOT harvard DOT edu
Subject: critical error routine

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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019