!***COPYRIGHT (C) 1974, 1975, 1976, 1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.*** MODULE OPR(RESERVE(#11, #12, #13, #14), SREG = #17, FREG = #16, DREGS = 4, VREG = #15, MLIST, TIMER = EXTERNAL(SIX12), FSAVE ) = BEGIN REQUIRE DATA.BLI; ! EVERYONE NEEDS THIS EXTERNAL CHKSRCTAB, CHKLFTAB, XTRIM, XDITEIT, XDOEO, XDOEOSRC, XDOEOLF, DPORT, DPORTS, DTERM, DTERMS, DNODE, DNODES, DNET, DNETS, QHASH, FINDPORT, BUILD, CHAIN, NEXTINTSN, INLOGMSG, DCHNKS, INSERT, LINK, UNLINK, INCREMENT, WAITCANCEL, PURGEO, KILGROUP; COMMENT; ! MCSOPR.BLI ! ====== === ! ROUTINE OPRTSEND ! ======= ======== ! THIS ROUTINE PROCESS THE OPERATOR SENDS TO TERMINALS GLOBAL ROUTINE OPRTSEND( TERMBLKPTR, CHUNKPTR ) = BEGIN REGISTER SRCPTR, UDX; MAP FORMAT SRCPTR; IF .TERMBLKPTR EQL 0 THEN ! DO ALL TERMINALS? BEGIN ! YES SRCPTR _ .SRCTAB + 1; ! THEN START AT THE BEGINNING OF THE SRC TABLE WHILE .SRCPTR[ S0IDW ] NEQ 0 DO ! AND UNTIL THE END DO BEGIN IF (UDX _ .SRCPTR[ S0PORTPTR ]) NEQ 0 THEN !IF CONNECTED OUTMSG(.CHUNKPTR,.UDX,TRUE,FALSE); !OUTPUT IT SRCPTR _ .SRCPTR + .S0SIZE !STEP TO NEXT TERMINAL END END ELSE IF ( SRCPTR _ CHKSRCTAB( .TERMBLKPTR ) ) EQL 0 THEN RETURN 1 ! NOT ALL SO GET POINTER ! TO THE RECIPIENT OF THIS MESSAGE ! IF BAD LEAVE NOW ELSE IF (UDX _ .SRCPTR[ S0PORTPTR ]) EQL 0 THEN RETURN 2 ELSE OUTMSG(.CHUNKPTR,.UDX,TRUE,FALSE); !OUTPUT IT 0 ! GOOD RETURN END; COMMENT; ! ROUTINE OPRDI ! ======= ===== ! THIS ROUTINE PERFORMS THE OPERATORS REQUEST TO DISABLE INPUT GLOBAL ROUTINE OPRDI( ARGBLK ) = BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; IF .ARGBLK EQL 0 THEN ! DISABLE ALL? BEGIN ! YES THEN NODEPTR _ ( TREE + 2 )<0,0>; ! GET THE FIRST NODE OF THE TREE DO TRIM( .NODEPTR ) WHILE ( NODEPTR _ .NODEPTR[ N0SAMND ] ) NEQ 0 END ELSE ! NOT ALL SO IF ( NODEPTR _ QHASH( .ARGBLK ) ) EQL 0 THEN RETURN FALSE ! IF NODE BAD RETURN FALSE ELSE TRIM( .NODEPTR ); ! OTHERWISE TRIM IT TRUE END; COMMENT; ! ROUTINE OPREI ! ======= ===== ! THIS ROUTINE PERFORMS THE OPERATORS REQUEST TO ENABLE INPUT GLOBAL ROUTINE OPREI( ARGBLK ) = BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; IF .ARGBLK EQL 0 THEN ! ENABLE ALL? BEGIN ! YES THEN NODEPTR _ ( TREE + 2 )<0,0>; ! GET THE FIRST NODE OF THE TREE DO UNTRIM( .NODEPTR ) WHILE ( NODEPTR _ .NODEPTR[ N0SAMND ] ) NEQ 0 END ELSE ! NOT ALL SO IF ( NODEPTR _ QHASH( .ARGBLK ) ) EQL 0 THEN RETURN FALSE ! IF NODE BAD RETURN FALSE ELSE UNTRIM( .NODEPTR ); ! OTHERWISE UNTRIM IT TRUE END; COMMENT; ! ROUTINE OPRDIT ! ======= ====== ! THIS ROUTINE PERFORMS THE OPERATOR'S DISABLE INPUT TERMINAL COMMAND GLOBAL ROUTINE OPRDIT( TERMBLKPTR, NODEBLKPTR ) = BEGIN IF .TERMBLKPTR EQL 0 THEN RETURN 1; ! IF NO TERMINAL GIVEN RETURN ERROR 1 SELECT XDITEIT( .TERMBLKPTR, .NODEBLKPTR, 1 %DISABLE% ) OF NSET ! DISABLE THE TERMINAL AND CHECK WHAT XDITEIT RETURNS STSGOOD: RETURN 0; ! EVERYTHING OK STSILLQNAME: RETURN 2; ! BAD NODE SPECIFIED STSUNKDST: RETURN 1; ! BAD TERMINAL GIVEN STSSRCNOTASS: RETURN 3; !SOURCE NOT ASSOC.WITH TERM OTHERWISE: INFORM( PAZ 'FXDITEIT RETURNED UNKNOWN VALUE IN OPRDIT@',0,0,0,0,0); ! SOMEONE BLEW IT TESN END; COMMENT; ! ROUTINE OPREIT ! ======= ====== ! THIS ROUTINE PERFORMS THE OPERATOR'S ENABLE INPUT TERMINAL COMMAND GLOBAL ROUTINE OPREIT( TERMBLKPTR, NODEBLKPTR ) = BEGIN IF .TERMBLKPTR EQL 0 THEN RETURN 1; ! IF NO TERMINAL GIVEN RETURN ERROR 1 SELECT XDITEIT( .TERMBLKPTR, .NODEBLKPTR, 0 %ENABLE% ) OF NSET ! ENABLE THE TERMINAL AND CHECK WHAT XDITEIT RETURNS STSGOOD: RETURN 0; ! EVERYTHING OK STSILLQNAME: RETURN 2; ! BAD NODE SPECIFIED STSUNKDST: RETURN 1; ! BAD TERMINAL GIVEN STSSRCNOTASS: RETURN 3; !SOURCE NOT ASSOC. WITH TERM OTHERWISE: INFORM( PAZ 'FXDITEIT RETURNED UNKNOWN VALUE IN OPREIT@',0,0,0,0,0); ! SOMEONE BLEW IT TESN END; FORWARD DOEOALLTERM, DOEOALLLEAF; COMMENT; ! ROUTINE OPRDO ! ======= ===== ! THIS ROUTINE PERFORMS THE OPERATORS REQUEST TO DISABLE OUTPUT GLOBAL ROUTINE OPRDO( TERMARGBLK, TYPEFLAG ) = BEGIN IF .TERMARGBLK EQL 0 THEN ! DISABLE ALL? BEGIN SELECT .TYPEFLAG OF NSET ! YES THEN DEPENDING UPON TYPEFLAG 0: DOEOALLTERM( 1 %DISABLE% ); ! DISABLE ALL TERMINAL DESTINATIONS 1: DOEOALLLEAF( 1 %DISABLE% ); ! DISABLE ALL LEAF TYPE DESTINATIONS 2: ( DOEOALLTERM( 1 ); DOEOALLLEAF( 1 ) ); ! DISABLE ALL DESTINATIONS OTHERWISE: RETURN INFORM( PAZ 'FBAD TYPE GIVEN TO OPRDO ROUTINE@',0,0,0,0,0); ! SOMEONE BLEW IT TESN; TRUE ! RETURN GOODNESS END ELSE XDOEO( .TERMARGBLK, 1 %DISABLE% ) ! NOT ALL SO DISABLE ONE END; COMMENT; ! ROUTINE OPREO ! ======= ===== ! THIS ROUTINE PERFORMS THE OPERATORS REQUEST TO ENABLE OUTPUT GLOBAL ROUTINE OPREO( TERMARGBLK, TYPEFLAG ) = BEGIN IF .TERMARGBLK EQL 0 THEN ! ENABLE ALL? BEGIN SELECT .TYPEFLAG OF NSET ! YES THEN DEPENDING UPON TYPEFLAG 0: DOEOALLTERM( 0 %ENABLE% ); ! ENABLE ALL TERMINAL DESTINATIONS 1: DOEOALLLEAF( 0 %ENABLE% ); ! ENABLE ALL LEAF TYPE DESTINATIONS 2: ( DOEOALLTERM( 0 ); DOEOALLLEAF( 0 ) ); ! ENABLE ALL DESTINATIONS OTHERWISE: RETURN INFORM( PAZ 'FBAD TYPE GIVEN TO OPREO ROUTINE@',0,0,0,0,0); ! SOMEONE BLEW IT TESN; TRUE ! RETURN GOODNESS END ELSE XDOEO( .TERMARGBLK, 0 %ENABLE% ) ! NOT ALL SO ENABLE ONE END; COMMENT; ! ROUTINE DOEOALLLEAF ! ======= =========== ! THIS ROUTINE DISABLES OR ENABLES FOR OUTPUT ALL LEAF TYPE DESTINATIONS GLOBAL ROUTINE DOEOALLLEAF( FCN ) = BEGIN REGISTER I; MAP FORMAT LFTAB; I _ 1; ! START WITH 1 WHILE .LFTAB[L0DSTW(.I)] NEQ 0 DO ! UNTIL WE RUN OUT OF LFTAB ENTRIES BEGIN XDOEOLF( .I, .FCN); ! DISABLE OR ENABLE IT I _ .I + L0SIZE ! THEN TRY ANOTHER END END; COMMENT; ! ROUTINE DOEOALLTERM ! ======= =========== ! THIS ROUTINE DISABLES OR ENABLES FOR OUTPUT ALL TERMINAL TYPE DESTINATIONS ROUTINE DOEOALLTERM( FCN ) = BEGIN REGISTER SRCPTR; MAP FORMAT SRCPTR; SRCPTR _ .SRCTAB + 1; ! START AT THE BEGINNING OF THE SRC TABLE WHILE .SRCPTR[ S0IDW ] NEQ 0 DO ! AND UNTIL THE END DO BEGIN XDOEOSRC( .SRCPTR, .FCN ); ! DISABLE OR ENALE THE TERMINAL SRCPTR _ .SRCPTR + .S0SIZE ! GET NEXT IN TABLE END END; COMMENT; ! ROUTINE OPRCHK ! ======= ====== ! THIS ROUTINE PERFORMS THE OPERATOR FUNCTION ! FOR SET CHECKPOINT AND SET NOCHECKPOINT GLOBAL ROUTINE OPRCHK( LEAFARGBLK, FCN) = BEGIN REGISTER I; REGISTER LEAFPTR; MAP FORMAT LEAFPTR; IF .LEAFARGBLK EQL 0 THEN BEGIN DECR I FROM .N0LFNO-1 TO 0 DO BEGIN LEAFPTR _ .LFPTRTAB[.I]; !GET POINTER TO LEAF LEAFPTR[N0CHKPNT] _ .FCN; !SET TO DESIRED VALUE END; END ELSE BEGIN IF (LEAFPTR _ QHASH( .LEAFARGBLK)) EQL 0 THEN RETURN FALSE; IF .LEAFPTR[N0NXTND] NEQ 0 %IF NOT LEAF% THEN RETURN FALSE; %ELSE% LEAFPTR[N0CHKPNT] _ .FCN END; TRUE !RETURN GOOD VALUE END; COMMENT; ! ROUTINE WNET ! ======= ==== ! THIS ROUTINE EXECUTES THE WHAT NET COMMAND FOR THE OPERATOR GLOBAL ROUTINE WNET( TERMARGBLK ) = BEGIN REGISTER SRCPTR; IF .TERMARGBLK EQL 0 THEN DNETS() ! IF "WHAT NET /ALL" ELSE IF (SRCPTR _ CHKSRCTAB(.TERMARGBLK) ) EQL 0 THEN RETURN FALSE !RETURN FALSE BAD TERMINAL ELSE DNET( .SRCPTR ); !IF NOT, DO SPECIFIC TERMINALS TRUE !RETURN WITH GOOD RETURN END; COMMENT; ! ROUTINE WTERM ! ======= ===== ! THIS ROUTINE EXECUTES THE WHAT TERMIANL OPERATOR COMMAND GLOBAL ROUTINE WTERM( TERMARGBLK ) = BEGIN REGISTER SRCPTR; IF .TERMARGBLK EQL 0 THEN ! WHAT /ALL? DTERMS() ! YES DISPLAY ALL TERMINALS ELSE ! NO THEN IF ( SRCPTR _ CHKSRCTAB( .TERMARGBLK ) ) EQL 0 THEN RETURN FALSE ! GOOD TERMINAL SPECIFIED? ! NOT GOOD THEN RETURN FALSE ELSE DTERM( .SRCPTR ); ! OTHERWISE DISPLAY IT TRUE ! RETURN GOODNESS END; COMMENT; ! ROUTINE WPORT ! ======= ===== ! THIS ROUTINE EXECUTES THE WHAT PORT OPERATOR COMMAND FORWARD CHKPORTTAB; GLOBAL ROUTINE WPORT( PORTNAME ) = BEGIN REGISTER PORTPTR; IF .PORTNAME EQL 0 THEN ! WHAT /ALL? DPORTS() ! YES DISPLAY ALL PORTS ELSE ! NO THEN IF ( PORTPTR _ CHKPORTTAB( .PORTNAME ) ) EQL 0 THEN RETURN FALSE ! GOOD PORT SPECIFIED? ! NOT GOOD THEN RETURN FALSE ELSE DPORT( .PORTPTR ); ! OTHERWISE DISPLAY IT TRUE ! RETURN GOODNESS END; COMMENT; ! ROUTINE CHKPORTTAB ! ======= ======== ! THIS ROUTINE SEARCHES THE PORT TABLE (PORTTAB) FOR A MATCH TO THE ! PORTNAME IT IS GIVEN ! CALLED WITH: A PORTNAME ! RETURNS: A POINTER TO THE PORT TABLE OF THE PORT WITH THE ! MATCHING PORTNAME GLOBAL ROUTINE CHKPORTTAB(PORTNAME) = BEGIN REGISTER PORTADDR, PORTNAMEREG; MAP FORMAT PORTADDR; PORTNAMEREG _ .PORTNAME; ! PUT THE PORTNAME IN A REGISTER BECAUSE ! I DON'T TRUST BLISS' OPTIMIZER PORTADDR _ .PORTTAB; WHILE .PORTADDR[PT0NAMEW] NEQ .PORTNAMEREG DO ! UNTIL WE FIND THE PORT WE WANT BEGIN PORTADDR _ .PORTADDR + PT0SIZE; ! STEP TO THE NEXT PORT IF .PORTADDR[PT0NAMEW] EQL 0 THEN ! IF WE RUN OUT OF PORTS THEN RETURN 0 END; .PORTADDR ! ELSE RETURN WHAT WAS WANTED END; COMMENT; ! ROUTINE WNODE ! ======= ===== ! THIS ROUTINE EXECUTES THE WHAT NODE OPERATOR COMMAND GLOBAL ROUTINE WNODE( NODEARGBLK ) = BEGIN REGISTER NODEPTR; IF .NODEARGBLK EQL 0 THEN ! WHAT /ALL? DNODES() ! YES DISPLAY ALL NODES ELSE ! NO THEN IF ( NODEPTR _ QHASH( .NODEARGBLK ) ) EQL 0 THEN RETURN FALSE ! GOOD NODE SPECIFIED? ! NOT GOOD THEN RETURN FALSE ELSE DNODE( .NODEPTR ); ! OTHERWISE DISPLAY IT TRUE ! RETURN GOODNESS END; COMMENT; ! ROUTINE KMPP ! ======= ==== ! THIS ROUTINE IS CALLED BY THE KERNEL TO CLEAN UP WHEN AN MPP ! IS KILLED OUT FROM UNDER US BY THE OPERATOR OR JUST DIES FOR SOME ! REASON GLOBAL ROUTINE KMPP(JOBSLOT) = BEGIN REGISTER GHPTR, MHPTR, NEXT; LOCAL LEAFPTR; MAP FORMAT RECVQ; MAP FORMAT LEAFPTR; MAP FORMAT GHPTR; MAP FORMAT MHPTR; WAITCANCEL( .JOBSLOT ); ! MAKE SURE IT ISN'T WAITING PURGEO( .JOBSLOT ); ! PURGE OUTPUT ! FOR INPUT'D GROUPS:::: IF .RECVQ[R0FGH(.JOBSLOT)] EQL 0 THEN RETURN; ! IF NOTHING WAS RECEIVED BY THIS JOB THEN LEAVE NOW GHPTR _ .RECVQ[R0FGH(.JOBSLOT)]; !GET THE FIRST GH IN RECVQ UNTIL .GHPTR EQL 0 DO BEGIN LEAFPTR_.GHPTR[ G0LFPTR ]; NEXT _ .GHPTR[G0FORE]; IF NOT (.GHPTR[G0CHKPNT] OR .GHPTR[G0ONDSK]) THEN KILGROUP(.GHPTR,.JOBSLOT) !IF CAN'T RECOVER THE TRANSACTION, GIVE UP NOW ELSE ! OTHERWISE FIX UP & REQUEUE BEGIN IF .GHPTR[G0EMPTY] AND .GHPTR[G0OUTMH] NEQ 0 THEN DPAGE(.GHPTR[G0PADDR]^9); GHPTR[ G0OUTMH ] _ MHPTR _ .GHPTR[ G0FMHPTR ]; DO IF .MHPTR[M0CHNKS] NEQ 0 THEN DCHNKS(.MHPTR) WHILE (MHPTR_.MHPTR[M0FORE]) NEQ 0; UNLINK( RECVQ[ R0GHS( .JOBSLOT ) ], .GHPTR ); ! REMOVE THE GROUP FROM THE RECVQ GHPTR[G0EMPTY]_GHPTR[G0RECEIVING]_GHPTR[G0FINISHED]_GHPTR[G0LINK]_0; GHPTR[ G0ONDSK ]_TRUE; LINK( LEAFPTR[ N0GHS ], .GHPTR ); ! REQUEUE LEAFPTR[ N0TSCORE ] _ .LEAFPTR[ N0TSCORE ] - 1; !THIS TRANSACTION IS NOT IN CORE INCREMENT( .LEAFPTR, 1) END; GHPTR _ .NEXT !GET THE NEXT GH IN RECVQ. END END; COMMENT; ! ROUTINE CHGALT ! ======= ====== ! THIS ROUTINE SWITCHES A TERMINAL TO THE NEXT ALTERNATE GLOBAL ROUTINE CHGALT( TERMARGBLK, RESETFLAG ) = BEGIN REGISTER SRCPTR; MAP FORMAT SRCPTR; MACRO CURALT = (.SRCPTR[ S0ALTPTR ] )< IF .SRCPTR[ S0RIGHTALT ] THEN RIGHT ELSE LEFT, HALFWORD >$, NEXTALT = IF (SRCPTR[S0RIGHTALT]_NOT .SRCPTR[S0RIGHTALT]) EQL 0 THEN INC(SRCPTR[S0ALTPTR],1)$; IF .TERMARGBLK EQL 0 THEN RETURN FALSE; ! IF TERMINAL NAME NOT GIVEN LEAVE NOW IF ( SRCPTR _ CHKSRCTAB( .TERMARGBLK ) ) EQL 0 THEN RETURN FALSE; ! IF TERMINAL NAME UNKNOWN LEAVE NOW IF .SRCPTR[ S0ALTPTR ] EQL 0 THEN RETURN FALSE; ! IF NO ALTERNATES LEAVE NOW IF NOT .RESETFLAG THEN ! IF NOT RESETTING THE PRIMARY TERMINAL THEN BEGIN IF .CURALT EQL 0 THEN RETURN FALSE; ! IF NO MORE ALTERNATES LEAVE WITH BAD IF .SRCPTR[ S0SELF ] THEN SRCPTR[ S0RIGHTALT ] _ SRCPTR[ S0SELF ] _ FALSE ! SET NOT RIGHT ALTERNATE & NO SELF ELSE NEXTALT; RETURN TRUE ! RETURN GOODNESS END; ! RESETTING TO THE PRIMARY TERMINAL SO WHILE .CURALT NEQ 0 DO NEXTALT; ! FIND THE LAST ENTRY NEXTALT; ! THE NEXT WITH POINTS TO THE FIRST SRCPTR[ S0ALTPTR ] _ CURALT; ! GET THE FIRST ALTERNATE SRCPTR[ S0RIGHTALT ] _ FALSE; ! MAKE FIRST ALTERNATE ON LEFT SRCPTR[ S0SELF ] _ TRUE %NOTE::::: NO SEMICOLON% ! MAKE SELF AGAIN END; COMMENT; ! ROUTINE SETQUOTA ! ======= ======== ! THIS ROUTINE PERFORMS THE OPERATOR SET QUOTA COMMAND GLOBAL ROUTINE SETQUOTA( ARGBLK, N ) = BEGIN REGISTER LEAFPTR; MAP FORMAT LEAFPTR; IF .ARGBLK EQL 0 THEN RETURN FALSE; ! IF NO QUEUE SPECIFIED RETURN FALSE IF ( LEAFPTR _ QHASH( .ARGBLK ) ) EQL 0 THEN RETURN FALSE; ! IF BAD QUEUE NAME RETURN FALSE IF .LEAFPTR[ N0NXTND ] NEQ 0 THEN RETURN FALSE; ! IF NOT LEAF RETURN BADNESS IF .N LSS 0 THEN RETURN FALSE; LEAFPTR[ N0QUOTA ] _ .N; TRUE END; COMMENT; ! ROUTINE SETTHRESHOLD ! ======= ============ ! THIS ROUTINE PERFORMS THE OPERATOR SET THRESHOLD COMMAND GLOBAL ROUTINE SETTHRESHOLD( ARGBLK, N ) = BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; IF .ARGBLK EQL 0 THEN RETURN FALSE; ! IF NO QUEUE SPECIFIED RETURN FALSE IF ( NODEPTR _ QHASH( .ARGBLK ) ) EQL 0 THEN RETURN FALSE; ! IF BAD QUEUE NAME RETURN FALSE IF .N LEQ 0 THEN RETURN FALSE; NODEPTR[ N0THRESH ] _ .N; TRUE END; COMMENT; ! ROUTINE SETRUN ! ======= ====== ! THIS ROUTINE EXECUTES THE OPERATOR SET MPP TO RUN AT NODE TO MPP GLOBAL ROUTINE SETRUN( NODENAME, MPPINDEX ) = BEGIN REGISTER NODEPTR; MAP FORMAT NODEPTR; IF .NODENAME EQL 0 THEN RETURN 1; ! THE NODE NAME MUST BE SPECIFIED IF ( NODEPTR _ QHASH( .NODENAME ) ) EQL 0 THEN RETURN 1; NODEPTR[ N0MPP ] _ .MPPINDEX; ! SET THIS ONE 0 END; COMMENT; !ROUTINE CPORT !======= ===== ! THIS ROUTINE MAPS THE PORT JUST CONNECTED TO A LOGICAL TERMINAL GLOBAL ROUTINE CPORT(PORT)= BEGIN REGISTER SRCPTR; REGISTER MSGCHUNKS; MAP FORMAT PORT; MAP FORMAT SRCPTR; EXTERNAL OUTMSG; EXTERNAL MAKEMSG; EXTERNAL MCSNAM; IF (SRCPTR _ .PORT[PT0SRCPTR]) EQL 0 THEN SRCPTR _ .PORT[PT0TMPSRCPTR] ELSE IF .PORT[PT0UDX] NEQ 0 THEN BEGIN MSGCHUNKS _ MAKEMSG(PAZ 'Connected to %0A% as terminal %1A% %Z%?M?J@', MCSNAM<36,7>,SRCPTR[S0ID],0,0,0); OUTMSG(.MSGCHUNKS,.PORT[PT0UDX],FALSE,FALSE) END; IF .SRCPTR NEQ 0 THEN SRCPTR[S0PORTPTR]_.PORT[PT0UDX] END; COMMENT; !ROUTINE CUDX !======= ==== !THIS ROUTINE CHECKS TO SEE IF THERE IS AN !ENTRY IN THE SOURCE TABLE WITH A GIVEN !UDX...IF THERE IS IT,THE UDX IN THE SOURCE !TABLE,IS ZEROED GLOBAL ROUTINE CUDX(UDX)= BEGIN EXTERNAL RESETTERMINAL; REGISTER SRCPTR; MAP FORMAT SRCPTR; SRCPTR _ .SRCTAB + 1; WHILE .SRCPTR[S0PORTPTR] NEQ .UDX DO BEGIN SRCPTR_.SRCPTR+.S0SIZE; IF .SRCPTR[S0IDW] EQL 0 THEN RETURN END; RESETTERMINAL(.SRCPTR); SRCPTR[S0PORTPTR]_0 END; END; ! END OF MCSOPR.BLI