HP 3000 Manuals

Traps [ HP Pascal/iX Programmer's Guide ] MPE/iX 5.0 Documentation


HP Pascal/iX Programmer's Guide

Traps 

Your HP Pascal program can use these MPE/iX traps:

   *   MPE/iX intrinsic XLIBTRAP, which traps library errors.

   *   MPE/iX intrinsic XARITRAP (the MPE/iX version of the MPE intrinsic
       XARITRAP), which traps arithmetic errors.

   *   MPE/iX intrinsics ARITRAP and HPENBLTRAP, which allow you to
       enable and disable trap conditions.

   *   MPE intrinsic XCONTRAP, which specifies a user-defined routine to
       handle the subsystem break (CONTROL Y).

The subsections of this section explain how to use these traps.


NOTE The user trap-handling routines whose addresses are passed to the traps in this section must be level-one routines.
ARITRAP and HPENBLTRAP Intrinsics The MPE/iX intrinsics ARITRAP and HPENBLTRAP are supported by the Trap Subsystem. ARITRAP allows a user program to enable or disable traps collectively. HPENBLTRAP is a new MPE/iX intrinsic that allows a user program to enable selected trap conditions. These terms apply to trap conditions: Term Meaning enable To allow a trap to be raised if the trap condition occurs. arm To specify that a particular trap handler is to be called if a certain trap is raised (the trap must be enabled to be raised). disable To prevent a trap from being raised, even if the trap condition occurs. By default, all traps except IEEE floating-point traps are enabled. (This complies with the IEEE floating-point standard, which stipulates that IEEE traps are to remain disabled by default.) Syntax ARITRAP (flag); HPENBLTRAP (mask, oldmask); Parameters flag 32-bit integer, passed by value. If flag is zero, all traps are disabled; otherwise, all traps are enabled. mask 32-bit integer, passed by value, whose bits specify which trap conditions are enabled. The assignment of each position in the bit mask is described in "XARITRAP Intrinsic." oldmask 32-bit integer, passed by reference, in which the old value of mask is returned. On MPE/iX, declare ARITRAP and HPENBLTRAP as external procedures this way: PROCEDURE ARITRAP; INTRINSIC; PROCEDURE HPENBLTRAP; INTRINSIC; On HP-UX, declare ARITRAP and HPENBLTRAP as external procedures this way: $PUSH; UPPERCASE ON$ PROCEDURE ARITRAP (Flag : integer); EXTERNAL; PROCEDURE HPENBLTRAP ( Mask : integer; VAR OldMask : integer ); EXTERNAL; $POP$ Example ARITRAP (1); {enables all traps} HPENBLTRAP (Hex('007C0000'), OldMask); {enables IEEE floating-point traps} XLIBTRAP Intrinsic The MPE/iX intrinsic XLIBTRAP is supported by the HP Pascal run-time library. It enables a user program to arm a library trap handling procedure (Library Trap Handler). Subsequently, any Pascal library error causes this Library Trap Handler to be called, allowing the user to decide whether to abort or continue the program, or correct the error. Syntax XLIBTRAP (plabel, oldplabel); Parameters plabel 32-bit integer, passed by value, which is the address of the Library Trap Handler. oldplabel 32-bit integer, passed by reference, in which the old value of plabel is returned. On MPE/iX, declare XLIBTRAP as an external procedure this way: PROCEDURE XLIBTRAP; INTRINSIC; On HP-UX, declare XLIBTRAP as an external procedure this way: $PUSH; UPPERCASE ON$ PROCEDURE XLIBTRAP ( PLabel : INTEGER; VAR OldPLabel : INTEGER ); EXTERNAL; $POP$ XLIBTRAP stores the address of the Library Trap Handler (plabel) so that the library routines can find the routine to call if an error occurs. The old value of PLabel is returned in the parameter OldPLabel. The only ways to leave a trap handler is by a normal return or by an escape. Your library trap handler cannot execute a nonlocal goto (a goto whose destination is outside the procedure).
NOTE This routine is available on the MPE/iX and HP-UX operating systems. On MPE/iX, it expects an MPE-style plabel; on HP-UX, it expects plabel to be the actual address of the Library Trap Handler. To make your program portable, use baddress (Library_Trap_Handler_name) as plabel.

NOTE The result record will be different if the trap has been raised outside of the Pascal run time library.
The user's trap handler must be declared this way: TYPE PStkMrk = RECORD {Stack Marker} users_PCS : integer; {space id of users code space} users_PCO : integer; {program counter offset within the code space} users_SP : integer; {stack pointer of the user's routine that called the library routine where the error occurred} users_DP : integer; {data pointer for the above routine} {future implementations may have further fields to return more information to the user's trap handler. If so, they will not affect existing code that uses the above fields.} END; PROCEDURE My_Library_Trap_Handler (VAR StkRec : PStkMrk; VAR ErrorCode : Integer; VAR AbortFlag : Integer ); BEGIN {My_Library_Trap_Handler} . . . END; {My_Library_Trap_Handler} Where StkRec A structure, as described above, passed by reference. Any changes to the fields of this structure are not reflected in the actual contents of the machine registers, when and if the program resumes normal execution. ErrorCode 32-bit integer, passed by reference, which contains the error code. For a complete list of error codes generated by the Pascal run-time library, see the file PASESC.PUB.SYS (on MPE/iX) or /usr/include/pasesc.ph (on HP-UX). Either of these files can be directly included in a user program. AbortFlag 32-bit integer, passed by reference. If AbortFlag is zero when the Library Trap Handler is exited, the program continues to execute. If AbortFlag is not zero, the Pascal run-time library prints an error message and aborts the program. To trap all run-time library errors and have them invoke your Library Trap Handler, call XLIBTRAP this way: XLIBTRAP (baddress(My_Library_Trap_Handler), OldPLabel); To disable your Library Trap Handler, pass zero to XLIBTRAP as the first parameter. Example {the user declares the following Pascal record for the PStkMrk record} TYPE PStkMrk = RECORD {"Stack Marker"} users_PCS, users_PCO, users_SP, users_DP : integer; END; $INCLUDE '/usr/include/pasesc.ph'$ {this file lists all the Pascal run-time library error codes for the HP-UX operating system} PROCEDURE My_Library_Trap_Handler (VAR StkRec : PStkMrk; VAR ErrorCode : Integer; VAR AbortFlag : Integer ); BEGIN {My_Library_Trap_Handler} {ignore file close errors, abort on all others} IF (ErrorCode = PasErr_CloseError) THEN BEGIN writeln ('Oops! File close error, continue execution'); AbortFlag := 0; {no abort} END ELSE AbortFlag := 1; {print message and abort} END; {My_Library_Trap_Handler} XARITRAP Intrinsic The MPE/iX intrinsic XARITRAP is supported by the Trap Subsystem. XARITRAP enables your program to arm an arithmetic trap handling procedure (Arithmetic Trap Handler). Subsequently, any arithmetic error causes this Arithmetic Trap Handler to be called, allowing the user to decide whether to abort or continue the program, or correct the error. For more information on trap handling, see the Trap Handling Programmer's Guide. Syntax To arm your Arithmetic Trap Handler, call XARITRAP this way: XARITRAP (mask, plabel, oldmask, oldplabel); Parameters mask 32-bit integer by value, whose bits specify which trap condition gets armed. The assignment of each position in the bit mask is as follows: Bit Error Trap 31 Compatibility Mode floating-point divide by zero 30 Integer divide by zero 29 Compatibility Mode floating-point underflow 28 Compatibility Mode floating-point overflow 27 Integer Overflow 26 Compatibility Mode double precision overflow 25 Compatibility Mode double precision underflow 24 Compatibility Mode double precision divide by zero 23 Decimal Overflow (COBOL) 22 Invalid ASCII digit (COBOL) 21 Invalid decimal digit (COBOL) 20-19 Reserved 18 Decimal divide by zero 17 IEEE floating-point inexact result 16 IEEE floating-point underflow 15 IEEE floating-point overflow 14 IEEE floating-point divide by zero 13 IEEE floating-point invalid operation 12 Range error (subrange violations, etc) 11 NIL pointer dereference 10 Result of pointer arithmetic is misaligned or error in conversion from long to short pointer 9 Unimplemented condition traps 8 Paragraph stack overflow (COBOL) 7-1 Reserved 0 Assertion Trap plabel 32-bit integer, passed by value, which is the address of the Arithmetic Trap Handler. oldmask 32-bit integer, passed by reference, in which the old value of mask is returned. old plabel 32-bit integer, passed by reference, in which the old value of plabel is returned. On MPE/iX, declare XARITRAP as an external procedure this way: PROCEDURE XARITRAP; INTRINSIC; On HP-UX, declare XARITRAP as an external procedure this way: $PUSH; UPPERCASE ON$ PROCEDURE XARITRAP ( Mask, plabel : integer; VAR OldMask, OldPlabel : integer ); EXTERNAL; $POP$ XARITRAP stores the address of the Arithmetic Trap Handler (plabel) so that the system trap handler can find the routine to call if an error occurs. The old value of plabel is returned in the parameter OldPLabel. The only ways to leave a trap handler is by a normal return or by an escape. Your library trap handler cannot execute a nonlocal goto (a goto whose destination is outside the procedure).
NOTE This routine is available on both the MPE/iX and HP-UX operating systems. On MPE/iX, it expects an MPE-style plabel; on HP-UX, it expects plabel to be the actual address of your Library Trap Handler. To make your program portable, use baddress(Arithmetic_Trap_Handler_name) as plabel. IEEE floating-point numbers are the default (native) real numbers in HP Precision Architecture. Compatibility Mode floating-point numbers have the format of reals on the MPE V system. The compiler options HP3000_32 and HP3000_16 specify native and compatibility Mode real numbers, respectively. For more information on HP3000_32 and HP3000_16, see the HP Pascal/iX Reference Manual or the HP Pascal/HP-UX Reference Manual, depending on your implementation.
The user's trap handler must be declared this way: TYPE TrapInfo= RECORD Instruction : integer; {the actual instruction word that caused the arithmetic trap} PC_Offset : integer; {offset of the above instruction within the user's code space} PC_Space : integer; {space id of user's code space} Error_Code : integer; {Trap type. This word is formed by setting the bit corresponding to the trap condition in a 32-bit integer, with all other bits zero. More than 1 bit will be turned on if multiple traps occur together} {more fields are returned for certain of the trap conditions. See below for details} END; PROCEDURE My_Arith_Trap_Handler (VAR Info : TrapInfo ); BEGIN {My_Arith_Trap_Handler} . . . END; {My_Arith_Trap_Handler} To enable (for example) all integer and IEEE floating-point traps, as well as all pointer traps, call XARITRAP this way: XARITRAP ( {bit 0 1 2 3 } { 01234567890123456789012345678901} Binary ('00000000001111111000000000010010'), BAddress (My_Arith_Trap_Handler), OldMask, OldPLabel );
NOTE In the preceding example, the IEEE inexact result trap is not enabled. HP Precision Architecture has only three distinct hardware arithmetic trap conditions: condition, [integer] overflow, and assist exception (IEEE floating-point traps are in the last category). The system is able to categorize most integer and decimal traps (except integer overflow) because each category has its own unique trapping instructions. If a condition trap occurs, and the system cannot categorize it, unimplemented condition trap (bit 9) is raised. The IEEE inexact result trap (bit 17), a trap required by the IEEE floating-point standard, indicates that a floating-point operation may have caused an inexact result (for example, the result of 10.0/3.0 is 3.333... regardless of the number of bits of precision you use). This trap is useful only for specialty number-crunching programs. Indiscriminate arming of this trap can severely degrade program performance, because almost any floating-point operation you perform will cause this trap to be raised.
To disable your Arithmetic Trap Handler, pass zero to XARITRAP as the second parameter. For the following traps, the system trap handler passes your Arithmetic Trap Handler more fields than the four defined above in the TrapInfo record, and you must adjust TrapInfo accordingly. Integer overflow trap Decimal overflow trap Invalid ASCII digit trap Invalid decimal digit trap IEEE floating-point traps Compatibility Mode floating-point traps The following sections describe the extra parameters. Integer Overflow Trap. The TrapInfo record must have one extra field, SubCode. SubCode (word #5) contains one of the following codes, which tells what kind of integer overflow occurred. SubCode Type of Overflow Value 1 32/64-bit overflow 2 16-bit overflow 3 8-bit overflow 4 overflow on conversion from a compatibility-mode floating-point number 5 overflow on conversion from an IEEE floating-point number Decimal Overflow Trap. The TrapInfo record must have one extra field, SubCode. SubCode (word #5) contains one of the following codes, which tells what kind of decimal overflow occurred. Subcode Type of Overflow Value 1 overflow in decimal arithmetic operation 2 overflow in conversion from ASCII to decimal Invalid ASCII Digit and Invalid Decimal Digit. The TrapInfo record has three extra fields: 1. Subcode (word #5) contains a code 0..3. Refer to the Trap Handling Programmer's Guide for more information. 2. Address (word #6) contains the address of the first digit of the number 3. Count (word #7) contains the digit count IEEE Floating Point Traps. The TrapInfo record has six extra fields: 1. Status (word #5) contains the value in the status register of the IEEE floating-point coprocessor. Any change in this field is reflected in the value of the status register when the program resumes execution. 2. Operation (word #6) contains one of the following codes, which tells the type of floating-point operation that caused the trap. Value Type of Operation 3 ABS 4 SQRT 5 RND 8 CNVFF 9 CNVXF 10 CNVFX 16 CMP 24 ADD 25 SUB 26 MPY 27 DIV 28 REM 3. Format (word #7) contains the type of the operands (single, double, or quadruple). If the operation was CONVERT (CNVxx), then the following values are returned: Value Types of Operands 1 Source is single, result is double 3 Source is single, result is quadruple 4 Source is double, result is quadruple If the operation was NOT a CONVERT (CNVxx), then the following values are returned: Value Type of Operand 0 Single 1 Double 3 Quadruple 4. source_op1_ptr (word #8) contains the address of the first operand, which can be a single-, double- or quadruple-word floating-point number, depending on the operation and the format. 5. source_op2_ptr (word #9) contains the address of the second operand, which can be a single-, double-, or quadruple-word floating-point number, depending on the operation and the format. 6. result_ptr (word #10) contains the address of the result of the operation, which can be a single-, double-, or quadruple-word floating-point number depending on the operation and the format. You can examine and replace the contents of the area referenced by result_ptr, and the Trap Subsystem will ensure that the change is reflected in the appropriate place. Compatibility Mode Floating-Point Traps. The TrapInfo record has one extra field, Result_ptr. Result_ptr (word #5) contains the address of the result of the operation, which can be a single- or double-word floating-point number, depending on the type of trap. You can examine and replace the contents of the area referenced by result_ptr, and the Trap Subsystem will ensure that the change is reflected in the appropriate place. Example {user declares the following Pascal record for the TrapInfo record} TYPE real_ptr = real; long_ptr = longreal; TrapInfo = RECORD { 1} instruction, { 2} pc_offset, { 3} pc_space, { 4} error_code, { 5} status, { 6} operation, { 7} format : integer; { 8} source1_ptr, { 9} source2_ptr, {10} result_ptr : localanyptr; END; CONST IEEE_mask = hex('0007C000'); fdiv_zero = hex('00002000'); {the error code for fl. pt. div. by 0} {trap handler routine} PROCEDURE IEEE_trap_handler (VAR Info : TrapInfo); VAR long_res_ptr : long_ptr; real_res_ptr : real_ptr; (Example continued on next page.) CONST max_real = 3.402823E+38; max_longreal = 1.797693L+308; BEGIN {IEEE_trap_handler} {handle only divide-by-zero, ignore others} WITH Info DO IF (Error_Code = fdiv_zero) THEN BEGIN {divide by zero} {change the value of the result} IF (format = 0) THEN BEGIN {real operation} real_res_ptr := result_ptr; real_res_ptr^ := maxreal; END {real operation} ELSE IF (format = 1) THEN BEGIN {longreal operation} long_res_ptr := result_ptr; long_res_ptr^ := maxlongreal; END; {longreal operation} END; {divide by zero} END; {IEEE_trap_handler} {user main program} VAR l1, l2, l3 : longreal; oldmask, oldplabel : integer; BEGIN {main program} ARITRAP (1); {see "ARITRAP and HPENBLTRAP Intrinsics" for details} XARITRAP (IEEE_mask, BAddress (IEEE_trap_handler), oldmask, oldplabel); l1 := 233.0; l2 := 0.0; l3 := l1/l2; {oops! divide by zero!} writeln (l3); {the trap handler should have fixed the result of the previous operation to maxlongreal (1.79769e+308)} END. {main program} XCONTRAP Intrinsic The MPE intrinsic XCONTRAP specifies a user-defined routine (Subsystem Break Handler) that will be called when the user enters a subsystem break (CONTROL Y) on the keyboard. When XCONTRAP is enabled and the user enters CONTROL Y: * Program control is transferred to the specified user-defined routine. * The subsystem break function is temporarily disabled to reduce the chance of race conditions. If normal program execution is to resume after the interrupt, the user-defined routine must re-enable the subsystem break by calling the intrinsic RESETCONTROL just before it ends. On MPE/iX, a normal exit from the user-defined routine is sufficient to return control to the point in the program where the subsystem break was trapped. Syntax To arm your Subsystem Break Handler, call XCONTRAP this way: XCONTRAP (plabel, oldplabel); Call RESETCONTROL this way: RESETCONTROL; Declare XCONTRAP and RESETCONTROL this way: PROCEDURE XCONTRAP; INTRINSIC; PROCEDURE RESETCONTROL; INTRINSIC; Parameters oldplabel A 32-bit integer, passed by reference, in which the old value of plabel is returned. If the subsystem break handler is not armed, this value is zero. plabel A 32-bit integer, passed by value, which is the address of your Subsystem Break Handler. Example The main program is a loop. Whenever the user enters CONTROL Y on the keyboard, control transfers to the procedure control_y_handler, which writes the current loop counter value, then re-enables the subsystem break, and returns to the point in the loop where the interrupt occurred. PROGRAM control_y_test (output); VAR count : integer; i : integer; oldplabel : integer; {Intrinsic Declarations} PROCEDURE XCONTRAP; INTRINSIC; PROCEDURE RESETCONTROL; INTRINSIC; {User-defined Subsystem Break Handler} PROCEDURE control_y_handler; BEGIN writeln('<Control-Y>: Count = ', count:1); {write counter value} RESETCONTROL; {re-enable subsystem break} END; BEGIN {Arm the Subsystem Break Handler, specifying control_y_handler as the user-defined routine} XCONTRAP (BAddress (control_y_handler), oldplabel); {Loop} FOR i := 1 TO 30000000 DO count := i; END. If you compile, link, and run the preceding program on an MPE/iX system and press CONTROL Y several times while it is running, the program prints the value of count each time you press CONTROL Y. For example: CONTROL Y: Count = 121765 CONTROL Y: Count = 2731435 CONTROL Y: Count = 5789345 CONTROL Y: Count = 10135467 CONTROL Y: Count = 23618560


MPE/iX 5.0 Documentation