home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c221 / 5.ddi / MWHC.005 / D3 < prev    next >
Encoding:
Text File  |  1992-12-09  |  5.2 KB  |  140 lines

  1. {*********************************************************************
  2. (C) Copyright 1983-92; MetaWare Incorporated;  Santa Cruz, CA 95060.
  3. *********************************************************************}
  4. pragma on(Optimize_for_space);
  5. Export(Here);
  6. pragma C_include('Implement.pf');
  7. pragma C_include('Interrupts.pf');
  8. pragma C_include('Portio.pf');
  9. package Here;
  10.    pragma Routine_aliasing_convention(Implement.RTE_aliasing);
  11.    procedure Init_interrupts;    External;
  12.    procedure Restore_interrupts;External;
  13.    end;
  14.  
  15. with Loopholes:[Adr,Retype,Longptr,Sizeof,Address,Pointer_arithmetic];
  16.  
  17. package Elsewhere;
  18.    pragma Routine_aliasing_convention(Implement.RTE_aliasing);
  19.    with Interrupts:[Interrupt_vector_element];
  20.    procedure Pop_and_jmp(A:Address; I:Interrupt_vector_element);       External;
  21.    procedure Display(const S:string); external;
  22.    procedure Abort(const Msg:String); external;
  23.    -- Displays message "stack overflow":
  24.    procedure Stkerr;            external;
  25.    end;
  26.  
  27. with Elsewhere,Interrupts,Portio;
  28. pragma Off(With_warnings);
  29. --with System;
  30. pragma Pop(With_warnings);
  31.  
  32. program Implement_ints;
  33. pragma Alias(Implement_ints,Implement.RTE || 'ints');
  34.  
  35. pragma off(emit_names);
  36.  
  37. { Interrupt processing.                 }
  38.  
  39. procedure Make_trace_work(var S:Machine_status);
  40.    { Place the return address near the saved BP so trace works.     }
  41.    begin
  42.    S.DS := S.Interrupt_address.Segment;
  43.    S.ES := S.Interrupt_address.Offset;
  44.    end;
  45.  
  46. const
  47.    Range    = 5;    -- Range or nil check error.
  48.    Quotient_oflo= 0;    -- Quotient oflo or divide by 0.
  49.    Control_C    = #23;    -- Control/C.
  50.  
  51. -- In later versions the divide & range errors will be user-trappable with
  52. -- exception handlers.
  53.  
  54. { Save area for old interrupt routine addresses:    }
  55. var
  56.    Range_H_old, Quotient_oflo_H_old, Control_C_H_old: Interrupt_vector_element;
  57.  
  58. procedure Die;
  59.    -- Can't afford to clean up with Halt since it may call
  60.    -- call_onexit_fcns in C, causing potential recursive interrupts.
  61.    begin
  62.    Abort('');
  63.    end;
  64.  
  65. pragma Calling_convention(Pascal_interrupt);
  66. procedure Interrupt5(S:Machine_status);
  67.    var Dummy: Machine_status;
  68.    begin
  69.    -- Check if this is a range interrupt, generated by an INT 5 instruction,
  70.    -- or some other source of an interrupt 5, such as SHIFT-PRTSC on an IBM PC.
  71.    -- If the latter, just call the latter routine.
  72.    -- How to detect the latter?  Right now there is no easy way.
  73.    -- Unfortunately, the MS-DOS designers used INT 5, where the 286
  74.    -- reserves this interrupt for range errors.  Print screen was really
  75.    -- put in the wrong place!    We therefore assume that if the INT 5
  76.    -- was issued above address #f000:0, it was from the BIOS and we assume
  77.    -- it wasn't a range error.  What are we going to do when we go to zenix?
  78.    -- Perhaps hope that the designers didn't mis-use int 5!
  79.    if S.Interrupt_address.Segment >= #f000 then
  80.       -- Someone else generated this interrupt!  Call the routine so doing.
  81.       Call_interrupt_vector_element(Dummy,Range_H_old)
  82.    else begin
  83.       Make_trace_work(S);
  84.       Display('***RANGE OR NIL CHECK ERROR***');
  85.       Fstackdump(Stderr);
  86.       Die;
  87.       end;
  88.    end;
  89. procedure Interrupt0(S:Machine_status);
  90.    begin
  91.    Make_trace_work(S);
  92.    { Examine instruction preceding the interrupt location to see if    }
  93.    { it was an INT 0 or an actual divide error.  We use INT 0 to flag    }
  94.    { stack overflow.                            }
  95.    Dec(S.Interrupt_address.Offset,2);
  96.    if Retype(S.Interrupt_address,Longptr(Cardinal))^ = #00CD then Stkerr()
  97.    else Display('***QUOTIENT OVERFLOW ON DIVIDE***');
  98.    Fstackdump(Stderr);    -- Trace must come from here so as not
  99.             -- to confuse reader with too many procs.
  100.    Die;
  101.    end;
  102. procedure Control_C_H(S:Machine_status);
  103.    begin
  104.    Restore_interrupts;
  105.    -- Now call the original control/C handler to wind up:
  106. -- Call_interrupt_vector_element(S,Control_C_H_old);
  107.    -- Unfortunately the above doesn't work under MS-DOS.  For some strange
  108.    -- reason the only way this will work is if we unwind the stack
  109.    -- back to just before we saved status, and directly jump to
  110.    -- Control_C_H_old.
  111.    -- Pop back to the pushed address and jump to the old routine.
  112.    -- 6 = size of flags + rtn adr, same in all memory models.
  113.    Pop_and_jmp(Adr(S)+Sizeof(S)-6,Control_C_H_old);
  114.    -- Therefore we just call DOS_exit here.
  115. -- Dos_exit(1);
  116.    -- This doesn't work well because we then lose the "interruptedness"
  117.    -- of the ^C -- in particular, a batch file will not abort.
  118.    end;
  119. pragma Calling_convention;
  120.  
  121. procedure Init_interrupts;
  122.    begin
  123.    Range_H_old := Vector_element(Range);
  124.    Quotient_oflo_H_old := Vector_element(Quotient_oflo);
  125.    Control_C_H_old := Vector_element(Control_C);
  126.    Install_interrupt_routine(Range,Interrupt5);
  127.    Install_interrupt_routine(Quotient_oflo,Interrupt0);
  128.    Install_interrupt_routine(Control_C,Control_C_H);
  129.    end;
  130.  
  131. procedure Restore_interrupts;
  132.    begin
  133.    Install_interrupt_vector_element(Range,Range_H_old);
  134.    Install_interrupt_vector_element(Quotient_oflo,Quotient_oflo_H_old);
  135.    Install_interrupt_vector_element(Control_C,Control_C_H_old);
  136.    end;
  137.  
  138. { (C) Copyright 1983-1985;  unpublished property and trade secret of }
  139. { MetaWare Incorporated; Santa Cruz, CA 95060; detailed notice above.}
  140.