*DECK C$STRIN 
          IDENT  C$STRIN
          TITLE  CBSTRIN - PROCESS STRING STATEMENT 
  
          MACHINE  ANY,I
          COMMENT  PROCESS STRING STATEMENT 
          SST 
          B1=1
 C.STRNG  SPACE  4
* 
*         C.STRIN - PROCESS STRING STATEMENT
* 
*         CALLING SEQUENCE- 
*                RJ C.STRIN 
* 
*         INPUT 
*                B3 = RESULT ADDRESS
*                B4 = RESULT BCP (+ SUBSC CHAR OFFSET IF SUBSCRIPTED) 
*                B5 = PARAMETER LIST ADDRESS
*                B6 = LAST PARAMETER ADDRESS
*                X1 = POINTER VALUE IN BINARY 
*                X3 = RESULTLENGTH
* 
*         PARAMETER LIST
* 
*         VFD    6/TYPE,18/LENGTH,18/OFFSET,18/ADDRESS
*           REPEATED FOR EACH DELIMITER AND SOURCE OPERAND
* 
*      TYPE HAS THE FOLLOWING VALUES -
*      NOTE THAT IDENTIFIER DELIMITERS HAVE TYPES OF 40B AND ABOVE, 
*      OTHER OPERANDS ARE 37B AND BELOW, SO OBJECT ROUTINES CAN USE 
*      PL AND NG INSTRUCTIONS TO CHECK FOR DELIMITERS TO SEARCH FOR.
*         00B = ALPHANUMERIC OPERAND
*         20B = SIZE DELIMITER
*         60B = IDENTIFIER DELIMITER (ALSO INSPECT BEFORE DELIMITER)
* 
*         OUTPUT
*                B7 = 0 IF NO OVERFLOW
*                   = 1 IF OVERFLOW 
*                X1 = POINTER VALUE IN BINARY 
* 
*         USES -
*                C.MOVE,C.INSPT 
*                ASSUMES B1=1 
*                ALL REGISTERS EXCEPT A0,X0,A4,A2 
* 
*         PHILOSOPHY OF DESIGN
*         THE C.STRNG ROUTINE SHOULD DO AS MUCH OF THE STRING VERB
*         OPERATIONS AS POSSIBLE. IT SHOULD BE FAST AND AS SMALL AS 
*         POSSIBLE. NUMERIC OPERANDS ARE THE BANE OF THIS OPERATION.
*         SINCE THE POINTER IS THE ONLY NUMERIC OPERAND, AND THE STRING 
*         VERB IS EXPECTED TO BE USED RELATIVELY FEW TIMES WHEN IT IS 
*         USED, THE MOVES OF POINTER TO REGISTER AND REGISTER TO
*         POINTER ARE DONE IN-LINE, BEFORE AND AFTER THE OBJECT ROUTINE 
*         CALL RESPECTIVELY, RATHER THAN IN A COMPREHENSIVE NUMERIC 
*         MOVE SUBROUTINE. THE OTHER PROBLEM OPERATION IS ON-OVERFLOW 
*         PROCESSING. THIS IS SOLVED BY RETURNING THE POINTER AND 
*         LENGTH, AND DOING THE TEST IN-LINE. 
  
          EJECT 
*      FLOW CHART OF C.STRNG
  
*      <   PTR   >
*      <   BAD   >---YES---(  EXIT   )
*           I 
*  I------> I 
*  I        I 
*  I   [ GET OPND]
*  I   [ DO SUBSC]
*  I        I 
*  I        I 
*  I        I 
*  I   <  DELIM  >         [ SET UP  ]
*  I   <  PARAM  >---YES---[ INSPECT ]---------I
*  I        I                                  I
*  I        I                                  I
*  I        I                                  I
*  I   <  DELIM  >         [ INSPECT ]         I
*  I   < BY SIZE >---NO----[ CALL    ]         I
*  I        I                   I              I
*  I        I <-----------------I              I
*  I        I                                  I
*  I   < OVERFLOW>         [ SHORTEN ]         I
*  I   <         >---YES---[ OPERAND ]         I
*  I        I                   I              I
*  I        I <-----------------I              I
*  I        I                                  I
*  I   [  CALL   ]                             I
*  I   [  C.MOVE ]                             I
*  I        I                                  I
*  I        I                                  I
*  I        I                                  I
*  I   < OVERFLOW>                             I
*  I   <         >---YES---(  EXIT   )         I
*  I        I                                  I
*  I        I <--------------------------------I
*  I        I 
*  I   [ INC PARM]
*  I   [ ADDR    ]
*  I        I 
*  I        I 
*  I        I 
*  I   <   MORE  >
*  I---<  PARAMS >---NO----(  EXIT   )
  
          EJECT 
          ENTRY  C.STRIN
 C.STRIN  DATA   0
  
*      <   PTR   >
*      <   BAD   >---YES---(  EXIT   )
*           I 
  
*      CHECK IF POINTER VALUE INITIALLY OUT OF RESULT FIELD SIZE RANGE
  
          SX2    B1                * TEST FOR LESS THAN 1 
          IX2    X1-X2
          NG     X2,OVERFLOW
          SX2    X3+1              * TEST FOR GREATER THAN RESULT LENGTH
          IX2    X1-X2
          NG     X2,PTROKAY 
 OVERFLOW BSS    0
          SB7    B1 
          EQ     C.STRIN
  
 PTROKAY  BSS    0
  
          BX7    X3 
          SA7    RESLLENG    RESULT LENGTH
          SPACE  4
*      ADD POINTER - 1 TO RESULT ADDRESS. 
  
          SB4    X1+B4
          SB4    B4-B1
  
*      DECREMENT RESULT LENGTH BY POINTER - 1.
*      THIS, PLUS THE ABOVE, ELIMINATES THE RESULT CHARACTERS IN FRONT
*      OF THE CHARACTER THE POINTER POINTS TO.
  
          IX3    X3-X1
          SX3    X3+B1
  
*      FINISH RESULT FIELD SUBSCRIPT CALCULATIONS 
  
          RJ     =XSTRSUBS         * STRSUBS INPUT: B3 = ADDR, B4 = OFFS
                                   *    OUTPUT: B3 = NEW ADDR, B4 = BCP 
                                   *          USES: X2, X4, X5
  
*      SAVE REGISTER PARAMETERS SO C.INSPT AND C.MOVE CAN BE CALLED 
  
          SX7    B3 
          SA7    RESLADDR          * B3 = RESULT ADDRESS (MODIFIED) 
          SX7    B4 
          SA7    RESLBCP           * B4 = RESULT BCP (MODIFIED) 
          SX7    B5 
          SA7    PARMAD            * B5 = PARAMETER ADDRESS 
          SX7    B6 
          SA7    PARMEND           * B6 = LAST PARAMETER ADDRESS
          BX7    X3 
          SA7    RESLLNSV          * SAVE RESULT LENGTH FOR MAIN LOOP 
                                   * CHECKS 
  
          SPACE  4
*  I------> I 
*  I        I 
*  I   [ GET OPND]
*  I   [ DO SUBSC]
*  I        I 
*  I        I 
  
*      MAIN STRING SOURCE OPERAND LOOP. DOES--
*         GETS OPERAND AND SETS UP INSPECT CALL FOR DELIMITER 
*         CALLS C.INSPT IF DATA NAME DELIMITER
*         SETS UP OPERAND FOR C.MOVE
*         CALLS C.MOVE
*      X1 (POINTER) IS SAVED THROUGH THE LOOP 
  
*      GET OPERAND FROM PARAMETER LIST
  
 MAINLOOP BSS    0
          SA4    B5                * OPERAND IN X4
  
*      DECODE THE OPERAND INTO B3 (ADDR), B4 (OFFSET), AND B7 (LENGTH). 
  
          MX2    6                 * SAVE TYPE CODE ACROSS STRSUBS CALL 
          BX7    X2*X4
          SB3    X4                * B3 = ADDR
          LX4    24 
          SB7    X4                * B7 = LENGTH OF PARAMETER OPERAND 
          LX4    18 
          SB4    X4                * B4 = OFFSET
  
*      FINISH SUBSCRIPT CALCULATIONS
  
          RJ     =XSTRSUBS         * STRSUBS INPUT: B3 = ADDR, B4 = OFFS
                                   *    OUTPUT: B3 = NEW ADDR, B4 = BCP 
                                   *          USES: X2, X4, X5
  
          SPACE  4
*  I        I 
*  I   <  DELIM  >         [ SET UP  ]
*  I   <  PARAM  >---YES---[ INSPECT ]---------I
*  I        I                                  I
*  I        I                                  I
  
*      IF DELIMITER PARAMETER, SAVE TYPE AND SET UP C.INSPT PARAM 
  
          ZR     X7,OPPARAM        * OPERAND IF TYPE IS 0 
  
          SA7    DELTYPE           * SAVE DELIMITER TYPE
  
          SA4    B5                * SAVE DELIMITER FOR C.INSPT PARAM.
          BX7    X4                * DATA NAME DELIM TYPE IS SAME AS
          SA7    INSPDEL           * C.INSPT BEFORE SPEC BY DESIGN
  
*      SAVE DELIMITER LENGTH
  
          MX4    42 
          LX7    24 
          BX7    -X4*X7            * ISOLATE LENGTH FOR SAVING
          SA7    DELLENG           * SAVE LENGTH
  
          EQ     LOOPINCR          * GET NEXT PARAMETER 
  
          SPACE  4
*  I        I                                  I
*  I   <  DELIM  >         [ INSPECT ]         I
*  I   < BY SIZE >---NO----[ CALL    ]         I
*  I        I                   I              I
*  I        I <-----------------I              I
  
*      OPERAND PARAMETER--CALL C.INSPT IF DATA NAME DELIMITER.
*      THE SIMULATED INSPECT STATEMENT IS 
*         INSPECT OPERAND TALLYING CHARACTERS BEFORE DELIMITER. 
*      THE TALLY VALUE (OPERAND LENGTH TO BE STRUNG) IS RETURNED IN X2. 
  
 OPPARAM  BSS    0
  
  
*      C.INSPT WILL BE CALLED TO FIND OPERAND LENGTH, INSTEAD OF USING
*      LENGTH FIELD FROM OPERAND PARAMETER. 
*      EITHER WAY, THE LENGTH TO BE STRUNG IS IN B7.
  
          SX7    B3 
          SA7    SRCADDR           * SAVE SOURCE OPERAND ADDRESS
          SX7    B4 
          SA7    SRCBCP            * SAVE SOURCE OPERAND BCP
          SA5    DELTYPE
          PL     X5,SIZEDEL  SIZE DELIMITER 
  
*      SET UP C.INSPT REGISTER PARAMETERS 
  
                                   * B3 = ADDR OF ITEM TO INSPECT 
                                   * B4 = BCP OF ITEM TO INSPECT
          SB5    INSPPARM          * B5 = ADDR OF SIMULATED PARAM LIST
          SB6    B5+B1             * B6 = LAST SIMULATED PARAMETER
                                   * B7 = LENGTH OF ITEM TO INSPECT 
  
*      INSPECT STRING OPERAND FOR CHARACTERS BEFORE DELIMITER 
*      IF SCAN ITEM IS MORE THAN 10 CHARACTERS, USE LONG SCAN.
  
          SA5    DELLENG
          SX5    X5-11
          NG     X5,SHRTSCAN       * SHORT SCAN IF 10 CHARS OR LESS 
  
*      SCAN ITEM IS MORE THAN 10 CHARACTERS--USE LONG SCAN
  
          SB6    B6+2        LAST PARAM ADDRESS 
          SX0    B1 
          MX7    0
          SA7    LENGTH 
          RJ     =XC.INSPS
          SA2    LENGTH 
          SB7    X2 
          SA1    POINTER
          IX6    X1+X2
          SA6    A1 
          EQ     CHKLEN 
  
*      SCAN ITEM IS 10 CHARACTERS OR LESS--USE SHORT SCAN 
  
 SHRTSCAN BSS    0
  
          RJ     =XC.INSPF
  
          SB7    X2                * SAVE NEW LENGTH IN B7
  
          SPACE  4
*      INCREMENT THE POINTER BY THE NUMBER OF CHARACTERS TO BE MOVED. 
  
 SIZEDEL  BSS    0
          SX7    X1+B7             * INCREMENT POINTER
          SA7    POINTER           * SAVE ACROSS C.MOVE 
  
          SPACE  4
*  I        I                                  I
*  I   < OVERFLOW>         [ SHORTEN ]         I
*  I   <         >---YES---[ OPERAND ]         I
*  I        I                   I              I
*  I        I <-----------------I              I
  
*      AT THIS POINT, WE HAVE A SOURCE OPERAND LENGTH, BASED ON THE 
*      CURRENT DELIMITER. NOW, ENSURE THE RESULT FIELD IS NOT 
*      OVERFLOWED AND SHORTEN LENGTH IF NECESSARY.
*         X1 = POINTER (SAVED ACROSS C.INSPT) 
*         B7 = SOURCE OPERAND LENGTH
*         X3 = RESULT LENGTH (TO BE RESTORED) 
  
*      THE SOURCE LENGTH IS OKAY IF   LENGTH - RESULTLENGTH - 1 < 0 
  
 CHKLEN   BSS    0
          SA3    RESLLNSV 
          SX5    X3+B1
          SX2    B7 
          IX5    X2-X5             * NOW HAVE FULL EXPRESSION 
          NG     X5,LENGOKAY       * SKIP LENGTH CHANGE IF NEGATIVE 
  
*      THE LENGTH IS TOO LARGE. CHANGE IT TO RESULTLENGTH.
  
          SB7    X3 
  
          SPACE  4
*  I        I                                  I
*  I   [  CALL   ]                             I
*  I   [  C.MOVE ]                             I
*  I        I                                  I
*  I        I                                  I
  
*      AT THIS POINT, THE FINAL LENGTH TO BE MOVED HAS BEEN FOUND.
  
 LENGOKAY BSS    0
  
*      DECREMENT RESULT LENGTH BY NUMBER OF CHARACTERS MOVED
  
          SX2    B7 
          IX7    X3-X2
          SA7    RESLLNSV 
  
*      SET UP C.MOVE PARAMETERS 
  
          SA5    RESLADDR 
          SB3    X5                * B3 = ADDR OF RESULT
          SA5    RESLBCP
          SB4    X5                * B4 = BCP OF RESULT 
          SA5    SRCADDR
          SB5    X5                * B5 = ADDR OF SOURCE TO STRING
          SA5    SRCBCP 
          SB6    X5                * B6 = BCP OF SOURCE TO STRING 
  
                                   * B7 = LENGTH TO MOVE
  
          MX2    0                 * X2 = NUMBER OF SPACES TO APPEND
  
*      MOVE STRING SOURCE TO RESULT 
  
          RJ     =XC.MOVE          * DOESNT USE A0,X0,A2,A4 
                                   * OUTPUT: B3 = NEW ADDR, B4 = NEW BCP
  
*      SAVE INCREMENTED RESULT ADDRESS AND BCP
  
          SX7    B3 
          SA7    RESLADDR          * B3 = RESULT ADDRESS
          SX7    B4 
          SA7    RESLBCP           * B4 = RESULT BCP
  
*      RESTORE POINTER FOR POSSIBLE EXIT
  
          SA1    POINTER
  
          SPACE  4
*  I        I                                  I
*  I   < OVERFLOW>                             I
*  I   <         >---YES---(  EXIT   )         I
*  I        I                                  I
  
*      EXIT IF OVERFLOW OCCURRED
  
          SA5    RESLLENG 
          SB7    X5                * PUT ORIGINAL RESULT LENGTH INTO B7 
          SB3    X1-1              * POINTER - 1  IN B3 
          GE     B7,B3,LOOPINCR 
          SX1    X5+B1       SET POINTER FOR OVERFLOW 
          EQ     OVERFLOW 
  
          SPACE  4
*  I        I <--------------------------------I
*  I        I 
*  I   [ INC PARM]
*  I   [ ADDR    ]
*  I        I 
*  I        I 
  
*      NO OVERFLOW, SO CHECK FOR MORE OPERANDS, EXIT IF DONE
  
 LOOPINCR BSS    0                 * FROM DELIMITER PROCESSING
  
          SA4    PARMAD            * CURRENT PARAMETER ADDRESS
          SA5    PARMEND           * LAST PARAMETER ADDRESS + 1 
  
          SPACE  4
*  I        I 
*  I   <   MORE  >
*  I---<  PARAMS >---NO----(  EXIT   )
  
          IX5    X5-X4
          ZR     X5,STREXIT        * EXIT WHEN CURRENT = LAST 
          SX7    X4+B1             * INCREMENT CURRENT PARAMETER ADDRESS
          SA7    PARMAD            * SAVE INCREMENTED PARAMETER ADDRESS 
  
          SB5    X7                * SAVE PARAM ADDR FOR MAIN LOOP
          EQ     MAINLOOP          * PROCESS NEXT PARAMETER 
  
          SPACE  4
*      C.STRNG EXIT POINT FOR ALL EXITS EXCEPT PRELIMINARY POINTER CHECK
  
 STREXIT  BSS    0
          SB7    B0 
  
          EQ     C.STRIN
  
          SPACE  3
 INCLEN   BSS    0
          SA1    LENGTH 
          SX7    X1+B1
          SA7    LENGTH 
          EQ     =XC.INSTE
          EJECT 
*      TEMPORARY SAVE AREA
  
*      INPUT PARAMETER TEMPS
  
 RESLADDR DATA   0                 * B3 = RESULT ADDRESS
 RESLBCP  DATA   0                 * B4 = RESULT BCP
 PARMAD   DATA   0                 * B5 = PARAMETER ADDRESS 
 PARMEND  DATA   0                 * B6 = LAST PARAMETER ADDRESS + 1
 POINTER  DATA   0                 * X1 = POINTER VALUE 
 RESLLENG DATA   0                 * X3 = RESULT LENGTH 
  
*      C.INSPT SIMULATED STATEMENT PARAMETER AREA.
*      THESE TWO ITEMS MUST BE IN THE ORDER--INSPPARM, INSPDEL
  
 INSPPARM VFD    6/0,54/0          * CHARACTERS SEARCH SPECIFICATION
 INSPDEL  DATA   0                 * BEFORE OPERAND 
          VFD    6/50B,36/0,18/INCLEN 
          VFD    6/51B,36/0,18/BEFORE 
  
 BEFORE   DATA   0                 * BEFORE BOUNDARY SAVE AREA FOR OBJ
  
  
 DELTYPE  DATA   0                 * CURRENT STRING DELIMITER TYPE
 DELLENG  DATA   0                 * DELIMITER LENGTH SAVE AREA 
  
*      MISCELLANEOUS TEMPS
  
 LENGTH   BSS    1
 SRCADDR  DATA   0                 * CURRENT PARAMETER SAVE 
 SRCBCP   DATA   0                 * (ACROSS C.INSPT) 
  
 RESLLNSV DATA   0                 * RESULT LENGTH FOR INCREMENTING 
  
          END                      * END OF C.STRNG 
