* V$IRC -- 16-BIT SIGNED INTEGER RANGE CHECK ROUTINES
*           V$CIRNG, V$CIUPB, V$CILWB:  CONSTANT (KNOWN) BOUNDS
*           V$VIRNG, V$VIUPB, V$VILWB:  VARIABLE (UNKNOWN) BOUNDS

*           REQUIRES SOFTWARE TOOLS LIBRARY


         SEG
         RLIT
         SYML

         ENT   V$CIRNG        IS A-REG WITHIN CONSTANT BOUNDS?
         ENT   V$CIUPB        IS A-REG <= A CONSTANT UPPER BOUND?
         ENT   V$CILWB        IS A-REG >= A CONSTANT LOWER BOUND?
         ENT   V$VIRNG        IS A-REG WITHIN DYNAMIC BOUNDS?
         ENT   V$VIUPB        IS A-REG <= A DYNAMIC UPPER BOUND?
         ENT   V$VILWB        IS A-REG >= A DYNAMIC LOWER BOUND?


VALUE    EQU   SB%+'12     FIRST AVAILABLE SCRATCH STORAGE LOCATION
LWBVAL   EQU   SB%+'13
UPBVAL   EQU   SB%+'14
COND     DATA  11,C'RANGE_ERROR'    PL/I CHAR VARYING FORM OF CONDITION
NULLP    DATA  '7777,0              PL/I NULL POINTER




* V$CIRNG --- CONSTANT INTEGER-BOUNDS RANGE CHECK
*
*        CALLING SEQUENCE:
*              LOAD ACCUMULATOR A WITH VALUE TO BE CHECKED
*              EXT   V$CIRNG
*              JSXB  V$CIRNG
*              DATA  LOWER_BOUND
*              DATA  UPPER_BOUND
*              DATA  LINE_NUMBER_TO_BE_USED_FOR_DIAGNOSTICS
*
*        EXAMPLE:
*              LDA   I
*              EXT   V$CIRNG
*              JSXB  V$CIRNG
*              DATA  1
*              DATA  100
*              DATA  47
*              TAX
*              LDA   ARRAY,X
*
*        VALUE IN A IS RETURNED UNCHANGED IF IT IS IN RANGE
*
*        ERROR MESSAGE IS ISSUED AND RANGE_ERROR EXCEPTION
*           IS RAISED IF IT IS NOT IN RANGE


V$CIRNG  EQU   *
         CAS   XB%         COMPARE VALUE IN A TO LOWER BOUND
         JMP#  L1          IF >, CHECK UPPER BOUND
         JMP#  L1          IF =, CHECK UPPER BOUND
         STA   VALUE
         PCL   LWBERR      IF <, REPORT LOWER BOUND ERROR
         AP    VALUE,S        GIVING ACTUAL VALUE
         AP    XB%,S          LOWER BOUND
         AP    XB%+2,S        SOURCE LINE NUMBER
         AP    SB%+18,*
         AP    XB%+16,SL      AND NAME OF ROUTINE

L1       EQU   *
         CAS   XB%+1       COMPARE VALUE IN A TO UPPER BOUND
         JMP#  L2          IF >, VALUE EXCEEDS TOP OF RANGE
         RCB               IF =
         JMP%  XB%+3          OR IF <, VALUE IS OK; DO NORMAL RETURN

L2       EQU   *
         STA   VALUE
         PCL   UPBERR      REPORT UPPER BOUND ERROR
         AP    VALUE,S        GIVING ACTUAL VALUE
         AP    XB%+1,S        UPPER BOUND
         AP    XB%+2,S        SOURCE LINE NUMBER
         AP    SB%+18,*
         AP    XB%+16,SL      AND NAME OF ROUTINE



* V$CIUPB -- CONSTANT UPPER-BOUND CHECK
*
*        CALLING SEQUENCE:
*              LOAD A WITH VALUE TO BE CHECKED
*              EXT   V$CIUPB
*              JSXB  V$CIUPB
*              DATA  UPPER_BOUND
*              DATA  SOURCE_LINE_NUMBER
*
*        EXAMPLE:
*              LDA   I
*              EXT   V$CIUPB
*              JSXB  V$CIUPB
*              DATA  10
*              DATA  14
*              TAX
*              LDA   ARRAY,X
*
*        A-REG IS RETURNED UNCHANGED IF IT IS <= UPPER BOUND
*
*        RANGE_ERROR EXCEPTION IS RAISED OTHERWISE


V$CIUPB  EQU   *
         CAS   XB%         COMPARE VALUE TO UPPER BOUND
         JMP#  L3          IF >, WE HAVE AN ERROR CONDITION
         RCB               IF =
         JMP%  XB%+2            OR IF <, WE RETURN NORMALLY

L3       EQU   *
         STA   VALUE
         PCL   UPBERR
         AP    VALUE,S
         AP    XB%,S
         AP    XB%+1,S
         AP    SB%+18,*
         AP    XB%+16,SL



* V$CILWB -- CONSTANT LOWER-BOUND CHECK
*
*        CALLING SEQUENCE:
*              LOAD A WITH VALUE TO BE CHECKED
*              EXT   V$CILWB
*              JSXB  V$CILWB
*              DATA  LOWER_BOUND
*              DATA  SOURCE_LINE_NUMBER
*
*        EXAMPLE:
*              LDA   I
*              EXT   V$CILWB
*              JSXB  V$CILWB
*              DATA  0
*              DATA  14
*              TAX
*              LDA   ARRAY,X
*
*        A-REG IS RETURNED UNCHANGED IF IT IS >= LOWER BOUND
*
*        RANGE_ERROR EXCEPTION IS RAISED OTHERWISE


V$CILWB  EQU   *
         CAS   XB%         COMPARE VALUE TO LOWER BOUND
         JMP#  L4          IF >
         JMP#  L4               OR IF =, WE RETURN NORMALLY

         STA   VALUE       OTHERWISE, WE REPORT AN ERROR
         PCL   LWBERR
         AP    VALUE,S     ACTUAL VALUE
         AP    XB%,S       LOWER BOUND
         AP    XB%+1,S     LINE NUMBER IN SOURCE CODE
         AP    SB%+18,*
         AP    XB%+16,SL   NAME OF ROUTINE (FOLLOWING ECB)

L4       EQU   *
         JMP%  XB%+2



* V$VIRNG -- VARIABLE BOUNDS RANGE CHECK
*
*        CALLING SEQUENCE:
*              LOAD A WITH LOWER BOUND
*              STORE A IN THE CURRENT STACK FRAME
*              LOAD A WITH UPPER BOUND
*              STORE A IN THE CURRENT STACK FRAME
*              LOAD A WITH VALUE TO BE CHECKED
*              EXT   V$VIRNG
*              JSXB  V$VIRNG
*              DATA  OFFSET_OF_LOWER_BOUND_IN_FRAME
*              DATA  OFFSET_OF_UPPER_BOUND_IN_FRAME
*              DATA  SOURCE_LINE_NUMBER
*
*        EXAMPLE:
*              EAXB  DISPLAY1,*
*              LDA   XB%+14
*              STA   SB%+21
*              LDA   XB%+15
*              STA   SB%+22
*              LDA   I
*              EXT   V$VIRNG
*              JSXB  V$VIRNG
*              DATA  21
*              DATA  22
*              DATA  14
*              TAX
*              LDA   ARRAY,X
*
*        A-REG IS RETURNED UNCHANGED IF IT IS IN RANGE
*
*        ERROR MESSAGE IS ISSUED AND RANGE_ERROR EXCEPTION
*           RAISED IF IT IS NOT IN RANGE


V$VIRNG  EQU   *
         LDX   XB%      GET OFFSET OF LOWER BOUND
         CAS   SB%,X    COMPARE VALUE TO THE LOWER BOUND
         JMP#  L5       IF >, MOVE ON TO TEST UPPER BOUND
         JMP#  L5       (SAME FOR =)
         STA   VALUE    IF <, BUILD ARGUMENT LIST AND REPORT ERROR
         LDA   SB%,X
         STA   LWBVAL
         PCL   LWBERR
         AP    VALUE,S     ACTUAL VALUE
         AP    LWBVAL,S    LOWER BOUND
         AP    XB%+2,S     SOURCE LINE NUMBER
         AP    SB%+18,*
         AP    XB%+16,SL   AND NAME OF ROUTINE

L5       EQU   *        BUILD A COLONY HERE
         LDX   XB%+1    GET OFFSET OF UPPER BOUND
         CAS   SB%,X    COMPARE VALUE TO THE UPPER BOUND
         JMP#  L6       IF >, WE REPORT AN ERROR
         RCB            OTHERWISE,
         JMP%  XB%+3    RETURN NORMALLY

L6       EQU   *
         STA   VALUE
         LDA   SB%,X
         STA   UPBVAL
         PCL   UPBERR   GENERATE AN INTELLIGIBLE ERROR MESSAGE
         AP    VALUE,S     CONTAINING THE INDEX VALUE
         AP    UPBVAL,S    THE ACTUAL UPPER BOUND
         AP    XB%+2,S     THE SOURCE LINE NUMBER
         AP    SB%+18,*
         AP    XB%+16,SL   AND THE NAME OF THE ERRANT ROUTINE



* V$VIUPB -- VARIABLE UPPER BOUND CHECK
*
*        CALLING SEQUENCE:
*              LOAD A WITH UPPER BOUND
*              STORE A IN THE CURRENT STACK FRAME
*              LOAD A WITH VALUE TO BE CHECKED
*              EXT   V$VIUPB
*              JSXB  V$VIUPB
*              DATA  OFFSET_OF_UPPER_BOUND_IN_FRAME
*              DATA  SOURCE_LINE_NUMBER
*
*        EXAMPLE:
*              EAXB  DISPLAY1,*
*              LDA   XB%+15
*              STA   SB%+22
*              LDA   I
*              EXT   V$VIUPB
*              JSXB  V$VIUPB
*              DATA  22
*              DATA  14
*              TAX
*              LDA   ARRAY,X
*
*        A-REG IS RETURNED UNCHANGED IF IT IS NOT GREATER THAN
*           THE UPPER BOUND
*
*        ERROR MESSAGE IS ISSUED AND RANGE_ERROR EXCEPTION
*           RAISED IF IT IS GREATER THAN THE UPPER BOUND


V$VIUPB  EQU   *
         LDX   XB%      GET OFFSET OF UPPER BOUND
         CAS   SB%,X    COMPARE VALUE TO THE UPPER BOUND
         JMP#  L7       IF >, WE REPORT AN ERROR
         RCB            OTHERWISE,
         JMP%  XB%+2    RETURN NORMALLY

L7       EQU   *
         STA   VALUE
         LDA   SB%,X
         STA   UPBVAL
         PCL   UPBERR   GENERATE AN INTELLIGIBLE ERROR MESSAGE
         AP    VALUE,S     CONTAINING THE INDEX VALUE
         AP    UPBVAL,S    THE ACTUAL UPPER BOUND
         AP    XB%+1,S     THE SOURCE LINE NUMBER
         AP    SB%+18,*
         AP    XB%+16,SL   AND THE NAME OF THE ERRANT ROUTINE



* V$VILWB -- VARIABLE LOWER-BOUND CHECK
*
*        CALLING SEQUENCE:
*              LOAD A WITH LOWER BOUND
*              STORE A IN THE CURRENT STACK FRAME
*              LOAD A WITH VALUE TO BE CHECKED
*              EXT   V$VILWB
*              JSXB  V$VILWB
*              DATA  OFFSET_OF_LOWER_BOUND_IN_FRAME
*              DATA  SOURCE_LINE_NUMBER
*
*        EXAMPLE:
*              EAXB  DISPLAY1,*
*              LDA   XB%+14
*              STA   SB%+21
*              LDA   I
*              EXT   V$VILWB
*              JSXB  V$VILWB
*              DATA  21
*              DATA  14
*              TAX
*              LDA   ARRAY,X
*
*        A-REG IS RETURNED UNCHANGED IF IT IS NOT LESS THAN
*           THE LOWER BOUND
*
*        ERROR MESSAGE IS ISSUED AND RANGE_ERROR EXCEPTION
*           RAISED IF IT IS LESS THAN THE LOWER BOUND


V$VILWB  EQU   *
         LDX   XB%      GET OFFSET OF LOWER BOUND
         CAS   SB%,X    COMPARE VALUE TO THE LOWER BOUND
         JMP#  L8       IF >, MOVE ON TO TEST UPPER BOUND
         JMP#  L8       (SAME FOR =)

         STA   VALUE    IF <, BUILD ARGUMENT LIST AND REPORT ERROR
         LDA   SB%,X
         STA   LWBVAL
         PCL   LWBERR
         AP    VALUE,S     ACTUAL VALUE
         AP    LWBVAL,S    LOWER BOUND
         AP    XB%+1,S     SOURCE LINE NUMBER
         AP    SB%+18,*
         AP    XB%+16,SL   AND NAME OF ROUTINE

L8       EQU   *
         JMP%  XB%+2    NORMAL RETURN



* LWBERR -- REPORT LOWER-BOUND RANGE ERROR

LWBERR   ECB   LWBERR$,,LWBVALP,4

         DYNM  LWBVALP(3),LWBP(3),LWBLINEP(3),LWBNAMEP(3)

LWBMSG   DATA  C'Range check failed (*i < *i)'  32 CHAR LIMIT ON LIT. SIZE
         DATA  C' on line *i of *v*n.'

LWBERR$  EQU   *
         ARGT

         CALL  PRINT    CHEAT; USE SWT PRINT ROUTINE TO DUMP ERROR MESSAGE
         AP    =1,S     (1 IS A FILE DESCRIPTOR FOR THE TERMINAL)
         AP    LWBMSG,S
         AP    LWBVALP,*S
         AP    LWBP,*S
         AP    LWBLINEP,*S
         AP    LWBNAMEP,*SL

         CALL  SIGNL$   RAISE A RANGE_ERROR EXCEPTION
         AP    COND,S      CHAR VARYING: 'RANGE_ERROR'
         AP    NULLP,S     NO STACK HEADER INFO
         AP    =0,S
         AP    NULLP,S     NO AUXILIARY INFO
         AP    =0,S
         AP    =0,SL       RETURN IS IMPOSSIBLE


* UPBERR -- REPORT UPPER-BOUND RANGE ERROR

UPBERR   ECB   UPBERR$,,UPBVALP,4

         DYNM  UPBVALP(3),UPBP(3),UPBLINEP(3),UPBNAMEP(3)

UPBMSG   DATA  C'Range check failed (*i > *i)'
         DATA  C' on line *i of *v*n.'

UPBERR$  EQU   *
         ARGT

         CALL  PRINT    CHEAT; USE SWT PRINT ROUTINE TO DUMP ERROR MESSAGE
         AP    =1,S     (1 IS A FILE DESCRIPTOR FOR THE TERMINAL)
         AP    UPBMSG,S
         AP    UPBVALP,*S
         AP    UPBP,*S
         AP    UPBLINEP,*S
         AP    UPBNAMEP,*SL

         CALL  SIGNL$   RAISE A RANGE_ERROR EXCEPTION
         AP    COND,S      CHAR VARYING: 'RANGE_ERROR'
         AP    NULLP,S     NO STACK HEADER INFO
         AP    =0,S
         AP    NULLP,S     NO AUXILIARY INFO
         AP    =0,S
         AP    =0,SL       RETURN IS IMPOSSIBLE

         END
