TITLE DTSCOM - Common Routines for DTS and DTR SUBTTL W. Nichols May, 1981 SEARCH JOBDAT,UUOSYM,SWIL,DTSPRM,MACTEN FTEXTRA==0 IFN FTEXTRA,SEARCH SCPAR EXTERNAL .ISCAN,.TYOCH ;ASSURE THAT SCAN COMES IN FOR LITTLES .REQUEST REL:SWIL EXTERNAL .LKWLD ;ASSURE THAT WILD COMES IN FOR E.LKEN .REQUEST REL:WILD .REQUEST REL:HELPER SALL .DIRECTIVE FLBLST ;DON'T GIVE ME CODE FOR ASCIZ ; This program conforms to the DTS specification version 1.1 ; published on 22 April 1981. ;Expand the INTERN/EXTERN macro from DTSPRM GLOBAL INTERNAL,EXTERNAL $RELOC $HIGH SUBTTL General Impure Storage $HIGH ;SHOULD ALREADY BE IN HISEG, BUT... PDLIOW::IOWD LN$PDL,DTSPDL ;IOWD TO LOAD INTO P UPON STARTUP $LOW DTSPDL::BLOCK LN$PDL+1 ;THE STACK CCLF1:: BLOCK 1 ;THE CCL ENTRY FLAG FOR .ISCAN TYPBOL::BLOCK 1 ;TYPOUT AT BEG OF LINE IF NON-ZERO TYPRCS::BLOCK 1 ;TYPOUT IS RECURSING IF NON-ZERO INIFF:: BLOCK 1 ;INITIAL VALUE OF .JBFF INICOR::BLOCK 1 ;INITIAL VALUE OF .JBREL CURCMD::BLOCK 1 ;CURRENT COMMAND NAME, FOR UNKCMD CHANEL::EXP -1 ;THE NSP. CHANNEL NUMBER ASSIGNED LOGSPC::BLOCK .FXLEN+1 ;SCAN BLOCK FOR LOG SPECIFICATION LOGFOP::BLOCK FOPLEN ;FILOP. BLOCK FOR LOG FILE LOGBRH::BLOCK 3 ;LOG FILE'S BUFFER RING HEADER LOGENT::BLOCK LN$ENT ;ENTER BLOCK FOR LOG SPEC LOGPTH::BLOCK .PTMAX ;PATH FOR .STOPB TO SET UP ERRPRI: BLOCK 1 ;NON-ZERO IF WE'RE PRINTING AN ERROR ALWPRI::BLOCK 1 ;NON-ZERO IF WE'RE PRINTING STATS LASTIM: BLOCK 1 ;USED BY GETTIM ;The User Data Block USRLEN==1+</4> ;STRING POINTER, COUNT+USER DATA(8-BIT) IFL USRLEN-STRLNW,USRLEN==STRLNW USERDA: STRBLK USRLEN ;A FREE STRING BLOCK FOR USER DATA CNTUSR: STRBLK USRLEN ;READ THE CONNECT/DISCONNECT DATA HERE RCVMSG: STRBLK MAXMGW ;THE DATA TEST'S RECEIVED MESSAGE PRCVMSG:POINT 8,RCVMSG+1 ;BYTE POINTER TO DATA TEST'S MESSAGE $HIGH CPRGID: EXP PRGID ;MACRO CAN'T STAND THIS IN A LITERAL ;Call: CHANEL/ The NSP. channel number ; CALL NSPREL ; Normal Return ; ;Uses T1,T2,T3,T4 NSPREL::SETO T1, ;MAKE A -1 TO COMPARE WITH CAMN T1,CHANEL ;IS IT OPEN? RET ;NO, DON'T NEED TO RELEASE IT. TRACE ,CRLF LDB T1,[POINTR(NSACH,NS.STA)] CAIE T1,.NSSRN ;IN RUN STATE? JRST NSPR.1 ;NO, HAVE TO RELEASE ;YES, WE SHOULD BE ABLE TO ABORT CALNSP .NSFAB,,NS.WAI ;FIRST, TRY ABORT TRNA ;FAILED, TRY RELEASE JRST NSPR.X ;SUCCESS RETURN CALL NSPERR ;FAILED, TELL USER WHY NSPR.1: CALNSP .NSFRL ;RELEASE (CLOSE) FUNCTION CALL NSPERR NSPR.X: SETOB NSACH,CHANEL ;THE CHANNEL IS NOW CLOSED CPOPJ: RET SUBTTL .STATUS - Read the Status of the Link ;.STATUS is called by the STATUS command ;TYPSTA is called by error handlers ;that have found strange states in NSP. returns. ; ;Call: CALL .STATUS ; Normal Return, message has been typed ; ;Uses T1,T2,T3,T4 DEFINE TYPSTB(bitname),< MOVEI T1,[ASCIZ ", bitname: "] CALLSCAN .TSTRG## LDB T1,[POINTR(NSACH,NS.'bitname)] CALLSCAN .TOCTW## > .STATUS:: SKIPGE CHANEL ;IS THE CHANNEL OPEN? JRST NOSTAT ;NO, TELL THEM NOTHING DOING TYPSTA::SAVEAC SKIPL CHANEL ;IS THE CHANNEL OPEN? CALL NSPSTS ;YES, GET STATUS INTO NSAA1 RET ;PROPOGATE ERROR RETURN LDB T1,[POINTR(NSACH,NS.STA)] CAILE T1,MAXSTA ;LEGAL STATE? MOVX T1,-1 ;NO, GET ERROR MESSAGE MOVE T1,STATAB(T1) CALL INFMSG ;OUTPUT AN INFO MESSAGE HEADER MOVEI T1,[ASCIZ / state/] CALLSCAN .TSTRG## TYPSTB NDA ;NORMAL DATA AVAIL TYPSTB NDR ;NORMAL DATA REQUESTS AVAIL TYPSTB IDA ;INTERRUPT DATA AVAIL TYPSTB IDR ;INTERRUPT DATA REQUESTS AVAIL CALLSCAN .TRBRK## ;A RIGHT SQUARE BRACKET FOR INFO CALLSCAN .TCRLF## RET ;"REPARSE" RETURN NOSTAT: ERROR ,CRLF RET ;Type out Flow Control value from T1 TYPFLO::CAIL T1,0 CAILE T1,3 MOVEI T1,4 ;UNKNOWN FLOW CONTROL TYPE MOVE T1,FLOTYP(T1) CALLSCAN .TSTRG## RET FLOTYP: [ASCIZ /Unknown/] [ASCIZ /None/] [ASCIZ /Segment/] [ASCIZ /Message/] [ASCIZ /Erroneous/] DEFINE STATE(code),< IFN .NSS'code-<.-STATAB>,PRINTX ?STATAB table wrong for code [ASCIZ /code/] > [ASCIZ /Too Big (illegal)/] ;-1 value used when state too big STATAB: [ASCIZ /Zero (illegal)/] STATE CW ;CONNECT WAIT STATE CR ;CONNECT RECEIVED STATE CS ;CONNECT SENT STATE RJ ;LINK WAS REJECTED STATE RN ;LINK IS UP AND RUNNING STATE DR ;DISCONNECT RECEIVED STATE DS ;DISCONNECT SENT STATE DC ;DISCONNECT CONFIRMED STATE CF ;NO CONFIDENCE STATE LK ;NO LINK STATE CM ;NO COMMUNICATION STATE NR ;NO RESOURCES MAXSTA==.-STATAB-1 ;NSPSTS - Get status of NSP channel into NSACH ; ;Call: CALL NSPSTS ; Error Return if NSP. UUO failed, message already output ; Normal Return with status in register NSACH ;This routine is expected to get the status and the other things ;that a read status function returns: seg size and flow control types. NSPSTS::CALNSP .NSFRS,NSAA2 ;READ STATUS FUNCTION CODE RET ;ERROR RETURN, LET USER ; ANNOUNCE IT IF S/HE WANTS RETSKP ;SUCCESS RETURN ;RDCNDT - Read Connect User Data ; ;Call: CALL RDCNDT ; Error Return, message already put out ; Normal Return, NSAxx and CNTUSR filled in, ; and NSAA1 holds pointer to CNTUSR ; NSAA2 holds Segment Size ; NSAA3 holds transmit flow control mode RDCNDT:: MOVEI NSAA1,CNTUSR ;PTR TO DIS/CONNECT USER DATA CALNSP .NSFRC,NSAA3 ;READ CONNECT DATA (NO WAIT) PJRST NSPERR RETSKP ;RDDSDT - Read Disconnect User Data ; ;Call: CALL RDDSDT ; Error Return, message already put out ; Normal Return, NSAxx and CNTUSR filled in, ; and NSAA1 holds pointer to CNTUSR ; NSAA2 holds Segment Size ; NSAA3 holds transmit flow control mode RDDSDT:: MOVEI NSAA1,CNTUSR ;PTR TO DIS/CONNECT USER DATA CALNSP .NSFRD,NSAA2 ;READ DISCONNECT DATA (NO WAIT) PJRST NSPERR RETSKP SUBTTL Error Routines ;NSPERR - Call this to interpret the error code from the NSP. UUO ;NSPERL - Same, but release the channel after printing the message ; ;Call: T1/ returned from NSP. ; CALL NSPERR/NSPERL ; Normal Return NSPERL::CALL NSPERR ;PRINT OUT THE ERROR PJRST NSPREL ;THEN RELEASE THE CHANNEL NSPERR::PUSH P,T1 ;SAVE ERROR FROM NSP. UUO WARN POP P,T1 ;GET NSP. ERROR MSG BACK CAIG T1,MAXERR ;DO WE KNOW THIS ERROR CODE? JRST [MOVEI T2,.TSTRG## MOVE T1,NSPERC(T1) JRST NSPER1] MOVEI T2,.TOCTW## ;NO, PRINT AS A OCTAL ERROR CODE NSPER1: CALL (T2) ;PRINT STRING OR NUMBER MOVEI T1,[ASCIZ /, function /] CALLSCAN .TSTRG## LDB T1,[POINTR(NSAFN,NS.AFN)] ;GET FUNCTION CODE FROM ARGS CAILE T1,FCNTBL ;OFFSET OK? MOVEI T1,0 ;NO, CALL IT ILLEGAL MOVE T1,FCNTAB(T1) ;GET PTR TO ASCIZ STRING CALLSCAN .TSTRG## ;TELL USER ABOUT FUNCTION CODE CALLSCAN .TCRLF## RET DEFINE ERRMAC(code,text),< IF1,,< PRINTX ?NSP. error code out of order in NSPERC table>> ERRMC1(\code,text) > DEFINE ERRMC1(code,text),<[ASCIZ |(code) text|]> NSPERC: ERRMAC 0, ERRMAC NSABE%, ERRMAC NSALF%, ERRMAC NSBCN%, ERRMAC NSBFT%, ERRMAC NSCFE%, ERRMAC NSIDL%, ERRMAC NSIFM%, ERRMAC NSILF%, ERRMAC NSJQX%, ERRMAC NSLQX%, ERRMAC NSNCD%, ERRMAC NSPIO%, ERRMAC NSPRV%, ERRMAC NSSTB%, ERRMAC NSUKN%, ERRMAC NSUXS%, ERRMAC NSWNA%, ERRMAC NSWRS%, ;New error codes (to be re-ordered): ERRMAC NSCBL%, ERRMAC NSPBL%, ERRMAC NSSBL%, ERRMAC NSUDS%, ERRMAC NSUDC%, ERRMAC NSUCF%, ERRMAC NSULK%, ERRMAC NSUCM%, ERRMAC NSUNR%, ;Error codes which correspond to DECnet disconnect codes. ERRMAC NSRBO%, ERRMAC NSDBO%, ERRMAC NSRES%, ERRMAC NSUNN%, ERRMAC NSRNS%, ERRMAC NSURO%, ERRMAC NSIOF%, ERRMAC NSOTB%, ERRMAC NSABM%, ERRMAC NSABO%, ERRMAC NSINF%, ERRMAC NSLNS%, ERRMAC NSACR%, ERRMAC NSNRO%, ERRMAC NSNUR%, ERRMAC NSNLK%, ERRMAC NSDSC%, ERRMAC NSIMG%, ERRMAC NSREJ%, ERRMAC NSBCF%, ERRMAC NSADE%,
; ERRMAC NSIMF%, MAXERR==.-NSPERC-1 DEFINE FCNMAC(code,text),< IFN code-<.-FCNTAB>, [ASCIZ /text/] > FCNTAB: FCNMAC 0, FCNMAC .NSFEA, FCNMAC .NSFEP, FCNMAC .NSFRI, FCNMAC .NSFAC, FCNMAC .NSFRJ, FCNMAC .NSFRC, FCNMAC .NSFSD, FCNMAC .NSFAB, FCNMAC .NSFRD, FCNMAC .NSFRL, FCNMAC .NSFRS, FCNMAC .NSFIS, FCNMAC .NSFIR, FCNMAC .NSFDS, FCNMAC .NSFDR, FCNMAC .NSFSQ, FCNMAC .NSFRQ, FCNMAC .NSFJS, FCNMAC .NSFJR, FCNMAC .NSFPI, FCNTBL==.-FCNTAB ;UNKCMD - Call this when .LKNAM fails to find a command ; ;Call: CURCMD/ Set up by LOOKNM ; T1/ The error code from .LKNAM ; CALL UNKCMD ; Normal Return, always ;Changes T1,T2,T3,T4 UNKCMD::MOVE T2,T1 ;COPY ERROR CODE FROM .LKNAM MOVEI T1,[ASCIZ \Unknown command: \] SKIPL T2 ;T2.LT.0 IF NOT MATCH MOVEI T1,[ASCIZ \Ambiguous command: \] PJRST ERRCMD ;ERRCMD - Type an error string followed by CURCMD ; ;Call: T1/ Ptr to ASCIZ string ; CALL ERRCMD ; Normal Return, always ERRCMD::SETOM ERRPRI ;ENABLE PRINT:ERROR CALL ERRMSG MOVE T1,CURCMD ;TYPE SIXBIT NAME SAVED BEFORE CALL CALLSCAN .TSIXN## ; TO .LKNAM CALLSCAN .TCRLF## PJRST ERWM.2 ;GO TO COMMON EXIT CODE ;xxxMSG - Type out a message, subject to /PRINT:xxx ; ;Call: T1/ Pointer to ASCIZ string, including CRLF if so desired ; CALL ERRMSG ; Normal Return ERRMSG::PUSH P,T1 ;SAVE ERROR MESSAGE PUSH P,["E"] SETOM ERRPRI ;ENABLE PRINT:ERROR MOVEI T1,"?" JRST ERWM.1 WRNMSG::PUSH P,T1 ;SAVE WARNING MESSAGE PUSH P,["W"] SETOM ERRPRI ;ENABLE PRINT:ERROR MOVEI T1,"%" JRST ERWM.1 IFN FTTRACE,< TRCMSG::PUSH P,T1 ;SAVE WARNING MESSAGE PUSH P,["I"] MOVEI T1,"[" JRST ERWM.1 > INFMSG::PUSH P,T1 ;SAVE INFO MESSAGE PUSH P,["I"] MOVEI T1,"[" ERWM.1: CALLSCAN .TCHAR## ;TYPE OUT ?,% OR [ MOVE T1,CPRGID ;GET 'DTS' OR 'DTR' CALLSCAN .TSIXN## ; (ITS IN SIXBIT) MOVEI T1,[ASCIZ / --/] CALLSCAN .TSTRG## POP P,T1 ;POP E,I OR W CALLSCAN .TCHAR## ;PRINT THE ERROR-TYPE CHARACTER MOVEI T1,[ASCIZ /-- /] CALLSCAN .TSTRG## POP P,T1 CALLSCAN .TSTRG## ERWM.2: SETOM .FLCBF## ;THERE WAS AN ERROR, CLEAR REST OF LINE RET ; WHEN WE NEXT REACH TOP LEVEL SUBTTL STYPIN - Special Typeing Routine for SCAN ;STYPIN - Called only by SCAN because of argument to .ISCAN call ; ;Call: CALL STYPIN ; Normal Return with char in C ; ;Saves all ACs except C ;This routine hibers before calling INCHRW so that PSISER will get ;a chance to interrupt us. The user-mode test bed depends on this. ;Here we use SKPINL and INCHRW rather than INCHSL so that ;MIC will see the INCHWL if the user types a space. STYPIN: REPEAT 0,< SKPINC ;ANY INPUT YET? JRST STYI.1 ;NO, WAIT FOR IT JRST STYI.2 ;YES, WAIT FOR A FULL LINE (FOR MIC) STYI.1: MOVE C,[EXP HB.RTC ! ^D1000] ;WAKE ON CHARACTER INPUT HIBER C, ;GIVE PSI A CHANCE TO INTERRUPT JFCL ; THE INCHRW SKPINC C ;SEE IF WE REALLY GOT A CHARACTER JRST STYI.1 ;NO, FALSEHOOD AND LIES FROM PSISER > ;END REPEAT 0 STYI.2: INCHWL C ;YES, GIVE CHAR TO SCAN RET Comment @ Note that this routine will hang in TI state once the first character of a line has been typed. This is for MIC. The user types a space, then MIC types the rest of the line. @ SUBTTL STYPOU - Output a Char to TTY and/or Log File ;STYPOU - Called by SCAN to output a char to the user ; ;Call: T1/ The Character ; CALL STYPOU ; Normal Return STYPOU::CALL STYPSB ;DO ANY TYPE OUT THAT IS REQUIRED CAIN T1,12 ;WAS IT A LINE FEED? SETZM ERRPRI ;YES, THAT WAS END OF ERROR LINE RET STYPSB: SAVEAC SKIPE TYPRCS ;SKIP IF NO STYPOU RECURSION JRST TYPO.3 ;IF RECURSING, MUST BE TIME STAMPING MOVE T2,PRINT ;GET PRINT OPTION FROM USER SKIPN ALWPRI ;SET BY STATISTICS PRINTOUT CAIN T2,PRI.AL ;PRINT:ALL? JRST TYPO.1 ;YES, TELL TTY AND LOG FILE CAIN T2,PRI.NO ;PRINT:NONE? JRST TYPO.2 ;YES, TELL LOG FILE ONLY SKIPN ERRPRI ;MUST BE PRINT:ERROR, PRINTING ERROR? JRST TYPO.2 ;NO, TELL LOG FILE ONLY ;YES, TELL TTY AND LOG FILE TYPO.1: OUTCHR T1 TYPO.2: SKIPN LOGFLG ;ARE WE LOGGING NOW? RET ;NO SKIPE TYPBOL ;AT BEG OF LINE? CALL TIMSTP ;YES, TIME STAMP THIS LINE CAIN T1,12 ;ARE WE STORING A LINE FEED? SETOM TYPBOL ;YES, NEXT CHR WILL BE A BEG OF LINE TYPO.3: CALL OUTBYT ;YES, PUT THE BYTE OUT TO THE LOG FILE RET ;ERROR, ALREADY CLOSED, LOGFLG ZEROED RET ;SUCCESS RETURN ;The TIMSTP subroutine for STYPOU: time stamp a log file TIMSTP::SAVEAC T1 ;SAVE CHR ABOUT TO BE STORED IN LOG SETOM TYPRCS ;WE ARE RECURSING IN STYPOU CALLSCAN .TDATN## ;TYPE TODAY'S DATE INTO LOG FILE CALLSCAN .TSPAC## ;TYPE A SPACE CALLSCAN .TTIMN## ;TYPE CURRENT TIME INTO LOG FILE CALLSCAN .TTABC## ;TYPE A TAB SETZM TYPRCS ;NO LONGER RECURSING SETZM TYPBOL ;NO LONGER AT BEG OF LINE RET SUBTTL DDT Aid for Logging REPEAT 0,< ;This routine is expected to be called by DDT with CALL LOGIT$X ;It is meant mostly for DTR, since DTS aleady has the LOG command. LOGIT:: SAVEAC MOVX P2,-1 ;-1 MEANS USE THE DEFAULT LOG FILE NAME CALL STRLOG MOVEM N,LOGFLG RET > ;END REPEAT 0 SUBTTL Log File I/O ;STRLOG - Start Logging to a Log File ; ;Call: CALL STRLOG ; Normal Return with N set to the value to store in LOGFLG ;Changes T1,T2,T3,T4 STRLOG::SKIPN LOGFLG ;HAVE A LOG FILE OPEN NOW? JRST STRL.1 ;NO CALL CLSLOG ;YES, CLOSE IT SO WE CAN START ANOTHER SETZM LOGSPC ;SMEAR LOGSPC TO ZEROS MOVE T1,[LOGSPC,,LOGSPC+1] BLT T1,LOGSPC+.FXLEN-1 ;Return from .FILIN is in T1: ; T1=0 if nothing typed ; T1=-1 if file spec typed ; T1=+1 if nothing but global switches typed STRL.1: JUMPL C,STRL.2 ;DON'T CALL .FILIN IF EOF CAIE C,":" ;IS PUNCTUATION A COLON? CAIN C,"=" ;OR AN EQUAL? CAIA ;YES, GET A FILESPEC JRST STRL.2 ;NO, TAKE THE DEFAULTS OUTSTR [ASCIZ /[A log file spec must be the last command on a line] /] CALLSCAN .FILIN## ;GET THE FILE SPEC FROM THE USER MOVEI T1,LOGSPC ;MOVE THE NEW SPEC TO HERE MOVEI T2,.FXLEN ;IT IS THIS LONG CALLSCAN .GTSPC## ;... STRL.2: MOVE T1,CPRGID ;DEFAULT TO NAME OF THIS PROGRAM SETO T2, ;NON-WILD MASK FOR WILD SKIPN LOGSPC+.FXNAM ;USER TYPE A NAME? DMOVEM T1,LOGSPC+.FXNAM;NO, FILL IN NAME AND NON-WILD MASK HRLOI T1,'LOG' ;DEFAULT TO .LOG EXTENSION SKIPN LOGSPC+.FXEXT ;USER TYPE AN EXT (OR . FOR NULL)? MOVEM T1,LOGSPC+.FXEXT;NO, MAKE IT .LOG ;Continued on Next Page ;From Previous Page with SCAN block all defaulted HRRI T1,LOGSPC ;THE SCAN BLOCK, HRLI T1,.FXLEN ; AND ITS LENGTH. MOVEI T2,LOGFOP+.FOIOS ;OUTPUT RING HDR BLK. (3-WORD) HRRI T3,LOGENT ;EXTENDED ENTER BLOCK. HRLI T3,LN$ENT ; ITS LENGTH. MOVEI T4,LOGPTH ;A PTHLNG-LENGTH-WORD PATH BLK. CALLSCAN .STOPB## ;NO-WILD SCAN BLK TO LOOKUP JRST STPERR ; BLOCK TRANSLATOR. MOVE T1,[FO.PRV ! B17 ! .FOAPP] MOVEM T1,LOGFOP+.FOFNC MOVEI T1,LN$ENT ;LENGTH OF THE ENTER BLOCK MOVEM T1,LOGENT ;STORE AS LENGTH FOR THE FILOP MOVEI T1,LOGENT ;PTR TO THE ENTER BLOCK MOVEM T1,LOGFOP+.FOLEB MOVEI T1,LOGBRH ;GET A BUFFER RING HEADER ADDRESS HRLM T1,LOGFOP+.FOBRH ;STORE IN THE FILOP BLOCK MOVE T1,[FOPLEN,,LOGFOP] FILOP. T1, ;APPEND THE LOG FILE (OR CREATE IT) JRST LGEERR ;OPEN ERROR ;Start the file with a form feed in case this is an appended file SETOM TYPRCS ;TELL STYPOU THAT WE'RE RECURSING MOVEI T1,14 ;A FORM FEED CALLSCAN .TCHAR## ;TYPE THE CHAR INTO THE LOG FILE CALLSCAN .TCRLF## ;TYPE A CARRIAGE RETURN, LINE FEED SETZM TYPRCS ;NO LONGER RECURSING SETOB N,TYPBOL ;WE NOW HAVE A LOG FILE TO WRITE TO ;RETURN VALUE TO STORE IN LOGFLG ;SET TYPBOL NON-ZERO TO START TIME- RET ; STAMPING STPERR: MOVEI T1,[ASCIZ \%Wild cards in log file name not supported\] CALL ERRMSG MOVEI T1,[ASCIZ \, logging disabled \] CALL ERRMSG JRST LGECOM LGEERR: MOVEI T1,LOGENT ;ENTER BLOCK MOVEI T2,LN$ENT ;LENGTH OF ENTER BLOCK MOVEI T3,LOGSPC ;SCAN BLOCK SETOM ERRPRI ;ENABLE PRINT:ERROR CALLSCAN E.LKEN## ;ERROR ENTERRING LOG FILE ;Common exit for all STRLOG errors: set N to zero. ;Caller will store N in LOGFLG LGECOM: SETZ N, ;TURN OFF LOGGING RET ;OUTBYT - Output a byte to the log file ; ;Call: T1/ The Byte ; CALL OUTBYT ; Error Return ; Normal Return ;Changes T1,T2,T3,T4 OUTBYT: OUTB.1: SOSGE LOGBRH+.BFCTR ;LOGBRH = HEADER FOR FILE OUTPUT JRST OUTBYN ;NO ROOM, GET A NEW BUFFER IDPB T1,LOGBRH+.BFPTR ;THE NORMAL OUTPUT DEPOSIT BYTE. AOS (P) ;SUCCESS RETURN RET OUTBYN: CALL OUTBUF ;OUTPUT THE BUFFER RET ;"DON'T CONTINUE" RETURN JRST OUTB.1 ;GOT A BUFFER, GO COUNT IT DOWN ;CALL CALL OUTBUF ; "DON'T CONTINUE" RETURN ; "OK" RETURN OUTBUF: OUT LOGCHN, JRST .POPJ1 ;OK RETURN: SUCCESS GETSTS LOGCHN, T1 PJRST OTIOER ;TELL USER ABOUT I/O ERROR ;OTIOER - Tell user about output I/O error ; ;Call: T1/ GETSTS code ; CALL OTIOER ; Normal Return OTIOER: SAVEAC ;DRASTIC, BUT NOT FREQUENT CALL CLSLOG ;SALVAGE WHAT WE CAN OF THE LOG FILE PUSH P, T1 ;SAVE GETSTS CODE FOR A SEC MOVEI T1,[ASCIZ "% Output I/O error, logging stopped"] CALLSCAN .TSTRG## POP P, T1 ;RESTORE GETSTS CODE CALL ERRSTS ;TELL USER ABOUT ERROR CALLSCAN .TCRLF## RET ;NO, NON-SKIP RETURN ;CALL T1/ GETSTS code ; CALL ERRSTS ; Only return DEFINE ERRMAC (name, text),< MOVEI T1,[ASCIZ " name:text"] $XLIST TXNE T2,name CALLSCAN .TSTRG## $LIST >;END OF DEFINE ERRMAC ERRSTS: PUSH P, T1 ;SAVE THE GETSTS CODE CALLSCAN .TOCTW## ;PRINT IT IN OCTAL MOVEI T1,[ASCIZ " ("] CALLSCAN .TSTRG## POP P,T2 ;RESTORE GETSTS CODE ERRMAC IO.IMP, Software Detected Error ERRMAC IO.DER, Device Error ERRMAC IO.DTE, Data Error ERRMAC IO.BKT, Block Too Large MOVEI T1,[ASCIZ " )"] CALLSCAN .TSTRG## RET SUBTTL STPLOG - Stop Logging to a Log File ;STPLOG - Stop Logging to a Log File ; ;Call: CALL STPLOG ; Normal Return with N set to zero for caller to store in LOGFLG ;Changes T1,T2,T3,T4 STPLOG::CALL CLSLOG ;CLOSE ANY LOG FILE THAT MAY HAVE ; BEEN OPEN. SETZB N,LOGFLG ;TELL STYPOU TO STOP LOGGING RET ;N GETS STORED IN LOGFLG BY CALLER ;Close the Log file politely CLSLOG::CLOSE LOGCHN, SETZM LOGFLG ;TELL STYPOU NOT TO LOG ANY MORE PUSH P,INIFF ;GET THE VALUE OF .JBFF AT STARTUP POP P,.JBFF SETZM LOGBRH ;NO LONGER HAVE THE BUFFER'S CORE SETZM LOGBRH+1 SETZM LOGBRH+2 RET SUBTTL String Handling Routines ;SIX2ST - Convert a sixbit word to a string block ; ;Call: T1/ Pointer to a string block big enough for six chars ; T2/ The SIXBIT word ; CALL SIX2ST ; Normal Return ; ;Uses T1,T2,T3,T4 SIX2ST::SAVEAC MOVSI P1,(POINT 8,) HRRI P1,1(T1) MOVE P2,[POINT 6,T2] MOVEI T4,6 ;UP TO SIX CHARS IN A SIXBIT WORD SX2S.1: ILDB T3,P2 ;GET A SIXBIT CHAR JUMPE T3,SX2S.2 ;STOP COPYING WHEN WE GET A NULL ADDI T3," " ;MAKE IT ASCII IDPB T3,P1 ;STORE IN STRING BLOCK SOJG T4,SX2S.1 ;LOOP IF WE'VE NOT DONE ALL YET SX2S.2: MOVEI T3,6 ;MAX NUMBER WE COULD HAVE MOVED SUB T3,T4 ;GET NUMBER WE DID MOVE HRLM T3,(T1) ;STORE NUMBER WE DID MOVE IN STRING BLK RET ;PUTxBY - Put a one- or two-byte value into a string block ; ;Call: T1/ The value ; T2/ Pointer to the string block ; T3/ Number of bytes for PUTNBY, ignored by PUT1BY and PUT2BY ; CALL PUTxBY ; Normal Return ; ;PUTxBY does NOT change T2, this is required for long sequences ; of calls to PUTxBY PUT2BY: MOVEI T3,2 ;NUMBER OF BYTES TO PUT PUTNBY: JUMPLE T3,.POPJ ;IGNORE IF NO BYTES TO COPY CALL PUT1BY ;STORE NEXT LOW-ORDER BYTE LSH T1,-^D8 ;SHIFT DOWN SOJA T3,PUTNBY ;LOOP UP TO 4 TIMES PUT1BY::HLRZ T4,(T2) ;GET CURRENT BYTE COUNT FROM STR BLK AOS T4 ;INCR COUNT FOR THIS NEW BYTE HRLM T4,(T2) ;FINISH UP A LEFT-HALF INCREMENT ADJBP T4,[POINT 8,1(T2)] ;BUILD BYTE PTR TO FIRST FREE BYTE DPB T1,T4 RET ;GETxBY - Get a one- or two-byte value from a string block ; ;Call: T1/ The offset of the byte to get (the first is 0) ; T2/ Pointer to the string block ; T3/ Number of bytes for GETNBY, ignored by GET1BY and GET2BY ; CALL GET1BY ; Error Return with T1 unchanged (for UNSUPT) ; Normal Return with value in T1 ; ;GETxBY does NOT change T2, this is required for long sequences ; of calls to GETxBY GET2BY::MOVEI T3,2 ;NUMBER OF BYTES TO GET PJRST GETNBY ;GET THEM GET1BY::MOVEI T3,1 ;NUMBER OF BYTES TO GET GETNBY::SAVEAC T2 ;CALLER EXPECTS THIS FOR MULTIPLE CALLS CAILE T3,4 ;MAX WE CAN HANDLE IS 4 BYTES/WORD HALT .+1 MOVE T4,T3 ;GET REQUESTED BYTE COUNT ADD T4,T1 ;GET OFFSET OF END OF PROPOSED STRING PUSH P,T2 HLRZ T2,(T2) ;GET COUNT OF BYTES IN STR BLK CAMLE T4,T2 ;MUST BE LEAST N MORE BYTES JRST [POP P,T2 ;NOPE, ERROR RETURN WITH T1 UNCHANGED RET] POP P,T2 MOVE T4,T1 ;GET OFFSET OF BEG OF STRING AGAIN ADJBP T4,[POINT 8,1] ;BUILD OFFSET IDLB PTR TO FIRST BYTE ADD T4,T2 ;POINT IT INTO THE STRING BLOCK PUSH P,T3 ;SAVE COUNT REQUESTED GETN.1: ILDB T1,T4 ;GET NEXT HIGHER ORDER BYTE LSHC T1,-^D8 ;PUT INTO HIGH BYTE OF T2 SOJG T3,GETN.1 ;DO ALL REQUESTED BYTES POP P,T3 ;HOW MANY WAS THAT? ASH T3,3 ;BYTE COUNT * 8 = BIT COUNT ;WE KNOW T1 IS ZERO NOW LSHC T1,(T3) ;RESULT NOW RIGHT JUSTIFIED IN T1 RETSKP ;SUCCESS RETURN ;ASC2ST - Convert an ASCII string to a string block ; ;Call: T1/ Pointer to a string block big enough ; T2/ ILDB Byte Pointer to ASCII string ; CALL ASC2ST ; Normal Return ; ;Uses T1,T2,T3,T4 ASC2ST::SAVEAC MOVSI P1,(POINT 8,) HRRI P1,1(T1) HRRZ T4,(T1) ;LENGTH OF THE STRING BLOCK (WORDS) SOJLE T4,CPOPJ ;COUNT INCLUDES COUNT WORD AT BEGINNING ASH T4,2 ;MULTIPLY BY 4 TO GET BYTE COUNT MOVE P2,T4 ;SAVE COUNT FOR LATER AS2S.1: ILDB T3,T2 ;GET A ASCII CHAR JUMPE T3,AS2S.2 ;STOP COPYING WHEN WE GET A NULL IDPB T3,P1 ;STORE IN STRING BLOCK SOJG T4,AS2S.1 ;LOOP IF WE'VE NOT DONE ALL YET AS2S.2: SUB P2,T4 ;CALC NUMBER WE DID COPY HRLM P2,(T1) ;STORE NUMBER WE MOVED IN STRING BLK RET ;SETQTA - Set SQUEUE or RQUEUE as the link quota ; ;Call: T1/ Value of SQUEUE or RQUEUE ; CALL SETQTA ; Error Return, message already given ; Normal Return ; ;Uses T1,T2,T3,T4 SETQTA::SKIPG T1 ;ZERO OR NEGATIVE IS ILLEGAL MOVEI T1,1 ;DEFAULT TO 1 IN, 1 OUT IMULI T1,2 ;DOUBLE IT, HALF FOR IN, HALF FOR OUT MOVE NSAA1,T1 ;THE QUOTA MOVEI NSAA2,^D50 ;50% INPUT QUOTA MOVEI NSAA3,0 ;NO GOAL (YET) CALNSP .NSFSQ,NSAA3 ;SET QUOTA FUNCTION CODE JRST SETQTE RETSKP SETQTE: ERROR ,CRLF RET ;.TSTRB - Type out a string block's string ; ;Call: T1/ Ptr to string block ; CALL .TSTRB ; Normal Return ; ;Uses T1,T2,T3,T4 .TSTRB::SAVEAC HLRZ P1,(T1) ;GET BYTES IN STRING JUMPE P1,CPOPJ ;IGNORE NULL STRING MOVEI P2,1(T1) HRLI P2,(POINT 8,) TSTB.1: ILDB T1,P2 ;LOAD UP AN 8-BIT BYTE CALLSCAN .TCHAR## ;TYPE THE LOW-ORDER 7 BIT'S CHARACTER SOJG P1,TSTB.1 RET SUBTTL Test String Routines ;FILSTD - Fill in a Standard Test String ; ;Call: T1/ Pointer to String Block to Fill ; T2/ Length of String to Fill ; CALL FILSTD ; Normal Return ; ;Uses T1,T2,T3,T4 FILSTD::JUMPLE T2,.POPJ HLRZ T4,(T1) ;GET CURRENT BYTE COUNT IN STR BLK MOVE T3,T4 ;PREPARE TO UPDATE STRING BLK'S ADD T3,T2 ; BYTE COUNT TO TAKE IN NEW STRING HRLM T3,(T1) ;STORE NEW COUNT BACK IN STRING BLK ADJBP T4,[POINT 8,0] ;BUILD IDPB PTR FOR OFFSET ADDI T4,1(T1) ;POINT IT INTO STRING BLOCK FILS.1: MOVE T1,STDSPT ;BYTE PTR TO STANDARD STRING FILS.2: ILDB T3,T1 JUMPE T3,FILS.1 ;SOURCE ALL DONE, START OVER IDPB T3,T4 SOJG T2,FILS.2 ;REMAINING LENGTH OF DEST STRING RET ;CMPSTD - Compare a Standard Test String ; ;Call: T1/ Byte Pointer to Target ; T2/ Length of String to Compare ; CALL CMPSTD ; No Match Return ; Match Return ; ;Uses T1,T2,T3,T4 CMPSTD::JUMPLE T2,.POPJ1 ;IF NO STRING, IT MATCHES SAVEAC P1 CMPS.1: MOVE T4,STDSPT ;BYTE PTR TO STANDARD STRING CMPS.2: ILDB T3,T4 ;GET A STANDARD BYTE JUMPE T3,CMPS.1 ;SOURCE ALL DONE, START OVER ILDB P1,T1 ;GET A BYTE TO COMPARE CAME P1,T3 ;IF NOT EQUAL RET ; TAKE NO MATCH RETURN IMMEDIATELY SOJG T2,CMPS.2 ;ELSE KEEP COMPARING FOR REST OF ; STRING PASSED BY USER RETSKP ;SUCCESS: MATCHED TO END OF USER STR STDSPT: POINT 7,STDSTR STDSTR: ASCIZ /ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/ ;CMPSTB - Compare two string blocks ; ;Call: T1/ Pointer to first string block ; T2/ Pointer to second string block ; CALL CMPSTB ; No Match Return ; Match Return ; ;Uses T1,T2,T3,T4 CMPSTB::SAVEAC HLRZ T3,(T1) ;GET LENGTH OF FIRST BLOCK HLRZ P1,(T2) ;GET LENGTH OF SECOND BLOCK CAME T3,P1 ;COMPARE THE LENGTHS RET ;NO-MATCH IF NOT SAME LENGTH HRLI T1,(POINT 8,0,35) ;ILDB POINTER TO (T1)+1 HRLI T2,(POINT 8,0,35) ;ILDB POINTER TO (T2)+1 CSTB.1: ILDB P1,T1 ;GET A BYTE OF THE FIRST STRING ILDB P2,T2 ;GET A BYTE OR THE SECOND CAME P1,P2 ;SAME? RET ;NO, NO-MATCH RETURN SOJG T3,CSTB.1 ;YES, TRY NEXT IF THERE IS A NEXT RETSKP ;ALL DONE, ALL MATCHED SUBTTL RSNTXT - Type Out Text for DECnet Reject Reason ;RSNTXT - Type Out Text for DECnet Reject Reason ; ;Call: T1/ The Reason Code ; CALL RSNTXT ; Normal Return DEFINE RSNMAC(code,text),< CAIN T1,code MOVEI T2,[ASCIZ |code: text|] > RSNTXT::MOVEI T2,0 ;SO WE KNOW IF NO REASON HAS MATCHED RSNMAC RSNDBO,Disconnected/Rejected by Object RSNMAC RSNRES,No Resources RSNMAC RSNUNN,Unrecognized Node Name RSNMAC RSNRNS,Remote Node Shut Down RSNMAC RSNURO,Unrecognized Object RSNMAC RSNIOF,Invalid Object Name Format RSNMAC RSNOTB,Object Too Busy RSNMAC RSNABM,Abort by Management RSNMAC RSNABO,Abort by Object RSNMAC RSNINF,Invalid Node Name Format RSNMAC RSNLNS,Local Node Shut Down RSNMAC RSNACR,Access Control Rejection RSNMAC RSNRNO,No Response from Object RSNMAC RSNNUR,Node Unreachable RSNMAC RSNNLK,No Link RSNMAC RSNDSC,Disconnect Complete RSNMAC RSNIMG,Image Field Too Long JUMPE T2,RSNT.1 ;JUMP IF NO MATCH FOUND MOVE T1,T2 ;MOVE TO T1 FOR .TSTRG CALLSCAN .TSTRG## ;GOT A MATCH, TYPE OUT TEXT RET RSNT.1: PUSH P,T1 ;NO MATCH, TYPE OUT CODE IN DECIMAL MOVEI T1,[ASCIZ /Unknown reason code: /] CALLSCAN .TSTRG## POP P,T1 CALLSCAN .TDECW## RET SUBTTL Get Unwrapping Time ;GETTIM - Get Unwrapping time in Milliseconds ; ;Call: CALL GETTIM ; Normal Return with time in T1 GETTIM::MSTIME T1, ;GET MILLISECONDS SINCE MIDNIGHT CAMGE T1,LASTIME ;WRAPPED AROUND? ADD T1,[DEC 1000*60*60*24] ;MILLISECS IN A DAY MOVEM T1,LASTIME ;STORE FOR NEXT TIME RET ;WITH TIME IN T1 SUBTTL PSTATS - Print Statistics ;Called by DTS and by DTR after a DATA or INTERRUPT test. ;Call: CALL PSTATS ; Normal Return PSTATS::SAVEAC P1 CALLSCAN .TCRLF## CALLSCAN .TTABC## MOVEI T1,[ASCIZ /Test ran for /] CALLSCAN .TSTRG## MOVE T1,ELPTIM ;GET ELAPSED TIME CALLSCAN .TDECW## MOVEI T1,[ASCIZ / milliseconds/] CALLSCAN .TSTRG## CALLSCAN .TCRLF## CALLSCAN .TTABC## MOVE T1,MSGSIZ ;GET MESSAGE SIZE CALLSCAN .TDECW## MOVEI T1,[ASCIZ / bytes per message, /] CALLSCAN .TSTRG## CALLSCAN .TCRLF## CALLSCAN .TCRLF## MOVEI T1,[ASCIZ /Send statistics:/] CALLSCAN .TSTRG## CALLSCAN .TCRLF## MOVE T1,SNDCNT ;LOAD UP # OF MSGS SENT MOVE T2,SERRCNT ; AND # OF ERRORS SENDING THEM CALL MSGSTS ;TYPE OUT SEND STATS CALLSCAN .TCRLF## MOVEI T1,[ASCIZ /Receive statistics:/] CALLSCAN .TSTRG## CALLSCAN .TCRLF## MOVE T1,RCVCNT ;LOAD UP # OF MSGS RECEIVED MOVE T2,RERRCNT ; AND # OF ERRORS RECEIVING THEM CALL MSGSTS ;TYPE OUT SEND STATS CALLSCAN .TCRLF## ;AN EXTRA CRLF RET ;Subroutine to type out received or sent stats ;Call: T1/ SNDCNT or RCVCNT ; T2/ SERRCNT or RERRCNT ;Return: ; Non-skip only MSGSTS: SAVEAC DMOVE P1,T1 ;P1/ Message Count, P2/ Error Count CALLSCAN .TTABC## MOVE T1,P1 ;MESSAGE COUNT CALLSCAN .TDECW## MOVEI T1,[ASCIZ / messages (/] CALLSCAN .TSTRG## MOVE T1,P2 ;NUMBER OF ERRORS CALLSCAN .TDECW## MOVEI T1,[ASCIZ / errors), /] CALLSCAN .TSTRG## MOVX T1,^D1000 ;MILLISECONDS IMUL T1,P1 ;GET # OF MSGS IDIV T1,ELPTIM ;MAKE MSGS/SECOND OF ELAPSED TIME PUSH P,T2 ;SAVE REMAINDER CALLSCAN .TDECW## ;PRINT WHOLE-NUMBER PART MOVEI T1,"." ;GET A DECIMAL POINT CALLSCAN .TCHAR## ;PRINT IT POP P,T1 ;GET REMAINDER BACK AGAIN IMULI T1,^D100 ;MAKE IT HUNDREDTHS IDIV T1,ELPTIM ;CHANGE REMAINDER TO HUNDREDTHS MOVEI T2,"0" ;FILL WITH ZERO CALLSCAN .TDEC2## ;TYPE 2-DIGIT REMAINDER WITH LEFT FILLER MOVEI T1,[ASCIZ \ messages/second\] CALLSCAN .TSTRG## CALLSCAN .TCRLF## JUMPE P1,CPOPJ ;LEAVE NOW IF NO MESSAGES COUNTED ;Characters per second and effective baud rate CALLSCAN .TTABC## MOVE T1,P1 ;NUMBER OF MESSAGES IMUL T1,MSGSIZ ;TIMES THE MESSAGE SIZE = CHARS SENT IMULI T1,^D1000 ;SET TO DIVIDE BY MILLISECONDS IDIV T1,ELPTIM ;DIVIDE BY MILLISECONDS ELAPSED MOVEI P2,^D8 ;MULTIPLY BY 8 FOR BITS/SEC ("BAUD") IMUL P2,T1 ;SAVE EFFECTIVE BAUD RATE CALLSCAN .TDECW## ;TYPE CHARS/SECOND MOVEI T1,[ASCIZ \ characters/second\] CALLSCAN .TSTRG## CALLSCAN .TCRLF## CALLSCAN .TTABC## ;TYPE A TAB MOVE T1,P2 ;P2 NOW HAS EFFECTIVE BAUD RATE CALLSCAN .TDECW## ;TYPE OUT EFFECTIVE "BAUD" RATE MOVEI T1,[ASCIZ \ effective baud rate = 8 * chars/sec\] CALLSCAN .TSTRG## CALLSCAN .TCRLF## ;Line efficiency if user declared an ideal baud rate SKIPG BAUD ;GET USER-DECLARED BAUD RATE RET ;NO BAUD RATE, NO MORE TO SAY CALLSCAN .TTABC## ;TYPE A TAB MOVE T1,P2 ;GET EFFECTIVE BAUD RATE AGAIN IMULI T1,^D100 ;MAKE IT A PERCENT IDIV T1,BAUD ;ACTUAL/THEORETICAL RATE = EFFICIENCY CALLSCAN .TDECW## ;TYPE CHARS/SECOND MOVEI T1,[ASCIZ /% line efficiency on a /] CALLSCAN .TSTRG## MOVE T1,BAUD ;GET USER-DECLARED BAUD RATE CALLSCAN .TDECW## ;TYPE USER-DECLARED IDEAL BAUD RATE MOVEI T1,[ASCIZ / baud line/] CALLSCAN .TSTRG## CALLSCAN .TCRLF## RET ;ONLY RETURN SUBTTL Utility Routines G:: PUSH P,.JBOPC ;RETURN FROM DDT POPJ P, ; WITHOUT TRASHING ACS IFN FTEXTRA, OPDEF LL [CALL USLINK] ;FOR LL$X IN DDT SUBTTL USLINK - Type out the Port Block for a Link IFN FTEXTRA,< ;This routine is expected to be called via the LINK command ;to DTS or by the CALL USLINK$X command to DDT, hence the huge ;SAVEAC call. USLINK: SAVEAC PROMPT REDLIN .DECNW## ;GET DECIMAL NUMBER MOVE T1,N ;GET REQUESTED LINK NUMBER LOAD P1,QHBEG,+NSPAPQ## ;GET HEAD OF NSP'S ALL PORTS QUEUE USLNK1: JUMPE P1,USNOLINK ;TELL USER HE'S ASKED FOR BUM LINK OPSTR ,NPLLA,(P1) ;COMPARE WITH LOCAL LINK ADDRESS JRST USLNK2 ;MATCH! LOAD P1,NPAPQ,(P1) ;NO MATCH, GET NEXT PORT BLOCK JRST USLNK1 ;CHECK THIS NEXT ONE USNOLINK: PROMPT CALLSCAN .TCRLF RET >;END OF IFN FTEXTRA IFN FTEXTRA,< EXTERN .TOCTW,.TXWDW,.TDECW,.TCHAR,.TCRLF,.TTABC DEFINE TYPLNK(heading,symbol,typout,offset,text),< PROMPT LOAD T1,symbol,+offset(P1) IFIDN ,,< CALLSCAN TYPOCT> IFDIF ,,< CALLSCAN .TDECW MOVEI T1,"." CALLSCAN .TCHAR > CALLSCAN .TTABC PROMPT(<;text>) CALLSCAN .TCRLF > DEFINE TYPLNQ(heading,symbol,offset,text),< TYPLNK heading+QHBEG,QHBEG,OCT,$'symbol+offset, TYPLNK heading+QHEND,QHEND,OCT,$'symbol+offset, TYPLNK heading+QHMAX,QHMAX,OCT,$'symbol+offset, TYPLNK heading+QHCNT,QHCNT,OCT,$'symbol+offset, > TYPOCT: TLNN T1,-1 ;ANYTHING IN THE LEFT HALF? CALLRET .TOCTW ;NO, TYPE OUT SIGNED OCTAL (SINGLE #) CALLRET .TXWDW ;YES, TYPE OUT 2 HALF-WORDS >;END OF IFN FTEXTRA IFN FTEXTRA,< USLNK2: TYPLNK NPAPQ,NPAPQ,OCT,0, TYPLNK NPHBQ,NPHBQ,OCT,0, TYPLNK NPJFQ,NPJFQ,OCT,0, TYPLNK NPSNC,NPSNC,OCT,0, TYPLNK NPCNF,NPCNF,OCT,0, TYPLNK NPSCM,NPSCM,OCT,0, TYPLNK NPABO,NPABO,OCT,0, TYPLNK NPOJQ,NPOJQ,OCT,0, TYPLNK NPSTA,NPSTA,DEC,0, TYPLNK NPVER,NPVER,DEC,0, TYPLNK NPSIZ,NPSIZ,DEC,0, TYPLNK NPLLA,NPLLA,DEC,0, TYPLNK NPRLA,NPRLA,DEC,0, TYPLNK NPOTC,NPOTC,DEC,0, TYPLNK NPDSG,NPDSG,DEC,0, TYPLNK NPDTM,NPDTM,DEC,0,< AND TIME IT WAS FIRST SENT> TYPLNK NPNNM,NPNNM,OCT,0, TYPLNK NPNDB,NPNDB,OCT,0, TYPLNK NPTMA,NPTMA,DEC,0, TYPLNK NPSCV,NPSCV,OCT,0, TYPLNK NPSCB,NPSCB,OCT,0, TYPLNK NPDIM,NPDIM,OCT,0, CALLSCAN .TCRLF PROMPT CALLSCAN .TCRLF TYPLNK NSOTH,NSOTH,OCT,NP.NSL, TYPLNK NSACK,NSACK,OCT,NP.NSL, TYPLNK NSROF,NSROF,OCT,NP.NSL, TYPLNK NSROC,NSROC,OCT,NP.NSL, TYPLNK NSXOF,NSXOF,OCT,NP.NSL, TYPLNK NSXOC,NSXOC,OCT,NP.NSL, TYPLNK NSRFL,NSRFL,DEC,NP.NSL, TYPLNK NSXFL,NSXFL,DEC,NP.NSL, TYPLNK NSGOL,NSGOL,DEC,NP.NSL, TYPLNK NSCGL,NSCGL,DEC,NP.NSL, TYPLNK NSXLD,NSXLD,DEC,NP.NSL, TYPLNK NSXRD,NSXRD,DEC,NP.NSL, TYPLNK NSXSD,NSXSD,DEC,NP.NSL, TYPLNK NSRLD,NSRLD,DEC,NP.NSL, TYPLNK NSRRD,NSRRD,DEC,NP.NSL, TYPLNK NSRSD,NSRSD,DEC,NP.NSL, TYPLNK NSLMA,NSLMA,OCT,NP.NSL, TYPLNK NSLAR,NSLAR,OCT,NP.NSL, TYPLNK NSLMR,NSLMR,OCT,NP.NSL, TYPLNQ NSAKQ,NSAKQ,NP.NSL, TYPLNQ NSRCQ,NSRCQ,NP.NSL, TYPLNQ NSXMQ,NSXMQ,NP.NSL, CALLSCAN .TCRLF PROMPT CALLSCAN .TCRLF TYPLNK NSOTH,NSOTH,OCT,NP.OSL, TYPLNK NSACK,NSACK,OCT,NP.OSL, TYPLNK NSROF,NSROF,OCT,NP.OSL, TYPLNK NSROC,NSROC,OCT,NP.OSL, TYPLNK NSXOF,NSXOF,OCT,NP.OSL, TYPLNK NSXOC,NSXOC,OCT,NP.OSL, TYPLNK NSRFL,NSRFL,DEC,NP.OSL, TYPLNK NSXFL,NSXFL,DEC,NP.OSL, TYPLNK NSGOL,NSGOL,DEC,NP.OSL, TYPLNK NSCGL,NSCGL,DEC,NP.OSL, TYPLNK NSXLD,NSXLD,DEC,NP.OSL, TYPLNK NSXRD,NSXRD,DEC,NP.OSL, TYPLNK NSXSD,NSXSD,DEC,NP.OSL, TYPLNK NSRLD,NSRLD,DEC,NP.OSL, TYPLNK NSRRD,NSRRD,DEC,NP.OSL, TYPLNK NSRSD,NSRSD,DEC,NP.OSL, TYPLNK NSLMA,NSLMA,OCT,NP.OSL, TYPLNK NSLAR,NSLAR,OCT,NP.OSL, TYPLNK NSLMR,NSLMR,OCT,NP.OSL, TYPLNQ NSAKQ,NSAKQ,NP.OSL, TYPLNQ NSRCQ,NSRCQ,NP.OSL, TYPLNQ NSXMQ,NSXMQ,NP.OSL, CALLSCAN .TCRLF TYPLNK NPCHK,NPCHK,OCT,0,
RET >;END OF IFN FTEXTRA SUBTTL End of Library END