*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