*DECK     CSCPNT
USETEXT TEXTCS
USETEXT TEXTSS
USETEXT TXTAPSS 
PROC CSCPNT;
# TITLE CSCPNT - PREPARE NOP TEXT.   #
  
      BEGIN  # CSCPNT # 
# 
**    CSCPNT - PREPARE NOP TEXT.
* 
*     D. G. DEPEW.           82/05/18.
* 
*     THIS PROCEDURE PROCESSES TEXT LINES (TERMINAL TEXT) FROM THE
*     I-LAYER DESTINED FOR A NOP.  ITS FUNCTION IS TO FORMAT THE TEXT 
*     INTO A NETWORK BLOCK AND EITHER ISSUE IT, QUEUE IT OR DISCARD IT
*     AS APPROPRIATE. 
* 
*     PROC CSCPNT 
* 
*     ENTRY    WCBUF[0] = WORD COUNT WORD FROM ORIGINAL CONNECTION
*                         TRAFFIC QUEUE (*CNQ*) ENTRY (CONTAINS THE 
*                         INPUT ALLOWED FLAG).
*             ABHBUF[0] = APPLICATION BLOCK (EVENT) HEADER FOR THE TEXT 
*                         (BASED ARRAY *ABH* IN *TXTAPSS* POINTS HERE). 
*             MSGBUF[0] = DISPLAY CODED TEXT LINE (BASED ARRAY *APSM* 
*                         IN *TXTAPSS* POINTS HERE).
* 
*     EXIT    ONE OR MORE OF THE FOLLOWING DEPENDING UPON THE STATE OF
*             THE CONNECTION, WHETHER APPLICATION BLOCK LIMIT HAS BEEN
*             REACHED, AND WHETHER THE CONNECTION HAS BEEN INITIALIZED: 
*              - A NETWORK DATA BLOCK FOR THE TEXT HAS BEEN PLACED IN 
*                THE OUTGOING TRAFFIC QUEUE (*OTQ*).
*              - THE TEXT HAS BEEN PLACED IN THE WAITING BLOCK QUEUE
*                (*WBQ*) PENDING RECEIPT OF A BLOCK ACKNOWLEDGEMENT OR
*                A FLOW CONTROL INITIALIZED SM FOR THE CONNECTION.
*              - THE TEXT HAS BEEN DISCARDED. 
*              - AN FC/RST/SM HAS BEEN PLACED IN THE *OTQ* FOLLOWED BY
*                A NETWORK *MSG* DATA BLOCK CONSISTING OF THE MESSAGES
*                *OUTPUT DISCARDED* FOLLOWED BY *READY..*.
*              - A CON/CB SM HAS BEEN FORMATTED AND PLACED IN THE 
*                PROTOCOL EVENT QUEUE (*PEQ*).
* 
*     NOTES   1. TO INSURE PROPER CURSOR POSITIONING AT A NOP TERMINAL
*                UNDER ALL CIRCUMSTANCES, CS USES THE POST PRINT FORMAT 
*                EFFECTOR *.* (PERIOD).  HOWEVER, THE I-LAYER GENERATES 
*                TEXT IN ONE FORMAT, IRRESPECTIVE OF FOR WHOM THE TEXT
*                IS DESTINED (HOP OR A NOP), AND THIS EXCLUDES FORMAT 
*                EFFECTORS.  HENCE, THIS ROUTINE MUST RIGHT SHIFT EACH
*                TEXT MESSAGE ONE CHARACTER AND INSERT THE FORMAT 
*                EFFECTOR IN THE LEADING CHARACTER POSITION.
*             2. PROCESSING IS IN ACCORDANCE WITH THE CS/NOP C-LAYER
*                STATE DIAGRAM. 
# 
  
# 
****  PROC CSCPNT - XREF LIST.
# 
      XREF
        BEGIN 
        PROC MOVE;         # MOVE STORAGE DIRECT ADDRESSING          #
        PROC SSBSBF;         # STORE BITFIELD                          #
        PROC SSTAQE;         # ACCEPT QUEUE ENTRY                      #
        PROC SSTETS;         # ENLARGE TABLE SPACE (ANYWHERE IN TABLE) #
        END 
# 
****
# 
  
  
      DEF  ODTLW$  #2#;      # *OUTPUT DISCARDED* TEXT LENGTH IN WORDS #
      DEF  RTLW$   #1#;      # *READY..* TEXT LENGTH IN WORDS          #
  
  
      ITEM I;                # LOOP INDUCTION VARIABLE                 #
      ITEM NACN;             # NOP ACN = ORDINAL OF ACN LIST ENTRY     #
      ITEM TLW;              # LENGTH OF TEXT IN CM WORDS              #
  
#     ITEMS BELOW ARE USED TO SHIFT TEXT RT ONE CHAR FOR FE INSERTION. #
  
      ITEM SWP;              # STORE WORD POSITION                     #
      ITEM SBP;              # STORE BIT POSITION (WITHIN *SWP*)       #
  
  
  
# 
*     MESSAGE ARRAYS WITH LEADING ZEROES AS FORMAT EFFECTORS. 
# 
      ARRAY DISCARD [00:00] S(ODTLW$);
        BEGIN 
        ITEM D$WD0      U(00,00,60);
        ITEM D$WD1      U(01,00,60);
        ITEM D$TEXT     C(00,00,17) = [".OUTPUT DISCARDED"];
        ITEM D$LT       U(01,42,18) = [0];
        END 
  
      ARRAY READY [00:00] S(RTLW$); 
        BEGIN 
        ITEM R$WD0      U(00,00,60);
        ITEM R$TEXT     C(00,00,08) = [".READY.."]; 
        ITEM R$LT       U(00,48,12) = [0];
        END 
  
  
  
  
  
CONTROL EJECT;
  
PROC SENDATA; 
  
      BEGIN  # SENDATA #
# 
*     SENDATA - SEND NETWORK DATA BLOCK TO A NOP. 
* 
*     THIS EMBEDDED PROC EITHER OUTPUTS OR ENQUEUES A SINGLE BLOCK OF 
*     NOP TEXT DEPENDING UPON WHETHER THE NOP'S CONNECTION IS CURRENTLY 
*     AT APPLICATION BLOCK LIMIT, AND WHETHER THE CONNECTION HAS BEEN 
*     INITIALIZED.
* 
*     PROC SENDATA
* 
*     ENTRY         TLW = LENGTH OF TEXT IN CM WORDS. 
*              WCBUF[0] = AS ABOVE IN MAIN PROC DESCRIPTION.
*             ABHBUF[1] = PARTIALLY COMPLETED APPLICATION BLOCK HEADER
*                         FOR THE TEXT.  THE APPLICATION BLOCK TYPE HAS 
*                         BEEN FILLED IN. 
*               APSM[1] = THE TEXT IN NETWORK BLOCK FORMAT WITH FORMAT
*                         EFFECTORS IN PLACE (2ND HALF OF *MSGBUF*).
*             THE STATE OF THE NOP'S CONNECTION IS SUCH THAT IT IS OK 
*             TO ISSUE NETWORK DATA BLOCKS. 
* 
*     EXIT    1. IF THE NOP"S  CONNECTION HAS BEEN INITIALIZED (FC/INIT 
*                RECEIVED) AND IT IS NOT AT APPLICATION BLOCK LIMIT,
*                THE BLOCK HAS BEEN PLACED IN THE OUTGOING TRAFFIC
*                QUEUE (*OTQ*). 
*             2. IF THE NOP"S CONNECTION HAS NOT BEEN INITIALIZED OR IT 
*                IS AT APPLICATION BLOCK LIMIT, THE BLOCK HAS BEEN
*                PLACED IN THE WAITING BLOCK QUEUE (*WBQ*) AS FOLLOWS:  
*                - IF, UPON ENTRY, THERE WAS AN EXISTING *WBQ* ENTRY
*                  FOR THIS NOP AND IF THE TEXT LENGTH OF THAT ENTRY
*                  PLUS THE TEXT LENGTH OF THE NEW BLOCK DID NOT EXCEED 
*                  THE RECOMMENDED BLOCK SIZE FOR THE CONNECTION (*DBZ* 
*                  IN CON/REQ/SM), THE NEW BLOCK WAS ADDED TO THE END 
*                  OF THAT EXISTING *WBQ* ENTRY.
*                - IF, UPON ENTRY, THERE WAS NO *WBQ* ENTRY FOR THIS
*                  NOP OR IF THE TEXT LENGTH OF THAT ENTRY PLUS THE 
*                  TEXT LENGTH OF THE NEW BLOCK EXCEEDED THE
*                  RECOMMENDED BLOCK SIZE, A NEW *WBQ* ENTRY FOR THIS 
*                  NOP WAS CREATED. 
* 
*     NOTE    NOP ENTRIES IN THE *WBQ* ARE IN NETWORK DATA BLOCK FORMAT 
*             AND MAY BE MOVED TO THE *OTQ* WITHOUT MODIFICATION. 
# 
  
      ITEM AORD;             # ORDINAL WHERE BLOCK IS INSERTED IN *WBQ*#
      ITEM WBC;              # WAITING BLOCK COUNT                     #
      ITEM WORD;             # WAITING BLOCK QUEUE ENTRY ORDINAL       #
  
  
  
# 
*     FIRST COMPLETE THE APPLICATION BLOCK HEADER FOR THE OUTGOING TEXT,
*     EXCEPT FOR THE BLOCK NUMBER.  ALSO, SET THE QUEUE ENTRY SIZE. 
# 
      ABHADR[1] = NACN; 
      ABHACT[1] = CT6DISPLAY; 
      ABHTLC[1] = TLW * 10; 
      WCB$WORD[1] = TLW + 2;
  
  
# 
*     CHECK FOR CONNECTION INITIALIZED AND APPLICATION BLOCK LIMIT AND
*     TAKE THE APPROPRIATE ACTION (AS HAS BEEN DESCRIBED).
# 
      IF ACN$INIT[NACN] 
        AND ACN$BLCNT[NACN] LS ACN$ABL[NACN]
      THEN                             # CAN SEND BLOCK IMMEDIATELY    #
        BEGIN 
        ABHABN[1] = ACN$ABN[NACN];               # ABH COMPLETE        #
        ACN$ABN[NACN] = ACN$ABN[NACN] + 1;       # NEXT BLOCK NUMBER   #
        ACN$BLCNT[NACN] = ACN$BLCNT[NACN] + 1;   # OUTSTANDING BLOCKS  #
        SSTAQE (P<OTQ>, WCBUF[1], ABHBUF[1], MSGBUF[MSBFAPL]);
        END 
  
  
      ELSE                   # MUST ENQUEUE BLOCK IN *WBQ*             #
        BEGIN 
  
# 
*       THE FIRST TASK IS TO LOCATE THE LAST *WBQ* ENTRY FOR THIS NOP 
*       (IF THERE IS ONE).  THE SEARCH TECHNIQUE EMPLOYED RESULTS IN
*       *AORD* POINTING TO THE NEXT *WBQ* ENTRY AFTER THE DESIRED ENTRY.
*       THIS IS THE CORRECT ORDINAL AT WHICH TO ADD THE NEW BLOCK TO
*       THE EXISTING *WBQ* ENTRY, IF THAT IS APPROPRIATE. 
# 
        WBC = 0;
        WORD = 0; 
        FOR AORD=0  STEP WBQ$ESIZE[AORD]
          WHILE WBC LS ACN$WBCNT[NACN]
        DO                             # FIND LAST ENTRY FOR THIS NOP  #
          IF WBQ$ABHACN[AORD] EQ NACN 
          THEN                         # THIS ENTRY FOR THIS NOP       #
            BEGIN 
            WBC = WBC + 1;
            WORD = AORD;               # SAVE ORDINAL                  #
            END 
  
# 
*       IF A *WBQ* ENTRY EXISTS FOR THIS NOP AND IF THE NEW BLOCK CAN 
*       BE APPENDED TO THIS ENTRY WITHOUT EXCEEDING THE RECOMMENDED 
*       BLOCK SIZE, THEN ADD THE NEW BLOCK TO THE EXISTING *WBQ* ENTRY. 
*       OTHERWISE, CREATE A NEW *WBQ* ENTRY.
# 
        IF WBC NQ 0 
          AND (WBQ$TLC[WORD] + ABHTLC[1]) LQ ACN$DBZ[NACN]
          AND WBQ$ABT[WORD] EQ APPBLK 
        THEN                           # CAN APPEND TO EXISTING ENTRY  #
          BEGIN 
          SSTETS (P<WBQ>, AORD, TLW);                 # MAKE ROOM      #
          MOVE (TLW, MSGBUF[MSBFAPL], WBQ[AORD]);     # TEXT           #
          WBQ$ESIZE[WORD] = WBQ$ESIZE[WORD] + TLW;    # ENTRY SIZE     #
          WBQ$TLC[WORD] = WBQ$TLC[WORD] + ABHTLC[1];  # TEXT LENGTH    #
          IF WCB$IAF[0] 
          THEN                         # INPUT ALLOWED AFTER THIS TEXT #
            WBQ$ABT[WORD] = APMSG;     # ENSURE SAME FOR QUEUED BLOCK  #
          END 
  
        ELSE                 # MUST CREATE NEW *WBQ* ENTRY             #
          BEGIN 
          ABHABN[1] = ACN$ABN[NACN];             # ABH COMPLETE        #
          ACN$ABN[NACN] = ACN$ABN[NACN] + 1;     # NEXT BLOCK NUMBER   #
          ACN$WBCNT[NACN] = WBC + 1;             # WAITING BLOCKS      #
          SSTAQE (P<WBQ> , WCBUF[1], ABHBUF[1], MSGBUF[MSBFAPL]); 
          END 
  
        END                  # ENQUEUING IN *WBQ*                      #
  
      END  # SENDATA #
  
  
  
  
  
CONTROL EJECT;
  
# 
*     MAIN ROUTINE BEGINS HERE. 
* 
*     WE BEGIN BY INITIALIZING IMPORTANT LOCAL VARIABLES AS WELL AS THE 
*     APPLICATION BLOCK HEADER FOR THE OUTBOUND TEXT.  NEXT, THE TEXT 
*     IS RIGHT SHIFTED ONE CHARACTER POSITION AND THE POST PRINT FORMAT 
*     EFFECTOR (*.*) IS INSERTED.  AFTER THE SHIFT, WE INSURE THERE ARE 
*     SUFFICIENT ZERO BITS PRESENT TO CONSTITUTE A VALID LINE 
*     TERMINATOR. 
# 
      NACN = ABHADR[0]; 
      TLW = WCB$WC[0] - 2;
      ABHWORD[1] = 0; 
  
      IF TLW NQ 0 
      THEN                   # THERE IS TEXT - INSERT FORMAT EFFECTOR  #
        BEGIN 
        MSG$WORD[MSBFAPL] = O"57" *2**54;   # POST PRINT FORMAT EFFECT #
        SWP = MSBFAPL;                 # SECOND HALF OF *MSGBUF*       #
        SBP = 6;                       # ONE CHARACTER TO THE RIGHT    #
        FOR I=0  STEP 1  UNTIL TLW-1
        DO                             # RT SHIFT TEXT STRING ONE CHAR #
          SSBSBF (MSGBUF[0], SWP, SBP, 60, MSG$WORD[I]);
  
        IF MSG$ZERO[SWP-1] NQ 0 
        THEN                 # TOO FEW ZERO BITS FOR SHIFTED ZERO BYTE #
          BEGIN 
          MSG$WORD[SWP] = 0;           # MAKE 66 BIT LINE TERMINATOR   #
          TLW = TLW + 1;
          END 
        END                  # FORMAT EFFECTOR INSERTION               #
  
  
  
# 
*     NOW TAKE A MAIN BRANCH DEPENDING UPON WHETHER INPUT IS ALLOWED ON 
*     THIS CONNECTION AFTER THIS TEXT HAS BEEN OUTPUT.
# 
      IF WCB$IAF[0] 
      THEN                   # COMMAND COMPLETE, INPUT ALLOWED         #
        BEGIN 
        ABHABT[1] = APMSG;
  
  
# 
*       IF THIS NOP HAS A COMMAND IN PROGRESS, THE TEXT IS PROCESSED
*       NORMALLY.  IF HE HAD ENTERED A USER BREAK, THE TEXT IS IGNORED
*       AND AN FC/RST/SM IS SENT FOLLOWED BY THE *OUTPUT DISCARDED* 
*       MESSAGE.  THE STATE OF THE ACN IS RESET TO ALLOW SUBSEQUENT 
*       COMMANDS. 
# 
        IF ACN$NOPST[NACN] EQ S"COMMAND"
          OR ACN$NOPST[NACN] EQ S"BREAK"
        THEN                           # COMMAND OR BREAK IN PROGRESS  #
          BEGIN 
  
          IF ACN$NOPST[NACN] EQ S"BREAK"
          THEN                         # BREAK IN PROGRESS             #
            BEGIN 
            SPMSG0[1] = D$WD0[0];      # SET TEXT = *OUTPUT DISCARDED* #
            SPMSG1[1] = D$WD1[0]; 
            TLW = ODTLW$; 
            ACN$NOPST[NACN] = S"CLEARI";
            END 
          ELSE
            BEGIN 
            ACN$NOPST[NACN] = S"ACTIVE";
            END 
  
# 
*         NOW PROCESS THE TEXT.  THE I-LAYER NEVER GENERATES *READY..*. 
*         THIS IS GENERATED BY THE C-LAYER (HEREIN) AS A RESULT OF THE
*         INPUT ALLOWED FLAG BEING SET.  THE RESPONSE TO MANY COMMANDS
*         CONSISTS SOLELY OF *READY..* (NULL TEXT). 
# 
          MSG$WORD[MSBFAPL + TLW] = R$WD0[0];    # APPEND *READY..*    #
          TLW = TLW + 1;
          SENDATA;
          END 
  
  
        ELSE IF ACN$NOPST[NACN] EQ S"BROKEN"
        THEN
          BEGIN                        # CONECTION BROKEN IN PROGRESS  #
  
# 
*         WITH THIS TEXT THE I-LAYER HAS INDICATED ITS QUIESCENCE FOR 
*         THIS NOP.  HENCE, IT IS NOW APPROPRIATE TO SEND THE CON/CB TO 
*         THE I-LAYER FOR FINAL CLEANUP.  THE TEXT GETS DISCARDED.
# 
          WCB$WORD[0] = 2;             # MIN QUEUE ENTRY SIZE          #
          WCB$SMID[0] = SMID"CONCB";
          SSTAQE (P<PEQ>, WCBUF[0], ABHBUF[0], MSGBUF[0]);
          END 
  
        END                  # INPUT ALLOWED = YES                     #
  
  
  
      ELSE                   # INPUT NOT ALLOWED AS RESULT THIS TEXT   #
        BEGIN 
        ABHABT[1] = APPBLK; 
  
  
# 
*       IF THE STATE OF THE NOP"S CONNECTION IS APPROPRIATE, PROCESS
*       THE TEXT NORMALLY.  OTHERWISE, DISCARD IT.
# 
        IF ACN$NOPST[NACN] EQ S"ACTIVE" 
          OR ACN$NOPST[NACN] EQ S"COMMAND"
          OR ABHBRK[0] EQ 1 
        THEN                           # OK TO SEND TEXT               #
          BEGIN 
          ABHBRK[0] = 0;
  
          SENDATA;
          END 
  
        END                  # INPUT ALLOWED = NO                      #
  
      END  # CSCPNT # 
  
      TERM
