Trailing-Edge
-
PDP-10 Archives
-
BB-F494Z-DD_1986
-
10,7/networ.mac
There are 9 other files named networ.mac in the archive. Click here to see a list.
TITLE NETWORK Program to list the nodes in a network
SUBTTL S. Sullivan
SALL ;Pretty listings
.DIREC FLBLST ;Prettier listings
COMMENT@
Things to do:
@
.TEXT \/SYMSEG:HIGH/LOCALS\
COMMENT@
COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979,1985,1986. ALL RIGHTS RESERVED.
THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE
INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
TRANSFERRED.
THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
CORPORATION.
DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
@
SUBTTL Edit history
COMMENT @
[1] Add the /TYPE: switch to determine a node by it's type
[2] Fix the core freeing code in CLRDAT to not zero DDT when loaded
[3] Fix the BLT in CLRDAT so it does not initalize MATCH to -1
[4] Fix the .ISCAN call so indirect files are illegal if logged out
[5] Make sure the user can't get into a "*" mode if not logged in
[6] Take care of the way the NODE. UUO error returns easier now
[7] Make CONC use .ISLGI in SCAN to be consistant in checking if logged in
[10] We saved the temps too early in the OFLINE routine
[11] Make sure that we are able to recover from a node in a "funny" state
[12] Buffer TTY output to reduce monitor overhead
[13] Change "NODE" in output to "Node"
[14] Change the HOST switch to be HOSTESS to be monitor compatable
[15] Make the program Reenterable by setting up .JBREN
[16] Change the way TRMOP. errors are handled and fix
miscellaneous bugs.
[17] Make a zero low segment. Remove EXPs and replace with BLOCK.
[20] Don't allow "*" mode if not logged in...only can do when we
get control because SCAN has a matching bug, before we get it.
[21] Add a reset instruction because the dispatch through RUNAME
or RUNAMC in COMCON or the RUN/R command will not do a
reset unless the program is gotten from DSK. This means
that if the sharable dormant high seg was there and there
was no low seg an address check was the result.
[22] Fix OFLINE and correct other error recovery problems
[23] Add the /TOPOLOGY,/COST, and /SORT switches and fix some
more small bugs including a stack phase problem when we
used the default case (null node name).
[24] Fix the output from /TOPOLOGY so final node,cost pair is
preceeded by a tab.
[25] Version 2! Add DECnet to the program. Reorganize the structure
to make it easier to add new networks as they come along.
Also, fix some bugs
[26] Fix /LINKS to work consistantly, consolidate code in the
DECnet listing routines.
[27] Fix to work with new DNET. uuo, as per MCO 10716.
%2(27) Shipped with 7.02
[30] Fix to work with DECnet Phase IV.
[31] Update copyright notice for 7.03.
[32] Teach how to report non-named nodes on DECnet display
33 RDH 16-Apr-85
De-PRGEND this beast. Call version 3.
34 RDH 16-Apr-85
Add LAT service junk.
35 LEO 4-Sep-85
Do Copyrights.
36 WXD 3-Oct-85
Teach about DECnet endnode support.
@
SUBTTL Constants, symbols, and registers
SEARCH UUOSYM,JOBDAT,MACTEN,SCNMAC
.REQUE REL:SCAN.REL
.REQUE REL:HELPER.REL
TWOSEG 400000 ;So the program will have two segments
;** Define the version word
CUSTVR==0 ;Customer version
DECVER==3 ;DEC version
DECMVR==0 ;DEC minor version
DECEVR==36 ;DEC edit number
NETVER=CUSTVR*1B2+DECVER*1B11+DECMVR*1B17+DECEVR
LOC 137
NETVER
;** Set up .JBINT for interrupt trapping
LOC 134 ;Set PC at .JBINT and
EXP INTBLK ;make it point to our interrupt block
;** Set up .JBREN to allow users to "Reenter" the program
LOC 124 ;Set PC at .JBREN
EXP START+1 ;Begin at run start address
RELOC ;Set back to the high segment
COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1979,1986. ALL RIGHTS RESERVED.
\;END COPYRIGHT MACRO
;REGISTER DEFINITIONS
F=0 ;Flags
F.SEL=400000
T1=1 ;Temps
T2=2
T3=3
T4=4
P1=5 ;Save registers
P2=6
P3=7 ;For passing arguments to SCAN
P4=10
T5=11
T6=12
T7=13
CN=14 ;Current node we are processing
L1=15 ;First loop counter
L2=16 ;Second loop counter
P=17 ;Stack pointer
;DEFINITIONS NOT YET IN UUOSYM
DN%ARE==176000 ;DECnet area number
DN%NOD==001777 ;DECnet node number field
;Program parameters
MAXSPC==^D100 ;The max number of specs we will allow
DNMAX==^D1024 ;The max number of DECnet nodes we support
DNINFL==40 ;Size of DNINF block
MAXNOD==200 ;The max number of ANF nodes we can handle
NODDLN==100 ;Size of NODE. block data buffer
BLKSIZ==.FXLEN ;Number of words allocated to each Scan block
PREALO==MAXNOD/10 ;How many nnode specs to preallocate for
MAXNFE==MAXNOD/2 ;Maximum # of non-fatal errors we will allow
MAXCOR==10000 ;The maximum amount of core we allow (in words)
MO.CHR==400000 ;Character mode bit
DEFWID==^D72 ;Define our default width
PSIZ==100 ;Number of words in the stack
SUBTTL Impure storage
RELOC ;Set to low segment for data and stack
PDL: BLOCK PSIZ ;Stack
;** Interrupt block
INTBLK: BLOCK 1 ;4 words long,,interrupt handler
BLOCK 1 ;No message control,, 2 ^C
LASTPC: BLOCK 1 ;User PC stored here when interrupted
INTYPE: BLOCK 1 ;interrupt type in LH
SUBTTL UUO argument blocks
STDAT: ;Start of core to be zeroed on initalization
DNLOOP: BLOCK 1 ;AOBJN loop counter
DNLOC: BLOCK 1 ;SIXBIT name of local node
DNADR: BLOCK 1 ;Local node network address
DNLST: BLOCK DNMAX ;Max size of DECnet network
DNBIT: BLOCK DNMAX ;Parallel table to DNLST for flags
DN.LST==400000 ;*don't list this node
DN.ONL==200000 ;*this node is on-line
DN.ACT==100000 ;*this node is active
DNBLK: BLOCK 20 ;Size of info block
DNCNT: BLOCK 1 ;Count of nodes returned
DNMCNT: BLOCK 1 ;Count of nodes matched by specs
DNINF: BLOCK DNINFL ;DNET. UUO block for info
DNLINE: BLOCK 5 ;String block for line descriptor
DNLINN==<<.-DNLINE>*5>-1 ;How many bytes for the descriptor
;** Argument block for the NODE. UUO's .NDNDB function
NODBLK: BLOCK 1 ;NODE. UUO arg block
CURNOD: BLOCK 1 ;Current node number
FLDNUM: BLOCK 1 ;Field number we want
DATBLK: BLOCK NODDLN ;Data area
;** Argument block for the TRMOP. UUO's .TOWID function
TTWID: BLOCK 1 ;Function code to get TTY width
UDX: BLOCK 1 ;Our TTY's UDX
;** argument block for the NODE. UUO's .NDLND function
; This generates a list of all the nodes in the network by number
NODNUM: BLOCK 1 ;Header for UUO
NODBIN: BLOCK MAXNOD ;The list of the node numbers
NODNAM: BLOCK MAXNOD ;The list of the node names
SUBTTL Tables to allow wildcarding node names
;** List of valid node spec's
SPCCNT: BLOCK 1 ;Count of valid specs
SPCFLG: BLOCK MAXSPC ;List for flags pertaining to specs
;LH bits - non error conditions
SP.ANF==400000 ;Node found in the ANF10 network
SP.DEC==200000 ;Node found in the DECnet network
;RH bits - error conditions
SP.NNN==400000 ;Node not found
SP.NWD==200000 ;Node went away while processing
SPCLST: BLOCK MAXSPC ;List of node specs we have read
WLDLST: BLOCK MAXSPC ;List of wild card masks
;** Our model of an NDB. We copy the nodes NDB here so we can get it easier
NNM: BLOCK 1 ;Node number
SNM: BLOCK 1 ;Node name in sixbit
SID: BLOCK 10 ;Software ID (asciz)
DAT: BLOCK 10 ;Software date (asciz)
LMA: BLOCK 1 ;Last NCL message assigned
LMS: BLOCK 1 ;Last NCL ACK message sent
LAR: BLOCK 1 ;Last NCL ACK recieved
LAP: BLOCK 1 ;Last NCL ACK processed
LMR: BLOCK 1 ;Last NCL message recieved
LMP: BLOCK 1 ;Last NCL message processed
LAS: BLOCK 1 ;Last NCL ACK sent
MOM: BLOCK 1 ;Maximum outstanding message counter
TOP: BLOCK 20 ;Network topology table in the form
;XWD Level , Node
CNF: BLOCK 20 ;Configuration table in the form
;XWD Object , Number
ENDB: BLOCK 1 ;End of our NDB
SUBTTL Scan related switces
;** Scan switch storage
FIRSW: ;Start of switch area
WIDWD: BLOCK 1 ;/WIDTH:nn switch.
FASWD: BLOCK 1 ;Short listing switch
SILWD: BLOCK 1 ;/SILENCE switch
ANF10W: BLOCK 1 ;/ANF10 switch
DECNWD: BLOCK 1 ;/DECNET switch
LATNWD: BLOCK 1 ;/LAT switch
URCHWD: BLOCK 1 ;/UNREACHABLE switch
HEADWD: BLOCK 1 ;/HEADERS switch
BRIEWD: BLOCK 1 ;/BRIEF switch
TOPWD: BLOCK 1 ;/TOPOLOGY switch
ERRWD: BLOCK 1 ;/ERROR switch
COSTWD: BLOCK 1 ;/COST switch
SORTWD: BLOCK 1 ;/SORT switch
LINKWD: BLOCK 1 ;/LINKS switch
;** The following 12 locations must be contigous and in the same order
MCRWD: BLOCK 1 ;Switch for nodes with "MCR"
TTYWD: BLOCK 1 ;Switch for nodes with "TTY"
CDRWD: BLOCK 1 ;Switch for nodes with "CDR"
LPTWD: BLOCK 1 ;Switch for nodes with "LPT"
PTRWD: BLOCK 1 ;Switch for nodes with "PTR"
PTPWD: BLOCK 1 ;Switch for nodes with "PTP"
PLTWD: BLOCK 1 ;Switch for nodes with "PLT"
MTAWD: BLOCK 1 ;Switch for nodes with "MTA"
DTAWD: BLOCK 1 ;Switch for nodes with "DTA"
TSKWD: BLOCK 1 ;Switch for nodes with "TSK"
RDAWD: BLOCK 1 ;Switch for nodes with "RDA"
CDPWD: BLOCK 1 ;Switch for ndoes with "CDP"
DDPWD: BLOCK 1 ;Switch for nodes with "DDP"
NDEV==.-MCRWD ;Length of table of device switches
TYPWD: BLOCK 1 ;Value for the /TYPE switch
LASTSW: ;Last switch location
;** Other random variables used in odd places
JOB: BLOCK 1 ;Our job number
MATCH: BLOCK 1 ;Count of matches or match errors
CARWID: BLOCK 1 ;The width we are using
FIRSTL: BLOCK 1 ;Count of times through the SHOLST code
SBMCNT: BLOCK 1 ;Count of Scan block error message
OFFSET: BLOCK 1 ;The starting offset
WMATCH: BLOCK 1 ;Flag for status of a wildcard search
HPOS: BLOCK 1 ;The current horizontallocation of the carriage
NFECNT: BLOCK 1 ;Number of non-fatal errors
OUTCON: BLOCK 1 ;Output control word
ANFCNT: BLOCK 1 ;Count of nodes that were found to match specs
FTANF: BLOCK 1 ;-1 means monitor has ANF10 software
FTDEC: BLOCK 1 ;-1 means monitor has DECnet software
FTEND: BLOCK 1 ;-1 means DECnet running as ethernet endnode
FTLAT: BLOCK 1 ;-1 means monitor has LAT software
TEMP: BLOCK BLKSIZ+1 ;Our scratch area
;** TTY buffer space
NCHAR: BLOCK 1 ;Number of characters in the buffer
BUFFP: BLOCK 1 ;Pointer into the buffer
BUFFER: BLOCK ^D100 ;TTY buffer
BUFSIZ==<<.-BUFFER> * 5 > - 2 ;Number of characters in the buffer
SUBTTL Scan block storage area
;** Counters to keep track of the Scan block allocation
OUTFIL: BLOCK 1 ;Number of output specs
INFIL: BLOCK 1 ;Number of input specs
NUMBLK: BLOCK 1 ;Number of scan blocks allocated so far
;** Default area to store Scan blocks.
; Must be at the end of core incase we want to expand
SBLKS: BLOCK PREALO*BLKSIZ ;Make large enough to hold 1 Scan block
ENDAT: ;End of our low seg to be zeroed
SUBTTL Start up and main loop code
RELOC ;Back to pure code
;** Here to get the show on the road
START: TDZA P,P ;Run start
MOVEI P,1 ;CCL start
MOVEM P,OFFSET ;Save starting offset for Scan
MOVE P,[PSIZ,,PDL] ;Set up the stack
RESET ;RESET to prevent address checks
MOVEI T1,START ;Get the reenter address
MOVEM T1,.JBREN ; and set it up
PUSHJ P,INITIA ;Clear the data base...
PUSHJ P,FLUSH ;Set up the output buffer header
PUSHJ P,ISCN ;Initalize Scan
; JRST LOOP ;Fall into the main loop
;** Here to process the main loop
LOOP: PUSHJ P,TSCN ;SCAN a command line
PUSHJ P,DISECT ;Parse the node spec's
PUSHJ P,ANF10 ;Check out the ANF10 network
PUSHJ P,DECNET ;Check out the DECnet network
PUSHJ P,LATSER ;Check out the LAT 'network'
PUSHJ P,ERRSCN ;Check if node constraints too tight
LOOP1: SKIPE OFFSET ;Did we CCL start?
JRST FINISH ;No, exit and flush buffers
PUSHJ P,.ISLGI ;Are we logged in?
JRST FINISH ;No, exit and flush buffers
PUSHJ P,FLUSH ;Output anything in the buffer
PUSHJ P,INITIA ;Clear the data base...
PUSHJ P,FLUSH ;Set up our buffer headers again
JRST LOOP ;and look for another line of input
SUBTTL Data initialization routine
;** Routine to reset the data areas
INITIA: HLRZ T1,.JBSA ;Reduce our core back to small
CORE T1, ;as we should be.
JFCL ;We don't care
MOVE T2,OFFSET ;Save our start address offset
MOVE T1,[STDAT,,STDAT+1] ;Get the start and end of impure data
SETZM STDAT ;Zero the first word
BLT T1,ENDAT ;to the last word
SETOM FIRSW ;Set the first location of the
MOVE T1,[FIRSW,,FIRSW+1] ;Switch block to -1, then
BLT T1,LASTSW-1 ;The last one
;*All switchs must be initalized
;to -1 or Scan won't work right
MOVE T1,[INT,,INTBLK] ;initalize interrupt control block
BLT T1,INTBLK+IBLKLN ;from data in the high seg
MOVEI T1,.TOWID ;Set up the argument block for TTY width
MOVEM T1,TTWID ;So we can find his TTY's width
MOVEI T1,MAXNOD+1 ;The max number of nodes we can handle
MOVEM T1,NODNUM ;So we can build tables of nodes
ADDI T1,2 ;Fix the value for the
MOVEM T1,NODBLK ;.NDNDB function of the NODE. UUO
MOVEM T2,OFFSET ;Restore the offset
PJOB T2, ;Get our job number
MOVEM T2,JOB ;Save it
TRMNO. T2, ;Get our TTY's UDX
SETO T2, ;No, TRMNO. error, default is -1
MOVEM T2,UDX ;Yes, save it in TRMOP. argument block
MOVEI T1,.TOWID ;TRMOP. width function
MOVE T3,[XWD 2,T1] ;Set up to get the TTY width
TRMOP. T3, ;Try for it
MOVEI T3,DEFWID ;Error, use the default width!
MOVEM T3,CARWID ;Save for other routines
MOVE T4,[%FTPER] ;Get the feature test word
GETTAB T4, ;...
PUSHJ P,GTABER ;GETTAB error? tell user and die
TRNN T4,F%NET&777777 ;Do we have network software?
TDZA T1,T1 ;No, zero the flag
SETO T1, ;Yes, set the flag
MOVEM T1,FTANF ;Remember ANF flag
MOVE T4,[%CNST2] ;Get the monitor status word
GETTAB T4, ;...
PUSHJ P,GTABER ;GETTAB error? tell user and die
TLNN T4,(ST%D36) ;DECnet here?
TDZA T1,T1 ;No, zero the flag
SETO T1, ;Yes, set the flag
MOVEM T1,FTDEC ;Remember DECnet flag
TLNN T4,(ST%END) ;DECnet ethernet endnode?
TDZA T1,T1 ;No, zero the flag
SETO T1, ;Yes, set the flag
MOVEM T1,FTEND ;Remember DECnet ethernet endnode flag
SETOM FTLAT ;Assume LAT service for the nonce
POPJ P, ;Done...return
SUBTTL ANF10 processing loop
;** Here to do the ANF10 network display
ANF10: SKIPE FTANF ;Do we have ANF10 software?
SKIPN ANF10W ;Did we have /NOANF?
POPJ P, ;Yes just return
SKIPLE LINKWD ;/LINKS??
SKIPLE ANF10W ;Specify /ANF10?
CAIA ;Sense is wrong
POPJ P, ;YES, skip ANF10 output
SKIPG ANF10W ;Specify /ANF10?
SKIPG DECNWD ;Specify DECnet list?
CAIA ;Sense is wrong
POPJ P, ;Yes, just return
PUSHJ P,ANFTAB ;Build the ANF10 tables
PUSHJ P,ANFWLD ;Resolve ANF10 wildcarded node names
SKIPN ANFCNT ;Do we have anything to print?
POPJ P, ;No, quit now and save computes
PUSHJ P,ANFHEA ;Do ANF10 headers
MOVN L1,NODNUM ;Negate the number of nodes
HRLZS L1 ;Make it an AOBJN counter
ANFLOP: HRRZ CN,NODBIN(L1) ;Get the current node number
MOVSI T1,SP.ANF ;Do we want to list this node?
TDNN T1,NODBIN(L1) ;???
JRST ANFLO1 ;Nope!
PUSHJ P,BLDNDB ;Build a copy of the node's NDB
JRST ANFLO1 ;Skip the rest, not quite there
PUSHJ P,SELECT ;Does node meet switch constraints?
TLNE F,F.SEL ;Is the node selected for printing?
PUSHJ P,PRINFO ;Yes, Print selected info
ANFLO1: AOBJN L1,ANFLOP ;Increment and loop till done
PJRST CRLFH ;Finish with a CRLF
;Here to print the ANF10 header, if we have any nodes to print and
;if we did not specify /NOHEADERS
ANFHEA: SKIPN HEADWD ;Did they say no headers?
POPJ P, ;Yes, don't!
MOVEI T1,[ASCIZ \[ANF10 network: connected to \] ;Say what we are doing
PUSHJ P,.TSTRG## ;...
MOVE T3,UDX ;Get our TTY's UDX
GTNTN. T3, ;Change to NODE,,LINE
SETZ T3, ;Don't care, catch it later
HLRZS T3 ;Make the node number
MOVEI T2,2 ;No, set up an argument block
MOVE T1,[.NDRNN,,T2] ;and an ac
NODE. T1, ;Use NODE. UUO to check node
JRST [MOVEI T1,[ASCIZ \??????\] ;Unknown
PUSHJ P,.TSTRG## ;Type it
JRST .+2] ;Continue
PUSHJ P,.TSIXN## ;and type it
MOVEI T1,[ASCIZ \(\] ;Open paren for the number
PUSHJ P,.TSTRG## ;...
MOVE T1,T3 ;Get the local node's number
PUSHJ P,.TOCTW## ;Type it in octal
MOVEI T1,[ASCIZ \), located at \] ;Close the node name
PUSHJ P,.TSTRG## ;Type it out
MOVEI T3,.GTLOC ;Get where we are located
HRL T3,JOB ;Our job #
GETTAB T3, ;Do the GETTAB
SETZ T3, ;Don't care, catch it later
MOVEI T2,2 ;No, set up an argument block
MOVE T1,[.NDRNN,,T2] ;and an ac
NODE. T1, ;Use NODE. UUO to check node
JRST [MOVEI T1,[ASCIZ \??????\] ;Unknown
PUSHJ P,.TSTRG## ;Type it
JRST .+2] ;Continue
PUSHJ P,.TSIXN## ;and type it
MOVEI T1,[ASCIZ \(\] ;Open paren for the number
PUSHJ P,.TSTRG## ;...
MOVE T1,T3 ;Get the local node's number
PUSHJ P,.TOCTW## ;Type it in octal
MOVEI T1,[ASCIZ \), \] ;Close the node name
PUSHJ P,.TSTRG## ;Type it out
MOVE T1,NODNUM ;Get the node number
PUSHJ P,.TDECW## ;Type the number of nodes
MOVE T1,NODNUM ;Get the node number
CAIG T1,1 ;Is it singular or plural
SKIPA T1,[[ASCIZ \ node]\]] ;Singular
MOVEI T1,[ASCIZ \ nodes]\] ;Plural
PUSHJ P,.TSTRG## ;...
PJRST CRLFH ;Cap off ANF header with a <CR><LF>
;** Here to resolve the wild cards in the node spec's we got
ANFWLD: SKIPN T1,SPCCNT ;Do we have any specs
JRST ANFWL4 ;None, take the default
MOVN L1,T1 ;Get the negative count of specs
HRLZS L1 ;Make an AOBJN pointer
ANFWL1: MOVE T3,SPCLST(L1) ;Get the name
SKIPN T4,WLDLST(L1) ;Is this a wild card entry?
PUSHJ P,ANFWL6 ;No, make sure it's a name and -1 mask
ANDCAM T4,T3 ;Mask it
SETZ T1, ;Clear the match counter
MOVN L2,NODNUM ;Get count of known nodes
HRLZS L2 ;Make an AOBJN pointer
ANFWL2: MOVE T2,NODNAM(L2) ;Get a node name
ANDCAM T4,T2 ;Mask it
CAME T2,T3 ;Match?
JRST ANFWL3 ;No, Try the next one
AOS ANFCNT ;Increment the count of nodes found
MOVSI T1,SP.ANF ;Yes, Flag it to be listed
IORM T1,SPCFLG(L1) ;Mark the match in the spec flags
IORM T1,NODBIN(L2) ;Mark the match in known node list
ANFWL3: AOBJN L2,ANFWL2 ;Loop over all known nodes
AOBJN L1,ANFWL1 ;And all node specs
POPJ P, ;Return
;Here to set up for the default case
ANFWL4: MOVN T1,NODNUM ;Get the number of nodes
HRLZ T1,T1 ;Make an AOBJN pointer
MOVSI T2,SP.ANF ;"LIST NODE" Flag
ANFWL5: IORM T2,NODBIN(T1) ;Flag all nodes
AOBJN T1,ANFWL5 ;Loop over all nodes
AOS ANFCNT ;Increment the count of matches
POPJ P, ;Return
;Here to setup mask for the non-wilcarded case
ANFWL6: SETZ T4, ;Non-wildcard mask is 0
MOVEI T2,2 ;No, set up an argument block
ANFWL7: MOVE T1,[.NDRNN,,T2] ;and an ac
NODE. T1, ;Use NODE. UUO to check node
POPJ P, ;Error, Use what we have to use
MOVE T3,T1 ;Put it where it's expected
TLNN T1,777777 ;Is what we have a name?
JRST ANFWL7 ;Try for a SIXBIT result
POPJ P, ;No, Just return
;** Here to build our network tables, this is our snapshot of the network
ANFTAB: MOVE T1,[XWD .NDLND,NODNUM] ;Set up ac for NODE. UUO
NODE. T1, ;Can we get the table of node numbers?
PUSHJ P,NODERR ;No, tell user why and die
MOVEM T1,NODNUM ;Stash the number of nodes in network
MOVE T1,SORTWD ;Get the sort status
JUMPL T1,ANFTA1 ;No switch, default to sorted
CAIE T1,SRT.DF ;Default sort?
CAIN T1,SRT.NU ;Did the user type /SORT:NUMBER
ANFTA1: PUSHJ P,ANFSRT ;Yes, Sort the numbers
MOVN L2,NODNUM ;Negate the number of nodes
HRLZS L2 ;Make it an AOBJN counter
MOVEI T3,2 ;Get the argument block length
ANFTA2: MOVE T4,NODBIN(L2) ;Get a node number
MOVE T1,[XWD .NDRNN,T3] ;Set up T1 for NODE. UUO
NODE. T1, ;Can we change number to sixbit name?
SETZ T1, ;No, make it a zero name and wing it
MOVEM T1,NODNAM(L2) ;Yes, stash in ajacent table of names
AOBJN L2,ANFTA2 ;Loop till done
MOVE T1,SORTWD ;Get the sort status
CAIN T1,SRT.NA ;Did the user type /SORT:NAME
PUSHJ P,ANFNSR ;Yes, Sort them by name
CPOPJ: POPJ P, ;Return
;** Here to shellsort the node names gotten above
ANFNSR: HRRZ T1,NODNUM ;T1=Number_of_nodes
ANFNS1: LSH T1,-1 ;T1=T1/2
JUMPE T1,CPOPJ ;IF T1=0 then RETURN
MOVEI T2,1 ;T2=1
ANFNS2: HRRZ T3,T2 ;T3=T2
ANFNS4: HRRZ T4,T3
ADDI T4,(T1) ;T4=T3+T1
MOVE T5,<NODNAM-1>(T4) ;T5=node[T3+T1]
CAML T5,<NODNAM-1>(T3) ;IF node[T3] <= node[T3+T1]
JRST ANFNS3 ;then GOTO SORT3
EXCH T5,<NODNAM-1>(T3)
MOVEM T5,<NODNAM-1>(T4) ;exchange
MOVE T5,<NODBIN-1>(T4) ;Exchange the node numbers too
EXCH T5,<NODBIN-1>(T3)
MOVEM T5,<NODBIN-1>(T4) ;exchange
SUBI T3,(T1) ;T3=T3-T1
JUMPG T3,ANFNS4 ;IF T3>=1 GOTO SORT4
ANFNS3: HRRZ T5,NODNUM ;delayed T2=T2+1
SUBI T5,1(T1) ;then comparison
CAILE T2,(T5) ;IF T2>N-T1 then
AOJA T2,ANFNS1 ;GOTO SORT1
AOJA T2,ANFNS2 ;ELSE GOTO SORT2
;** Here to shellsort the node numbers gotten above
ANFSRT: HRRZ T1,NODNUM ;T1=Number_of_nodes
ANFSR1: LSH T1,-1 ;T1=T1/2
JUMPE T1,CPOPJ ;IF T1=0 then RETURN
MOVEI T2,1 ;T2=1
ANFSR2: HRRZ T3,T2 ;T3=T2
ANFSR4: HRRZ T4,T3
ADDI T4,(T1) ;T4=T3+T1
MOVE T5,<NODBIN-1>(T4) ;T5=node[T3+T1]
CAML T5,<NODBIN-1>(T3) ;IF node[T3] <= node[T3+T1]
JRST ANFSR3 ;then GOTO SORT3
EXCH T5,<NODBIN-1>(T3)
MOVEM T5,<NODBIN-1>(T4) ;exchange
SUBI T3,(T1) ;T3=T3-T1
JUMPG T3,ANFSR4 ;IF T3>=1 GOTO SORT4
ANFSR3: HRRZ T5,NODNUM ;delayed T2=T2+1
SUBI T5,1(T1) ;then comparison
CAILE T2,(T5) ;IF T2>N-T1 then
AOJA T2,ANFSR1 ;GOTO SORT1
AOJA T2,ANFSR2 ;ELSE GOTO SORT2
SUBTTL Build a node data block
;** Here to build a copy of the node's NDB in our space
BLDNDB: HRRZM CN,NNM ;Stash node number
HRRZM CN,CURNOD ;Again for NODE. UUO
MOVEI T1,2 ;Set up the field number
MOVEM T1,FLDNUM ;for the NODE. UUO
MOVE T2,CN ;Get the current node #
MOVE T3,[.NDRNN,,T1] ;Set up the AC
NODE. T3, ;Try to get the name
JRST BLDND2 ;Oops, node in a funny state
MOVEM T3,SNM ;Stash it
MOVE T1,[.NDNDB,,NODBLK] ;Set up the ac
AOS FLDNUM ;Point to next field in NDB
NODE. T1, ;Get next info?
JRST BLDND3 ;No, investigate
MOVE T3,[DATBLK,,SID] ;Yes, set up to BLT software ID
BLT T3,DAT ;to our NDB copy
AOS FLDNUM ;Point to software date field
NODE. T1, ;Get more info?
JRST BLDND4 ;No, investigate
MOVE T3,[DATBLK,,DAT] ;Yes, set up to BLT date
BLT T3,LMA ;to our NDB copy
AOS FLDNUM ;Point to next field
MOVE L2,[-10,,LMA] ;make loop counter for one word fields
BLDND1: NODE. T1, ;Get the info?
JRST BLDND4 ;No, investigate
MOVE T2,DATBLK ;Yes, move it to
MOVEM T2,(L2) ;our NDB copy
AOS FLDNUM ;Increment to point to next field
AOBJN L2,BLDND1 ;Loop till done
NODE. T1, ;Get the topology table?
JRST BLDND5 ;No, investigate
MOVE T3,[DATBLK,,TOP] ;Yes, copy topology table
BLT T3,CNF ;to our NDB copy
AOS T3,FLDNUM ;Point to the configuration field
NODE. T1, ;Can we get it?
JRST BLDND6 ;No, investigate
MOVE T3,[DATBLK,,CNF] ;Yes, BLT it to
BLT T3,ENDB ;our NDB copy
AOS (P) ;Skip return for success
POPJ P, ;Return
BLDND2: SETZM SNM ;Zero the info we can not get
BLDND3: SETZM SID ;...
BLDND4: SETZM DAT ;...
BLDND5: SETZM TOP ;...
BLDND6: SETZM CNF ;...
PJRST OFLINE ;Tell the user
SUBTTL ANF10 output routines
;** Here to decide whether or not to print a node. The decision is
; based on the selection of /<device-name> switches.
; A skip return is taken if the node is not to be printed.
SELECT: MOVE T1,[-NDEV,,0] ;Make a AOBJN pointer to switch words
TLO F,F.SEL
SELEC0: SKIPLE MCRWD(T1) ;Switch selected for a match?
JRST [SKIPGE DECNWD ;Did we specify DECnet listing?
SETZM DECNWD ;No, don't list if device switch
PUSHJ P,SEL0 ;Yes, Look for a match
TLZA F,F.SEL ;No match, clear the selected flag
JRST SELEC1 ;Continue
POPJ P,] ;No match, return
SKIPN MCRWD(T1) ;Switch selected for a non-match?
JRST [PUSHJ P,SEL0 ;Yes, Look for a match
CAIA ;Opposite sense from before
TLZA F,F.SEL ;No match, clear the selected flag
JRST SELEC1 ;Continue
POPJ P,] ;No match, return
SELEC1: AOBJN T1,SELEC0 ;Loop through all switches
SETO T1, ;Make T1 -1
CAMN T1,TYPWD ;Did we specify /TYPE:?
JRST SELEC4 ;No, don't check it
MOVE T1,TYPWD ;Get the type we are looking for
MOVEI T2,SID ;Point to the software ID
PUSHJ P,ASCSIX ;See if it matches
TLZ F,F.SEL ;No Match, Clear the print flag
SELEC4: AOS MATCH ;Count the number of matches
POPJ P, ;We want to print this node, just return
;Subroutine to see if a device type is in the NDB The device type
;is in the RH of T1
;CALL PUSHJ P,SEL0
; Return with no match
; Return with a match
SEL0: MOVE T2,[-NDEV,,0] ;AOBJN pointer to the configuration info
SEL1: SKIPN CNF(T2) ;No more devices?
POPJ P, ;None, just return, no match
HLRZ T3,CNF(T2) ;Get the object type
CAIN T3,(T1) ;Are they the same device?
AOSA (P) ;Skip return means we will print it
AOBJN T2,SEL1 ;No, loop till found or NDEV
POPJ P, ;...
;** Routine to compare the first six characters of an ASCIZ string
; with the SIXBIT value it T1
;
; call: T1=SIXBIT\value\
; T2=[ASCIZ\string\]
; PUSHJ P,ASCSIX
; <no match> ;First six chars of string converted to sixbit in T2
; <match>
ASCSIX: PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,[-6,,-6] ;Set up an AOBJN pointer
SETZB T4,TEMP ;Clear temps where necessary
HLL T2,[POINT 7,0] ;Byte pointer for the asciz string
MOVE T3,[POINT 6,TEMP] ;Byte pointer for sixbit conversion
ASCSI1: ILDB T4,T2 ;Get a byte from the string
SUBI T4," " ;Make SIXBIT
JUMPLE T4,ASCEOS ;Is the character a space?
IDPB T4,T3 ;Place into the save byte
AOBJN T1,ASCSI1 ;Loop about 6 times
ASCEOS: PUSHJ P,.POP4T## ;Restore the temps
CAMN T1,TEMP ;Is it the same??
AOS (P) ;Yes, do the skip return
CAME T1,TEMP ;Did we match?
MOVE T2,TEMP ;No, copy what we had to T2
POPJ P, ;Return
;** Here to print the information about a node.
; This routine dispatches according to the switches selected:
; /SILENCE, /FAST, /BRIEF, /WIDTH, /TOPOLOGY
;
; destroys many registers
PRINFO: AOS MATCH ;If here we must have had a match
SKIPLE SILWD ;/SILENCE?
POPJ P, ;Yes, Just return...errors only!
PRINF1: SKIPLE TOPWD ;If /TOPOLOGY was specified
JRST PRTOPO ; then go print it
SKIPG FASWD ;/NOFAST or default?
PUSHJ P,PFIRST ;Yes, print the first line
SKIPLE FASWD ;/FAST?
PUSHJ P,SHOLST ;Yes, do a short list
SKIPG FASWD ;/FAST?
JRST PRINF2 ;No, /BRIEF is the default
SKIPE BRIEWD ;Did he say /BRIEF?
POPJ P, ;Yes, don't print configuration
PRINF2: SKIPG BRIEWD ;Here if /NOBRIEF or default
PUSHJ P,PCONF ;No, print the configuration
PRINF3: POPJ P, ;Return to loop
;** Here to print the first line in the default format
;
PFIRST: MOVEI T1,[ASCIZ \Node \] ;Print the lead word
PUSHJ P,.TSTRG## ;...
MOVE T1,SNM ;Get the sixbit node name
PUSHJ P,.TSIXN## ;and print it
PUSHJ P,.TTABC## ;followed by a <tab>
MOVEI T1,"(" ;Get a <left-paren>
PUSHJ P,.TCHAR## ;and print it
MOVE T1,NNM ;Get out node number
PUSHJ P,.TOCTW## ;and print it in octal
MOVEI T1,")" ;Get a <right-paren>
PUSHJ P,.TCHAR## ;and print it
PUSHJ P,.TTABC## ;followed by a <tab>
MOVEI T1,^D28 ;This is our horizontal position
MOVEM T1,HPOS ;so set it
MOVEI T1,SID ;Point at the software ID (asciz)
PUSHJ P,KILBLK ;And kill leading blanks
PUSHJ P,TCARE ;and print it carefully
PUSHJ P,.TTABC## ;followed by a <tab>
MOVEI T1,DAT ;Point to the software date (asciz)
PSTCRL: PUSHJ P,TCARE ;and print it carefully
PJRST CRLFH ;Cap off with a <CR><LF>
;Here to print topology information for a node
;P1 points to topo, p2 = count
PRTOPO: SETZ P2, ;Clear the count of chars printed
MOVEI T1,[ASCIZ \Node \] ;Lead off with "node<tab>"
PUSHJ P,.TSTRG## ;...
MOVE T1,SNM ;Get the name
PUSHJ P,.TSIXN## ; and print it
PUSHJ P,.TTABC## ;Print a <TAB>
MOVEI T1,"(" ;Get an open paren
PUSHJ P,.TCHAR## ; and print it
MOVE T1,NNM ;Get the node's number
PUSHJ P,.TOCTW## ; and print it
MOVEI T1,")" ;Finally, get the close paren
PUSHJ P,.TCHAR## ; and print it
PUSHJ P,.TTABC## ;Print another <TAB>
MOVEI P2,30 ;3 <TAB>s bring us to col # ^D24
MOVEM P2,HPOS ;Save our horizontal position
;Set up to output the topology information
MOVEI P1,TOP ;Get the address of the topology
SKIPN (P1) ; and if there aren't any
JRST [MOVEI T1,[ASCIZ \None\]; neighbors, then
PJRST PSTCRL] ; tell the user
JRST PRTOP3 ;Skip the ","<TAB> the first time
;Here to type a comma in the correct place
PRTOP2: MOVEI T1,[ASCIZ \, \] ;Point to ","<space>
CAIE P2,10 ;No ","<TAB> if CRLFH called
PUSHJ P,TCARE ;type it
;Here to print the neighbor's node number
PRTOP3: MOVE P2,HPOS ;Get the horizontal position
HRRZ T1,(P1) ;Get the neighbors node number
PUSHJ P,FLATSO ;Account for the size
PUSHJ P,.TOCTW## ; and print it in octal
SKIPE COSTWD ;Should we print the link costs?
PUSHJ P,PRCOST ;Print the link costs
SKIPE 1(P1) ;See if there are any more entrys
AOJA P1,PRTOP2 ; and if so, go process them
PUSHJ P,CRLFH ;Cap off the topology/cost line
SKIPN BRIEWD ;Check for configuration typeout
PUSHJ P,PCONF ;Yes, do the configuration
POPJ P, ;No more neighbors to process
;Here to print the link costs
PRCOST: HLRZ T1,(P1) ;Get the link's cost
PUSHJ P,FLATSD ;Account for the size
ADDI P2,2 ;Allow for the ")" & "("
MOVE T1,P2 ;Save P2
SUB T1,HPOS ;Get the length of the string
CAML P2,CARWID ;exceeded the carrage width?
PUSHJ P,CRLFH ;Yes, <CRLF> now
ADDM T1,HPOS ;add the length of the string
MOVE P2,HPOS ;Restore the horizontal postion
MOVEI T1,"(" ;Get an open paren
PUSHJ P,.TCHAR## ; and print it
HLRZ T1,(P1) ;Get the link's cost
PUSHJ P,.TDECW## ; and print it in decimal
MOVEI T1,")" ;Finish off the entry
PJRST .TCHAR## ; with a close paren
;** Routines to count (in P2) the number of chars used in the printed
; representation of the item in T1.
FLATSN: PUSH P,T1 ;Here for counting names
MOVEM P2,HPOS ;Save the horizontal position
FLATN1: SKIPE T1 ;If we haven't zeroed the whole wd
JRST [LSH T1,6 ;yet, then shift the name
AOJA P2,FLATN1] ;and count it
CAML P2,CARWID ;Can this fit??
PUSHJ P,CRLFH ;Too big to fit, <CRLF> now
MOVE P2,HPOS ;Restore the local count
POP P,T1 ;Restore the name
POPJ P, ;and return
FLATSO: PUSH P,T1 ;Here for octal numbers
MOVEM P2,HPOS ;Save the horizontal position
SKIPE T1 ;Worry about a zero
FLATO1: SKIPE T1 ;if we're not done yet
JRST [LSH T1,-3 ;divide the number by 8
AOJA P2,FLATO1] ;and count the digit
CAML P2,CARWID ;Can this fit??
PUSHJ P,CRLFH ;Too big to fit, <CRLF> now
MOVE P2,HPOS ;Restore the local count
POP P,T1 ;restore the number
POPJ P, ;and return
FLATSD: PUSH P,T1 ;Here for decimal numbers
SKIPE T1 ;Make sure zero counts 1
FLATD1: SKIPE T1 ;If there are still more digits
JRST [IDIVI T1,5+5 ;divide by 10
AOJA P2,FLATD1] ;and count the char
MOVEM P2,HPOS ;Save the horizontal position
POP P,T1 ;Restore the number
POPJ P, ;and return
;** Here to print the configuration information
PCONF: MOVE P1,[XWD -20,CNF] ;Make a AOBJN pointer
PUSHJ P,.TTABC## ;Type a <tab>
MOVEI T5,10 ;and set up horizontal position
PCONF1: SKIPN (P1) ;Any more devices?
JRST PCONF2 ;No, all done
HLRZ T1,(P1) ;Yes, get the configuration word
MOVE T1,CTAB(T1) ;and the asciz name string
PUSHJ P,.TSTRG## ;and print it
HRRZ T1,(P1) ;Get how many
PCONF3: IDIVI T1,^D10 ;and find the number of digits
ADDI T5,1 ;add one to the horizontal position
JUMPG T1,PCONF3 ;loop till we have counted all digits
HRRZ T1,(P1) ;Get how many, again
PUSHJ P,.TDECW## ;and print it this time
MOVEI T1,"]" ;Get a <left bracket>
PUSHJ P,.TCHAR## ;and print it
PUSHJ P,.TSPAC## ;followed by a space
ADDI T5,6 ;Add number of characters in the:
;device name [3]
;brackets [2]
;<space> [1]
;to the horizontal position
PUSH P,T5 ;save T5
ADDI T5,11 ;Add the max expected for the
;next device
CAMLE T5,CARWID ;Do we exceed the TTY's width?
JRST PCONF4 ;Yes, do a <CR><LF>
POP P,T5 ;No, restore T5 and
AOBJN P1,PCONF1 ;loop till done
PCONF2: PJRST CRLFH ;Cap off configuration line
PCONF4: SKIPG 1(P1) ;any more devices?
JRST PCONF5 ;Yes, loop back
PUSHJ P,CRLFH ;Type a <CR><LF>
PUSHJ P,.TTABC## ;and a <tab>
PCONF5: POP P,T5 ;then restore T5
MOVEI T5,10 ;Reset the horizontal position counter
AOBJN P1,PCONF1 ;and loop back
;** routine to produce a listing of nodes in the network
; by name and number only on one or two lines
SHOLSS: EXP [ASCIZ/)/] ;Zero
EXP [ASCIZ/) /] ;One
EXP [ASCIZ/) /] ;Two
EXP [ASCIZ/) /] ;Three
EXP [ASCIZ/) /] ;Four
EXP [ASCIZ/) /] ;Five
EXP [ASCIZ/) /] ;Six
EXP [ASCIZ/) /] ;Seven
EXP [ASCIZ/) /] ;Eight
EXP [ASCIZ/) /] ;Nine
EXP [ASCIZ/) /] ;Ten
EXP [ASCIZ/) /] ;Eleven
EXP [ASCIZ/) /] ;Twelve
EXP [ASCIZ/) /] ;Thirteen
EXP [ASCIZ/) /] ;Fourteen
EXP [ASCIZ/) /] ;Fifteen
SPCPRT=^D12
SHOLST: SKIPN FIRSTL ;Is this the first spec?
PUSHJ P,CRLFH ;Yes, do a <CR><LF>
AOS FIRSTL ;Count the number of specs we do
MOVE T2,HPOS ;Get our horizontal position
ADDI T2,SPCPRT ;INCREMENT by on tab to get here
IDIVI T2,SPCPRT ;Worst case node spec
IMULI T2,SPCPRT ;Make the number of 12 bit tabs
MOVEM T2,HPOS ;Save it for later
CAMLE T2,CARWID ;Enough space left?
JRST [PUSHJ P,CRLFH ;Do a <CR><LF>
MOVEI T1,SPCPRT ;Get new HPOS
MOVEM T1,HPOS ;Save the new position
JRST .+1] ;Continue
SETZ P1, ;Zero the position counter
MOVE T2,[POINT 6,SNM] ;Get the node name
MOVEI T1,6 ;Max number of characters in a name
SHOLS0: ILDB T3,T2 ;Get a character
JUMPE T3,SHOLS1 ;Is it blank?
ADDI P1,1 ;No, count characters in the spec
SOJG T1,SHOLS0 ;Have we looked at six characters?
SHOLS1: ADDI P1,2 ;Done, account for parens
SKIPA T1,NNM ;Get the node number, allowing for zero
SHOLS2: SKIPE T1 ;if we're not done yet
JRST [LSH T1,-3 ;divide the number by 8
AOJA P1,SHOLS2] ;and count the digit
MOVE T1,SNM ;Get the sixbit node name
PUSHJ P,.TSIXN## ;Type the node name
MOVEI T1,"(" ;Type a left paren
PUSHJ P,.TCHAR## ;...
HRRZ T1,NNM ;Type the node number
PUSHJ P,.TOCTW## ;in octal...
MOVEI T1,SPCPRT ;Our normal tab stop
SUBI T1,(P1) ;Subtract what we have
MOVE T1,SHOLSS(T1) ;to get pointer to fill string
PJRST .TSTRG ;Finish the entry
;** Here to do a carrage return/ line feed sequence
; and set HPOS (our horizontal position) to zero
CRLFH: SETZM HPOS ;Set the horizontal position back to
;the left margin
PJRST .TCRLF## ;And do a real <CR><LF>
;** Here to kill leading blanks or tabs from a string pointed to by T1
; Returns with T1 pointing to the start of the new string
; * destroys P3
KILBLK: PUSHJ P,.PSH4T## ;Save the temps
HLL T1,[POINT 7,0] ;Make T1 a byte pointer
MOVE T3,T1 ;Copy it
KILBL1: ILDB T2,T1 ;Load a byte
CAIN T2,40 ;Is it a <blank>
JRST KILBL1 ;Loop til we find a non-blank character
CAMN T1,T3 ;Are the byte pointers different?
JRST KILBL4 ;No, return to the caller
KILBL2: IDPB T2,T3 ;Deposit the current byte
ILDB T2,T1 ;Get another byte
JUMPN T2,KILBL2 ;Loop until zero byte
IDPB T2,T3 ;and deposit it
KILBL4: PUSHJ P,.POP4T## ;Restore the temps
POPJ P, ;and return
;** here to type a asciz string without exceeding the page width
; (if possible).
TCARE: PUSHJ P,.PSH4T## ;Save the temps
MOVE T3,HPOS ;Get the current horizontal position
HLL T1,[POINT 7,0] ;Make a byte pointer
TCARE1: ILDB T2,T1 ;Get the first byte
CAIN T2," " ;Is this a <tab>
JRST [ADDI T3,10 ;Yes, add to get to the next tab stop
TRZ T3,7 ;and get rid of the remainder
JRST .+2 ] ;Continue with corrected HPOS
AOS T3 ;Increment the string length
JUMPN T2,TCARE1 ;Loop till the end of the string
SOS T3 ;Correct for the Off By One error
MOVEM T3,HPOS ;Save our horizontal position
CAMLE T3,CARWID ;Is this less than the width?
PUSHJ P,CRLFH ;Reset HPOS and do a CRLF
TCARE3: PUSHJ P,.POP4T## ;and restore the temps
PJRST .TSTRG## ;Type the string and return
SUBTTL DECnet processing loop
;ROUTINE to do the DECnet part of the program
DECNET: SKIPE FTDEC ;Is there DECnet software??
SKIPN DECNWD ;Did they say /NODECNET??
POPJ P, ;Yes, just return
SKIPG DECNWD ;Did we get /DECNET?
SKIPG ANF10W ;Did we get /ANF10?
CAIA ;Wrong sense
POPJ P, ;Don't output the DECnet list
SKIPN FTDEC ;DECnet support in monitor?
POPJ P, ;No, just return
;Set up to get the list of all DECnet nodes
MOVE T5,[.DNLNN,,DNMAX] ;Argument for DNET. list node function
SKIPLE URCHWD ;Check the unreachable switch
TXOA T5,DN.FLK ;List of known nodes
TXO T5,DN.FLR ;List of active (reachable) nodes
MOVEM T5,DNLST ;Save the function code
MOVEI T5,DNLST ;Arg block for DNET.
DNET. T5, ;Get a list of node names
PUSHJ P,DNETER ;Error, Check it out
MOVE T3,.DNCNT(T5) ;Get the count of nodes
MOVEM T3,DNCNT ;Save it for later
MOVNS T3 ;Make an AOBJN pointer
HRLS T3 ;-count in LH
HRRI T3,2(T5) ;Point at the first node name
MOVEM T3,DNLOOP ;Save it for later reference
MOVE T1,SORTWD ;Get the sort status
JUMPL T1,DECNE1 ;No /SORT switch?
CAIE T1,SRT.DF ;Default sort?
CAIN T1,SRT.NA ;/SORT:NAME?
DECNE1: PUSHJ P,DNSRT ;Yes, sort the DECnet nodes by name
;Continued on next page
;Continued from previous page
;Get the local node name
MOVEI T5,DNBLK ;Point to the DNET. arg block
MOVE T2,[DN.FLE+<.DNLNN,,3>];Get the local node name
MOVEM T2,.DNFFL(T5) ;Save the function
DNET. T5, ;Get the local node name
PUSHJ P,DNETER ;Error, Check it out
MOVE T1,.DNCNT+1(T5) ;Get the local node name
MOVEM T1,DNLOC ;Save it
MOVEI T5,DNINF ;Pointer to DNET. argument block
MOVE T2,[.DNNDI,,DNINFL] ;Get local node's network address
MOVEM T2,.DNFFL(T5) ;...
MOVEM T1,.DNNAM(T5) ;Store local node's name
DNET. T5, ;Get network address of local node
PUSHJ P,DNETER ;Error, Check it out
MOVE T1,.DNADR(T5) ;Get local node's network address
MOVEM T1,DNADR ;Save for later
PUSHJ P,DECWLD ;Handle wild cards
SKIPN DNMCNT ;Any spec's match?
POPJ P, ;No, don't bother any more
PUSHJ P,DECHEA ;Print the header line if needed
PUSHJ P,CRLFH ;Lead off with a CRLF
SKIPE FTEND ;DECnet running as ethernet endnode?
POPJ P, ;Yes, all done, return
;Continued on next page
;Continued from previous page
DECLST: SKIPLE TOPWD ;Did they say /TOPOLOGY??
JRST DECTOP ;Yes, do the topology display
HLLZ L1,DNLOOP ;Get the DECnet AOBJN pointer
DECLS1: MOVSI T3,DN.LST ;Get the list-it bit
TDNN T3,DNBIT+2(L1) ;Do we list it?
JRST DECLS3 ;No, try the next one
;Do we just want nodes with links?
SKIPG LINKWD ;/LINKS??
JRST DECLS2 ;no, skip the check
PUSHJ P,DECINF ;Build a node info block
LDB T1,[POINTR .DNLLI(T5),DN.LNK] ;Get active links
JUMPE T1,DECLS3 ;Zero means ignore this node
DECLS2: MOVE T2,HPOS ;Get our horizontal position
ADDI T2,10 ;INCREMENT by on tab to get here
TRZ T2,7 ;Get rid of the remainder
MOVEM T2,HPOS ;Save it for later
CAMLE T2,CARWID ;Enough space left?
JRST [PUSHJ P,CRLFH ;Do a <CR><LF>
MOVEI T1,10 ;Get new HPOS
MOVEM T1,HPOS ;Save the new position
JRST .+1] ;Continue
MOVE T1,DNLST+2(L1) ;Get the sixbit node name
TLNN T1,770000 ;Make sure we have a top character
JRST [PUSH P,T1 ;[32] Remember node number
MOVEI T1,"(" ;[32] Blank, type number
PUSHJ P,.TCHAR## ;
LDB T1,[POINTR(0(P),DN%ARE)] ;[32] Area number
JUMPE T1,DECL2B ;[32] Skip if none
PUSHJ P,.TDECW## ;[32] Print area number
MOVEI T1,"." ;
PUSHJ P,.TCHAR## ;
DECL2B: POP P,T1 ;[32] Node number back
ANDI T1,DN%NOD ;[32] Except for area
PUSHJ P,.TDECW## ;
MOVEI T1,")" ;
PUSHJ P,.TCHAR## ;
JRST DECL2A] ;[32] Resume with tab
PUSHJ P,.TSIXN## ;Type the name
DECL2A: PUSHJ P,.TTABC## ;Print a <tab>
DECLS3: AOBJN L1,DECLS1 ;Loop
PJRST CRLFH ;Finish with a CRLF
;Get info about DECnet nodes
DECINF: MOVEI T5,DNINF ;Point to the DNET. UUO block
MOVE T1,[.DNNDI,,DNINFL] ;Function,,block size
MOVEM T1,.DNFFL(T5) ;Save it
MOVE T1,DNLST+2(L1) ;Get the sixbit node name
MOVEM T1,.DNNAM(T5) ;Save it
DNET. T5, ;Get the info
PUSHJ P,DNETER ;DNET.error, check it out
POPJ P, ;Return
;Routine to print the DECnet header if there are any nodes to print and
;the user has not specified /NOHEADERS
DECHEA: SKIPN HEADWD ;Did they say no headers?
POPJ P, ;Yes, just return
MOVEI T1,[ASCIZ \[DECnet network: local node \] ;Print the leader
PUSHJ P,.TSTRG## ;...
MOVE T1,DNLOC ;Get the local node name
PUSHJ P,.TSIXN## ;and type it too
MOVEI T1,[ASCIZ \, \] ;Local node name
PUSHJ P,.TSTRG## ;...
SKIPE FTEND ;DECnet running as ethernet endnode?
JRST [MOVEI T1,[ASCIZ \running as an ethernet endnode]\]
PJRST .TSTRG##] ;...
SKIPG T1,DNCNT ;Get the count of on-line nodes
JRST [MOVEI T1,[ASCIZ \no reachable nodes]\]
PJRST .TSTRG##] ;...
PUSHJ P,.TDECW## ;Type the number of nodes
MOVEI T1,[ASCIZ \ reachable\]
SKIPG URCHWD ;Just reachable?
PUSHJ P,.TSTRG## ;Yes, say so
MOVE T1,DNCNT ;Get the count back
CAIG T1,1 ;More than one
SKIPA T1,[[ASCIZ \ node\]] ;singular
MOVEI T1,[ASCIZ \ nodes\] ;plural
PUSHJ P,.TSTRG## ;...
LDB T1,[POINTR(DNADR,DN%ARE)] ;Get network area number
JUMPE T1,.TRBRK## ;Finish message if no area number
PUSH P,T1 ;Save area number a bit
MOVEI T1,[ASCIZ \ in area \] ;Add some explanation
PUSHJ P,.TSTRG## ;...
POP P,T1 ;Get back area number
PUSHJ P,.TDECW## ;Type area number
PJRST .TRBRK## ;Finish message and return
;DECTOP - print the "topology" of the DECnet network
DECTOP: MOVEI T1,[ASCIZ \Name Number Line Hops L.Links Delay
\]
SKIPE COSTWD ;Print the cost?
MOVEI T1,[ASCIZ \Name Number Line Cost Hops L.Links Delay
\]
PUSHJ P,.TSTRG## ;Type the header line
HLLZ L1,DNLOOP ;Get the DECnet AOBJN pointer
DECTO1: MOVSI T3,DN.LST ;Get the list-it bit
TDNN T3,DNBIT+2(L1) ;Do we list it?
JRST DECTO7 ;No, try the next one
PUSHJ P,DECINF ;Build a node information block
SKIPG LINKWD ;/LINKS??
JRST DECTO2 ;no, skip the check
LDB T1,[POINTR .DNLLI(T5),DN.LNK] ;Get active links
JUMPE T1,DECTO7 ;Zero means ignore this node
;Identify the node
DECTO2: MOVE T1,.DNNAM(T5) ;Get the node name
TLNN T1,770000 ;Make sure we have a node name
SETZ T1, ;Nope, don't type it out
PUSHJ P,.TSIXN## ;Type it
MOVEI T1,[ASCIZ \ (\] ;Tab over
PUSHJ P,.TSTRG## ;Type the string
MOVE T1,.DNADR(T5) ;Get the node number
TXNN T1,DN%ARE ;Is there an area number?
JRST DECTO3 ;No, continue
LDB T1,[POINTR(T1,DN%ARE)] ;Get area number
PUSHJ P,.TDECW## ;Type it
MOVEI T1,"." ;Add a seperator
PUSHJ P,.TCHAR## ;...
MOVE T1,.DNADR(T5) ;Get node number again
ANDX T1,DN%NOD ;Mask to just node within area
DECTO3: PUSHJ P,.TDECW## ;Type the node number
MOVEI T1,[ASCIZ \) \] ;Tab over
PUSHJ P,.TSTRG## ;Type the string
;Continued on next page
;Continued from previous page
;See if the node is reachable
LDB T1,[POINTR .DNRTR(T5),DN.RCH] ;Is the node reachable?
JUMPE T1,[MOVEI T1,[ASCIZ\Unreachable\]
PUSHJ P,.TSTRG## ;No, tell the user
JRST DECTO6] ;Continue with the next node
;Describe the connection to the node
MOVEI T1,.DNCKT(T5)
PUSHJ P,.TSTRG## ;If non-zero type the name
PUSHJ P,.TTABC## ;Tab over for fill
PUSHJ P,.TTABC## ;Tab over
;Check for the /COST switch setting
SKIPN COSTWD ;Print the cost?
JRST DECTO4
LDB T1,[POINTR .DNRTR(T5),DN.CST] ;Get the cost information
PUSHJ P,.TDECW## ;Print it
PUSHJ P,.TTABC## ;Tab over
DECTO4: LDB T1,[POINTR .DNRTR(T5),DN.HOP]
PUSHJ P,.TDECW## ;Print the number of hops
PUSHJ P,.TTABC## ;Tab over
;Tell about the logical links we have to the node
DECTO5: SKIPL .DNLLI(T5) ;Do we have valid information?
JRST DECTO6 ;No, finish the line
LDB T1,[POINTR .DNLLI(T5),DN.LNK] ;Get active links
PUSHJ P,.TDECW## ;Type it
PUSHJ P,.TTABC## ;Tab over
LDB T1,[POINTR .DNLLI(T5),DN.DLY] ;Get millisecond delay to node
PUSHJ P,.TDECW## ;Type it
DECTO6: PUSHJ P,.TCRLF## ;end line
DECTO7: AOBJN L1,DECTO1 ;Loop
POPJ P, ;Return
;Routine to select specific nodes to look at by dissecting the scan blocks
;L1 = AOBJN pointer to the list of DECnet node names in SIXBIT
DECWLD: SKIPN L1,SPCCNT ;Do we have any specs
JRST DECWL4 ;None, take the default
MOVNS L1 ;Get the negative count of specs
HRLZS L1 ;Make an AOBJN pointer
DECWL1: MOVE T3,SPCLST(L1) ;Get the name
SKIPN T4,WLDLST(L1) ;Is this a wild card entry?
SETZ T4, ;No, mask no names
ANDCAM T4,T3 ;Mask it
HLLZ L2,DNLOOP ;Get count of known nodes
DECWL2: MOVE T2,DNLST+2(L2) ;Get a node name
ANDCAM T4,T2 ;Mask it
CAME T2,T3 ;Match?
JRST DECWL3 ;No, Try the next one
AOS DNMCNT ;Count nodes that match
MOVSI T5,SP.DEC ;Yes, Flag it to be listed
IORM T5,SPCFLG(L1) ;Mark the match in the spec flags
MOVSI T5,DN.LST ;Flag node to be listed
IORM T5,DNBIT+2(L2) ;Mark the match in known node list
DECWL3: AOBJN L2,DECWL2 ;Loop over all known nodes
AOBJN L1,DECWL1 ;And all node specs
POPJ P, ;Return
;Here to set up for the default case
DECWL4: HLLZ T1,DNLOOP ;Get the number of nodes
MOVSI T2,DN.LST ;"LIST NODE" Flag
DECWL5: IORM T2,DNBIT+2(T1) ;Flag all nodes
AOBJN T1,DECWL5 ;Loop over all nodes
AOS DNMCNT ;Count a match
POPJ P, ;Return
SUBTTL DNSRT - SHELLsort the DECnet nodes
;DNSRT: T1=Number_of_nodes (N)
;DNSR1: T1=T1/2
; IF T1=0 then RETURN
; T2=1
;DNSR2: T3=T2
;DNSR4: IF node[T3] <= node[T3+T1] goto SORT3
; EXCH(node[T3],node[T3+T1])
; T3=T3-T1
; IF T3>=1 then goto SORT4
;DNSR3: T2=T2+1
; IF T2>N-T1 then goto SORT1
; goto sort2
DNSRT: HRRZ T1,DNCNT ;T1=Number_of_nodes
DNSR1: LSH T1,-1 ;T1=T1/2
JUMPE T1,CPOPJ ;IF T1=0 then RETURN
MOVEI T2,1 ;T2=1
DNSR2: HRRZ T3,T2 ;T3=T2
DNSR4: HRRZ T4,T3
ADDI T4,(T1) ;T4=T3+T1
MOVE T5,<DNLST+1>(T4) ;T5=node[T3+T1]
CAML T5,<DNLST+1>(T3) ;IF node[T3] <= node[T3+T1]
JRST DNSR3 ;then GOTO SORT3
EXCH T5,<DNLST+1>(T3)
MOVEM T5,<DNLST+1>(T4) ;exchange
SUBI T3,(T1) ;T3=T3-T1
JUMPG T3,DNSR4 ;IF T3>=1 GOTO SORT4
DNSR3: HRRZ T5,DNCNT ;delayed T2=T2+1
SUBI T5,1(T1) ;then comparison
CAILE T2,(T5) ;IF T2>N-T1 then
AOJA T2,DNSR1 ;GOTO SORT1
AOJA T2,DNSR2 ;ELSE GOTO SORT2
SUBTTL LAT processing routines
;Here to list info the LAT "network".
;
;As of this writing (18-Apr-85) the -10 doesn't support being itself a
;"LAT server", only a "LAT host", so we can only list servers since that
;is all we are listening for on the ethernet.
;
;Note also that since the LAT servers don't themselves broadcast their
;existence the -10 only knows about LAT servers that have in the past
;connected to the -10. As such, NETWORK can only type out a partial sum-
;mary of the LAT network.
LATSER: SKIPG LATNWD ;Want to see LATish info?
POPJ P, ;No, nothing to do here
PUSHJ P,LATHEA ;Type out a header if needed
POPJ P, ;Fatal LATOP. error
SKIPG P1,T1 ;Save number of known servers to be listed
POPJ P, ;None, just return now
MOVEI P2,DNLST ;Address of list of known servers
;Loop listing info for each known server
LATLP: MOVEI T1,5 ;Length
MOVEI T2,.LASAS ;And LATOP. function
DMOVEM T1,NODBLK+.LAACT;Set for LATOP. UUO
MOVEI T1,DNINFL ;Length
MOVEI T2,DNINF ;And address of aux buffer
DMOVEM T1,NODBLK+.LABCT;Set aux buffer for LATOP.
MOVSI T1,(POINT 7,) ;7-bit byte pointer
HRRI T1,1(P2) ;Address of server name string (short block)
MOVEM T1,NODBLK+.LAQUA;Set for LATOP.
MOVEI T1,NODBLK ;LATOP. UUO arg pointer to
LATOP. T1, ;Read info about LAT server
JRST [PUSHJ P,LATOPE ;LATOP. UUO error
JRST LATLP8] ;Advance to next server
PUSHJ P,LATWLD ;See if want to see this name
JRST LATLP8 ;Skip this LAT server
AOS MATCH ;Matched a LAT server
MOVEI T1,DNINF+10 ;Address of server name
PUSHJ P,.TSTRG## ;Type server name
MOVEI T1,[ASCIZ\ (\] ;Separating text
PUSHJ P,.TSTRG## ;Type that out too
MOVEI T1,DNINF+14 ;Address of server "location" string
PUSHJ P,.TSTRG## ;Type that out
MOVEI T1,")" ;Close off text
PUSHJ P,.TCHAR## ;Type it out
LATLP7: PUSHJ P,.TCRLF## ;End this listing line
LATLP8: ADDI P2,7 ;Advance to next "short form" server block
SOJG P1,LATLP ;Loop for all LAT servers
POPJ P, ;Return successfully
;Type out the LAT header info
LATHEA: MOVEI T1,4 ;Length of UUO arg block
MOVEI T2,.LASCH ;LAT function "Show Characteristics"
DMOVEM T1,NODBLK ;Stash for LATOP.
MOVEI T1,2*MAXNOD ;Size of aux area
MOVEI T2,NODBIN ;Address of aux area
DMOVEM T1,NODBLK+.LABCT;Set pointer to returned-data buffer
MOVEI T1,NODBLK ;LATOP. arg pointer to
LATOP. T1, ;Read general LAT host info
JRST [CAIN T1,NODBLK ;UUO unimplemented?
JRST NOLAT ;Yes, tell user no LAT here
JRST LATOPE] ;No, LATOP. UUO error
MOVEI T1,5 ;Length of UUO arg block
MOVEI T2,.LASAS ;LAT function "Show Servers"
DMOVEM T1,NODBLK+.LAACT;Stash for LATOP.
MOVEI T1,2*DNMAX ;Length of aux buffer
MOVEI T2,DNLST ;Address of aux buffer
DMOVEM T1,NODBLK+.LABCT;Set pointer for returned-info
SETZM NODBLK+.LAQUA ;Want short-form blocks
MOVEI T1,NODBLK ;LATOP. arg pointer to
LATOP. T1, ;Read list of known LAT servers
JRST LATOPE ;LATOP. UUO erorr
PUSHJ P,.TCRLF## ;Space down a line for neatness
SKIPN HEADWD ;User want a header?
JRST .POPJ1## ;No, all done here
MOVEI T1,[ASCIZ\[LAT service: local LAT host \]
PUSHJ P,.TSTRG## ;Start up the LAT header
MOVEI T1,NODBIN+24 ;Our LAT host name
PUSHJ P,.TSTRG## ;Type out host name string
MOVEI T1,[ASCIZ\; \] ;Separating text
PUSHJ P,.TSTRG## ;'Twixt name and number
HRRZ T1,NODBIN+00 ;"N-ALLOC-CIRCUITS"
PUSH P,T1 ;Hang onto it for a moment
JUMPE T1,[MOVEI T1,[ASCIZ\No\] ;If "0" then
PUSHJ P,.TSTRG## ;Then type "No known..."
JRST .+2] ;Blunder onwards
PUSHJ P,.TDECW## ;Type number of known servers
MOVE T2,0(P) ;Restore number of known servers
MOVEI T1,[ASCIZ\ known server]\] ;Cap off the LAT header text
CAIE T2,1 ;Singular or plural?
MOVEI T1,[ASCIZ\ known servers]\] ;Cap off the LAT header text
PUSHJ P,.TSTRG## ;With the closing bracket
PUSHJ P,.TCRLF## ;A <CR><LF>
POP P,T1 ;Return number of servers in T1
JRST .POPJ1## ;Now type out the known servers
;Wildcard selection of LAT servers
;
;Note that only the first six characters are checked!
LATWLD: SKIPG SPCCNT ;Did user type any specs?
JRST .POPJ1## ;No, then match everything
HRRZ T1,DNINF+6 ;Length of LAT server name string
MOVSI T2,(POINT 7,) ;Prototype byte pointer
HRRI T2,DNINF+10 ;Address of LAT server name string
PUSHJ P,LATSIX ;Get SIXBIT name in T1
POPJ P, ;Failed?
MOVN T4,SPCCNT ;Count of specs to check
HRLZ T4,T4 ;AOBJN pointer to SPCLST/WLDLST
;Loop checking wildcarded node specs
LATWL2: MOVE T3,SPCLST(T4) ;Next user-typed name
XOR T3,T1 ;Contrast with proposed server name
AND T3,WLDLST(T4) ;(ignoring any junk that should be ignored)
JUMPN T3,LATWL5 ;This spec loses!
JRST .POPJ1## ;No other constraints, this spec wins
LATWL5: AOBJN T4,LATWL2 ;Loop back and check the rest of the specs
POPJ P, ;Reject this LAT server
;Make SIXBIT name out of ASCIZ string
;
;Call with T1/count (future) and T2/pointer
LATSIX: PUSH P,[0] ;The prototype name
MOVSI T3,(POINT 6,0(P)) ;SIXBIT name builder
JRST LATSI4 ;Enter loop
LATSI2: ILDB T4,T2 ;Next name string character
SUBI T4,"0"-'0' ;SIXBITIFY the character
JUMPLE T4,LATSI5 ;Quit on space, null, or control characters
TLNE T3,770000 ;Filled up one word yet?
IDPB T4,T3 ;Nope, accumulate this character
LATSI4: SOJA T1,LATSI2 ;Decrement the count
LATSI5: POP P,T1 ;Position name
JRST .POPJ1## ;Successful return
;LAT errors
NOLAT:: PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,['NWKNLS'] ;The prefix
MOVE T2,["?",,[ASCIZ \No LAT service available
\]]
PUSHJ P,.ERMSG## ;Print the error message
PUSHJ P,.POP4T## ;Restore the temps in case of dump
POPJ P, ;Propagate error return
;LATOP. UUO error
LATOPE: PUSHJ P,.PSH4T## ;Save the "T" acs
PUSH P,T1 ;Save the error code
MOVE T1,['NWKLUE'] ;LAT UUO Error prefix
MOVE T2,["?",,[ASCIZ\LATOP. UUO error (\]]
PUSHJ P,.ERMSG## ;Start up the error message
MOVE T1,0(P) ;The offending error code
PUSHJ P,.TOCTW## ;List the error code in octal
POP P,T2 ;Retrieve the error code
CAIG T2,LATERL ;Is the error code in range?
CAIGE T2,0 ;...?
SETO T2, ;No? make it zero!
MOVE T1,LATERT(T2) ;Get the error string
PUSHJ P,.TSTRG## ;and type it
PUSHJ P,.TCRLF## ;Cap off the error text
PUSHJ P,.POP4T## ;Restore the temps in case of dump
POPJ P, ;Propagate error
DEFINE X(TXT),<[ASCIZ\) TXT\]>
X Unknown LATOP UUO error
LATERT: X Insufficient buffer size
X Invalid parameter value
X LAT is not operational
X Invalid/Unknown LAT server name
X Invalid LAT parameter
X Invalid LAT parameter value
X Invalid/Unknown LAT service name
X Insufficient resources
X LAT host name already set
X Invalid LATOP. function
X Argument list too small
X Address check
X Insufficient privileges
LATERL==.-LATERT
SUBTTL Routines to interface to Scan
;** Routine to finish I/O and exit
;
FINISH: PUSHJ P,FLUSH ;Finish output
JRST .MONRT## ;And exit gracefully
;** Routine to flush output and go into character mode
;Clobbers T1
FLUSH: MOVSI T1,MO.CHR ;Get the output control bit
ANDCAM T1,OUTCON ;And clear it
SETZ T1, ;Send a null character to output the
PJRST OUTC ;current buffer and return
;** Routine to buffer tty output
; Called by SCAN and placed in character mode for prompt
; The character is in T1
OUTC: IDPB T1,BUFFP ;Deposit character in the buffer
SKIPL OUTCON ;If bit 0 is set then line mode
JRST OUTLST ;If char mode output the buffer
SOSGE NCHAR ;Decrement the character count
JRST OUTLST ;Output it to the TTY
POPJ P, ;Return
OUTLST: SETZ T1, ;Zero next character
IDPB T1,BUFFP ;To make the string ASCIZ
OUTSTR BUFFER ;Output the buffer
MOVE T1,[POINT 7,BUFFER] ;Reset the buffer pointer
MOVEM T1,BUFFP ;...
MOVEI T1,BUFSIZ ;Reset the character count
MOVEM T1,NCHAR ;...
POPJ P, ;Return to SCAN
;** Here from Scan to allocate space for Scan blocks as node or file specs
; IALLO increments number of specs on the input side of the "="
; OALLO increments the number of specs on the output side of the "="
;
; Scan will try to BLT the info into the right spot
IALLO: AOSA INFIL ;Add one to the number of input specs
OALLO: AOS OUTFIL ;Add one to the number of output specs
MOVE T1,NUMBLK ;Number of blocks allocated so far
CAILE T1,MAXSPC ;More than we allow?
JRST ALOCE1 ;Tell user we have an allocation error
IMULI T1,BLKSIZ ;Get the amount of core this takes
ADDI T1,BLKSIZ+SBLKS ;And add one more block & address
CAMG T1,.JBREL ;Do we already have enough core?
JRST OALLO1 ;Yes, We already have enough
PUSH P,T1 ;No, Save T1 around CORE UUO
CAILE T1,MAXCOR ;Are we still smaller than max allowed
JRST ALOCER ;No, tell user
ADDI T1,BLKSIZ ;Add block size
ANDI T1,777000 ;Mask to pages
ADDI T1,1000 ;And add one
CORE T1, ;...
JRST ALOCER ;Allocation error, tell user
PUSHJ P,.TCRLF## ;Do a <CR><LF>
MOVEI T1,"[" ;Type a <left bracket>
PUSHJ P,.TCHAR## ;...
MOVE T1,.JBREL ;Get how much we got now
ANDI T1,777000 ;Mask to pages
ADDI T1,2000 ;And add one
PUSHJ P,.TCORW## ;Type how much core we are using
MOVEI T1,[ASCIZ \ core]\] ;Tell him it's core
PUSHJ P,.TSTRG## ;...
POP P,T1 ;Ok, Restore T1
OALLO1: MOVEI T2,BLKSIZ ;a pointer and a block size
SUB T1,T2 ;Backup one block length
AOS NUMBLK ;add one to the count of
;Scan blocks allocated
POPJ P, ;Return to Scan
;** Here to initalize Scan with .ISCAN
; called from the startup code
ISCN: MOVE T2,[ISLEN,,ISBLK] ;.ISCAN argument block if logged in
PUSHJ P,.ISLGI## ;Are we logged in?
MOVE T2,[ISLEN,,ISBLO] ;.ISCAN argument block if logged out
MOVE T1,T2 ;Put the argument into T2
PJRST .ISCAN## ;Call .ISCAN
;** Here to do the Traditional Scanner .TSCAN
; called from the startup code
TSCN: MOVE T1,[TSLEN,,TSBLK] ;.TSCAN arg block for DECnet and ANF10
PUSHJ P,.TSCAN## ;Scan a line of input
MOVE T1,[OSLEN,,OSBLK] ;.OSCAN argument block
PUSHJ P,.OSCAN## ;Check SWITCH.INI[,]
MOVSI T1,MO.CHR ;Get the output control bit
IORM T1,OUTCON ;Set it for buffered mode
SKIPL T1,WIDWD ;Did the user type /WIDTH?
MOVEM T1,CARWID ;Yes, save his value for it
;Select default /ANF, /DECNET, /LAT action
SKIPGE ANF10W ;/ANF switch of some flavor?
SKIPL DECNWD ;or /DECNET switch of some type?
JRST TSCN2 ;Yes, no defaulting needed
SKIPGE LATNWD ;/LAT switch of some flavor?
JRST TSCN5 ;No, default to /ANF/DEC/NOLAT
;Here when user typed at least one of /ANF, /DECNET, or /LAT
TSCN2: SKIPGE ANF10W ;/[NO]ANF explicitly selected?
SETZM ANF10W ;No, deselect ANF
SKIPGE DECNWD ;/[NO]DECNET explicitly selected?
SETZM DECNWD ;No, deselect DECnet
SKIPGE LATNWD ;/[NO]LAT explicitly selected?
TSCN5: SETZM LATNWD ;No, deselect LAT
POPJ P, ;Return
SUBTTL Dissect the Scan blocks
;** Routine to get a node-spec out of a Scan block
;
; If the spec is "wild" do a search of node names for winners
; If not "wild" use the NODE. UUO to figure out who we want
; Then (in either case) insert the proper entries into the
; selection table
; Finally jump to the main loop to tell the user about what we already know
DISECT: SETZB T4,SPCCNT ;Zero both counts
SKIPN T3,NUMBLK ;Any spec's typed?
JRST DISEC3 ;No, just return
MOVN T3,NUMBLK ;Number of Scan Blocks
HRL T3,T3 ;Make an AOBJN pointer
HRRI T3,SBLKS ;Point to the first Scan block
DISEC1: PUSH P,[DISEC2] ;Return address for error routines
MOVE T1,.FXMOD(T3) ;Get the modifier word
TDNN T1,[FX.NDV] ;Did he type a device?
JRST SPECER ;Yes, tell him
TDNN T1,[FX.NUL] ;Did he type an extension?
JRST SPECER ;Yes, tell him
TDNE T1,[FX.DIR] ;Did he type a P,PN?
JRST SPECER ;Yes, tell him
MOVE T2,.FXNAM(T3) ;Is there a name?
MOVEM T2,SPCLST(T4) ;Save the node spec
SETCM T1,.FXNMM(T3) ;And out the mask
MOVEM T1,WLDLST(T4) ;Save the wild card mask
AOS T4 ;Increment the count of node specs
POP P,(P) ;Don't do the error return
DISEC2: ADDI T3,BLKSIZ-1 ;Add size of the block to the pointer
AOBJN T3,DISEC1 ;Loop until all the blocks are checked
MOVEM T4,SPCCNT ;Save the count of spec's
SKIPE SPCLST ;If there are any spec's then
POPJ P, ;Just return
DISEC3: MOVEI T1,1 ;Our default (/BRIEF)
SKIPGE BRIEWD ;Did he specify /BRIEF or /NOBRIEF?
MOVEM T1,BRIEWD ;No, assume /BRIEF on default
POPJ P, ;Return when all blocks are checked
SUBTTL Error message handling routines
;** Here when we run out of Scan block storage.
; tell the user once and continue, ignoring any more specs
ALOCER: SKIPE SBMCNT ;Sure to only tell him once!
JRST ALOCE2 ;Don't count errors unless we print them
MOVE T1,NFECNT ;How many non-fatal errors did we have?
CAILE T1,MAXNFE ;Did we have too many?
JRST NFEERR ;Yes, tell the user and die
AOS NFECNT ;No, count the error
POP P,T1 ;Restore T1
ALOCE1: PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,['NWKSBE'] ;Yes, tell the user
MOVE T2,["%",,[ASCIZ \Scan Blocks used up. Node spec ignored
\]]
PUSHJ P,.ERMSG## ;Yes, print the error
PUSHJ P,.POP4T## ;Restore the temps
ALOCE2: MOVEI T2,1 ;Dummy up a scan block
MOVE T1,NUMBLK ;Number of blocks allocated so far
IMULI T1,BLKSIZ ;Get the amount of core this takes
ADDI T1,BLKSIZ+SBLKS ;And add one more block & address
AOS SBMCNT ;Keep track of how many times here
POPJ P, ;Return
;Copy of the interrupt control block to be BLTed on initalization
INT: XWD 4,CONC ;4 words long,,interrupt handler
XWD 0,2 ;No message control,, 2 ^C
BLOCK 1 ;User PC stored here when interrupted
BLOCK 1 ;Iinterrupt type in LH
IBLKLN==.-INT ;Length of interrupt block
;** Pointers to asciz strings used by the PCONF routine to
; print the device names in the configuration of a node. They must
; be in this order since they are indexed by their NCL device types.
CTAB: POINT 7,[ASCIZ \MCR[\]
POINT 7,[ASCIZ \TTY[\]
POINT 7,[ASCIZ \CDR[\]
POINT 7,[ASCIZ \LPT[\]
POINT 7,[ASCIZ \PTR[\]
POINT 7,[ASCIZ \PTP[\]
POINT 7,[ASCIZ \PLT[\]
POINT 7,[ASCIZ \MTA[\]
POINT 7,[ASCIZ \DTA[\]
POINT 7,[ASCIZ \TSK[\]
POINT 7,[ASCIZ \RDA[\]
POINT 7,[ASCIZ \CDP[\]
POINT 7,[ASCIZ \DDP[\]
SUBTTL Scan macro calls and definitions
;** Switch definitions
DEFINE SWTCHS<
SN *ANF10,ANF10W,FS.NFS ;Control ANF10 portion of program
SN BRIEF,BRIEWD,FS.NFS ;Control listing of devices
SN CDP,CDPWD,FS.NFS ;Only nodes with CDP's
SN CDR,CDRWD,FS.NFS ;Only nodes with CDR's
SN COST,COSTWD,FS.NFS ;List the link cost with /TOPOLOGY
SN DDP,DDPWD,FS.NFS ;Only nodes with DDP's
SN *DECNET,DECNWD,FS.NFS ;Control DECnet portion of program
SN DTA,DTAWD,FS.NFS ;Only nodes with DTA's
SN ERROR,ERRWD,FS.NFS ;Control listing of errors
SN FAST,FASWD,FS.NFS ;For super short list of nodes
SN HEADER,HEADWD,FS.NFS ;Control listing of headers
SN HOSTES,MCRWD,FS.NFS ;Same as "MCR"
SN LAT,LATNWD,FS.NFS ;Control LAT portion of program
SN LINKS,LINKWD,FS.NFS ;Listing of DECnet nodes with links
SN LPT,LPTWD,FS.NFS ;Only nodes with LPT's
SN MCR,MCRWD,FS.NFS ;Only nodes with MCR's (can be a host)
SN MTA,MTAWD,FS.NFS ;Only nodes with MTA's
SN PLT,PLTWD,FS.NFS ;Only nodes with PLT's
SN PTP,PTPWD,FS.NFS ;Only nodes with PTP's
SN PTR,PTRWD,FS.NFS ;Only nodes with PTR's
SN RDA,RDAWD,FS.NFS ;Only nodes with RDA's
SN SILENC,SILWD,FS.NFS ;Control non-error output
SL *SORT,SORTWD,SRT,SRT.DF,FS.NFS ;To sort the node names
SN *TOPOLO,TOPWD,FS.NFS ;For the TOPOLOGY listing
SN TSK,TSKWD,FS.NFS ;Only nodes with TSK's
SN TTY,TTYWD,FS.NFS ;Only nodes with TTY's
SP TYPE,TYPWD,.SIXSW##,-1,FS.LRG!FS.NFS!FS.VRQ ;Node type
SN UNREACH,URCHWD,FS.NFS ;List all known DECnet nodes
SP WIDTH,WIDWD,.DECNW##,-1,FS.NFS!FS.LRG ;Output width
> ;END OF THE SWTCHS MACRO
DOSCAN (TOGLS) ;The DOSCAN macro generates the tables
;defined by the SWTCHS macro
KEYS SRT,<NAME,NONE,NUMBER>
SRT.DF==SRT.L+1
SRT.NA==SRTNAM
SRT.NO==SRTNON
SRT.NU==SRTNUM
SUBTTL Scan argument blocks
;** .ISCAN initalization block if logged out
ISBLO: IOWD 1,ISCANI ;Acceptable CCL commands table
XWD OFFSET,'NWK' ;Starting offset,,Tmp core name
XWD 0,OUTC ;Default I/O
XWD 0,0 ;Indirect file name (unknown)
XWD 0,0 ;Monitor return,, prompt routine
EXP FS.IFI ;Indirect files illegal if logged out
;** .ISCAN initalization block if logged in
ISBLK: IOWD 1,ISCANI ;Acceptable CCL commands table
XWD OFFSET,'NWK' ;Starting offset,,Tmp core name
XWD 0,OUTC ;Default I/O
XWD 0,0 ;Indirect file name (unknown)
XWD 0,0 ;Monitor return,, prompt routine
EXP 0 ;Reserved by Scan for the future
ISLEN==.-ISBLK ;.ISCAN block length
;** Table of CCL names for SCAN
ISCANI: SIXBIT/NETWOR/ ;Default CCL name
;** .OSCAN argument block
; The options file scanner (SWITCH.INI[,])
OSBLK: IOWD TOGLSL,TOGLSN ;SWTCHS' table length,,name table
XWD TOGLSD,TOGLSM ;Table of defaults,,processor address
XWD 0,TOGLSP ;Pointers for storing values
EXP -1 ;Help word, -1 for "HLP:NETWOR.HLP"
SIXBIT /NETWOR/ ;Options word...our name
OSLEN==.-OSBLK ;Length of .OSCAN block
TSBLK: IOWD TOGLSL,TOGLSN ;SWTCHS' table length,,name table
XWD TOGLSD,TOGLSM ;Table of defaults,,processor address
XWD 0,TOGLSP ;Pointers for storing values
EXP -1 ;Use our name for help
XWD 0,0 ;Default to clear answers and file specs
XWD IALLO,OALLO ;Scan block allocation routines
XWD 0,0 ;Default for sticky defaults
XWD 0,1B18!1B19 ;Scan control flags
;1B18=More than 1 input spec OK
;1B19=Global switches can be anywhere
XWD 0,0 ;Let Scan store the values
TSLEN==.-TSBLK ;.TSCAN block length
;Here on a GETTAB error
GTABER: PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,['NWKGUE'] ;The prefix
MOVE T2,["?",,[ASCIZ \GETTAB UUO error at PC \]]
PUSHJ P,.ERMSG## ;Print the error message
HRRZ T1,-4(P) ;Get the PC
SUBI T1,2 ;Backup to the UUO
PUSHJ P,.TOCTW## ;Type the address of the error
PUSHJ P,.POP4T## ;Restore the temps in case of dump
JRST FINISH ;and die
;Here with no network software loaded
NNSERR: PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,['NWKNNS'] ;The prefix
MOVE T2,["?",,[ASCIZ \No networks are available
\]]
PUSHJ P,.ERMSG## ;Print the error message
PUSHJ P,.POP4T## ;Restore the temps in case of dump
JRST FINISH ;and die
NOANF: MOVE T1,['NWKNA1'] ;The prefix
MOVE T2,["?",,[ASCIZ \No ANF10 software installed\]]
PUSHJ P,.ERMSG## ;Print the error message
PUSHJ P,.POP4T## ;Restore in case of dump
JRST FINISH ;and die
OLDMON: MOVE T1,['NWKMTO'] ;The prefix
MOVE T2,["?",,[ASCIZ \Monitor too old. Must be 7.00 or later\]]
PUSHJ P,.ERMSG## ;Print the error message
PUSHJ P,.POP4T## ;Restore in case of dump
JRST FINISH ;and die
;Here on a DNET. UUO error
;DNET. errors:
DNERMS: [ASCIZ \DNUNE% Unknown DNET error\]
[ASCIZ \DNADE% Address error\]
[ASCIZ \DNWNA% Wrong number of arguments\]
[ASCIZ \DNIDN% Illegal job number\]
[ASCIZ \DNFNE% Illegal function number\]
[ASCIZ \DNILF% Illegal flag combination\]
[ASCIZ \DNNSN% No such node name\]
[ASCIZ \DNNSC% No such channel\]
DNERML=.-DNERMS ;Size of error message table
DNETER: PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,['NWKDUE'] ;The prefix
MOVE T2,["?",,[ASCIZ \DNET. UUO error \]]
PUSHJ P,.ERMSG## ;Print the error message
PUSH P,T5 ;Save the error code
CAIG T5,DNERML ;Is the error code in range?
CAIGE T5,0 ;...?
SETZ T5, ;No? make it zero!
MOVE T1,DNERMS(T5) ;Get the error string
PUSHJ P,.TSTRG## ;and type it
POP P,T5 ;Restore the error code
MOVEI T1,[ASCIZ \ at PC \] ;End of string
PUSHJ P,.TSTRG## ;Type it
HRRZ T1,-4(P) ;Get the PC
SUBI T1,2 ;Backup to the UUO
PUSHJ P,.TOCTW## ;Type the address of the error
PUSHJ P,.POP4T## ;Restore the temps in case of dump
JRST FINISH ;and die
;Here on a NODE. UUO error
;Error codes
NODERM: [ASCIZ \NDUKE% Undefined error\]
[ASCIZ \NDIAL% Illegal argument list\]
[ASCIZ \NDINN% Illegal node name/number\]
[ASCIZ \NDPRV% Caller not privileged\]
[ASCIZ \NDNNA% Node not available\]
[ASCIZ \NDNLC% Job not locked in core\]
[ASCIZ \NDTOE% Time out error\]
[ASCIZ \NDRNZ% Reserved word non-zero\]
[ASCIZ \NDNND% I/O channel not open to or not network device\]
[ASCIZ \NDIOE% I/O Error occurred, LH is getsts info\]
[ASCIZ \NDNFC% No free core\]
[ASCIZ \NDIAJ% In use by another job\]
[ASCIZ \NDNMA% No message available\]
[ASCIZ \NDTNA% Terminal not available\]
[ASCIZ \NDNLT% Not a legal terminal\]
[ASCIZ \NDISF% Illegal sub function\]
[ASCIZ \NDRBS% Receive buffer too small\]
[ASCIZ \NDNUG% No ungreeted nodes\]
NODERL=.-NODERM
NODERR: PUSHJ P,.PSH4T## ;Save the temps
MOVE T4,[%FTPER] ;Get the feature test word
GETTAB T4, ;...
PUSHJ P,GTABER ;GETTAB error? tell user and die
TRNN T4,F%NET&777777 ;Do we have network software?
JRST NOANF ;No, tell the user
MOVE T4,[%CNVER] ;Is the monitor 7.00 or later?
GETTAB T4, ;...
PUSHJ P,GTABER ;GETTAB error? tell user and die
LSH T4,-6 ;Right justify monitor version
ANDI T4,777 ;and mask out other stuff
CAIGE T4,700 ;7.00 or later?
JRST OLDMON ;No, tell user and die
PUSH P,T1 ;Save the error code
MOVE T1,['NWKNUE'] ;Yes, the prefix
MOVE T2,["?",,[ASCIZ \NODE UUO error \]]
PUSHJ P,.ERMSG## ;Print the error message
POP P,T1 ;Restore the error code
CAIG T1,NODERL ;Is the error code in range?
CAIGE T1,0 ;...?
SETZ T1, ;No? make it zero!
MOVE T1,NODERM(T1) ;Get the error string
PUSHJ P,.TSTRG## ;and type it
MOVEI T1,[ASCIZ \ at PC \] ;End of string
PUSHJ P,.TSTRG## ;Type it
HRRZ T1,-4(P) ;Get the PC
SUBI T1,2 ;Backup to the UUO
PUSHJ P,.TOCTW## ;Type the address of the error
PUSHJ P,.POP4T## ;Restore the temps in case of dump
JRST FINISH ;and die
;Loop through all the specs looking for error bits
;in the SPCFLG vector
ERRSCN: MOVE T1,NFECNT ;How many non-fatal errors did we have?
CAILE T1,MAXNFE ;Did we have too many?
JRST NFEERR ;Yes, tell the user and die
AOS NFECNT ;No, count the error
MOVE T1,ANF10W ;Get /ANF
IOR T1,DECNWD ;And /DECNET
IOR T1,LATNWD ;And /LAT
JUMPE T1,NONET ;If /NO<everything> then complain
SKIPN L1,SPCCNT ;Any Spec's?
POPJ P, ;No, just return
MOVNS L1 ;Get the count of specs
HRLZS L1 ;Make a AOBJN pointer
SETZ T4, ;Clear our accumulator
ERRSC1: MOVE T1,SPCFLG(L1) ;Get the error mask
TLNN T1,SP.DEC!SP.ANF ;Did we find this node?
JRST [PUSHJ P,NONOD ;No, check it out
AOS T4 ;Count loosers
JRST ERRSC2 ] ;Carry on...
TLNE T1,SP.DEC ;DECnet node?
AOS MATCH ;Yes, count the match
ERRSC2: AOBJN L1,ERRSC1 ;Loop over all specs
SKIPE MATCH ;Any WINNERS?
POPJ P, ;Yes, See if we printed it
SKIPN T4 ;No, Any LOSERS?
PUSHJ P,NOMAT ;Yes, Tell user
POPJ P, ;Done, return to the main loop
;** Here when no node can meet the constraints set by the device
; switches set by the user
; Only prints if no other message has been typed
; uses T1-T4
NOMAT: MOVE T1,['NWKNNM'] ;The prefix
MOVE T2,["%",,[ASCIZ \No Nodes meet constraints
\]]
SETZB T3,T4 ;Zero these for Scan
PJRST .ERMSG## ;Print the error message
;and return
;** Here when the user has both /NOANF and /NODECNET selected
NONET: SKIPN ERRWD ;Do we want to print no-node errors?
POPJ P, ;No, just return
MOVE T1,['NWKNNS'] ;Get the prefix characters
PUSHJ P,ERMSP ;Go to our error message processor
POPJ P, ;Prefix only...
MOVE T1,[POINT 7,[ASCIZ \No network type selected.\]]
PUSHJ P,.TSTRG## ;rest of the message
; MOVEI T1,[ASCIZ\ ANF10\] ;ANF10 string
; SKIPE FTANF ;If we have ANF10
; PUSHJ P,.TSTRG## ;Tell the user
; MOVEI T1,[ASCIZ\ and\] ;If we have both ANF10 and DECnet
; SKIPE FTANF ;...
; SKIPN FTDEC ;...
; CAIA ;Wrong sense
; PUSHJ P,.TSTRG## ;Tell the user
; MOVEI T1,[ASCIZ\ DECnet\] ;DECnet string
; SKIPE FTDEC ;If we have DECnet
; PUSHJ P,.TSTRG## ;Tell the user
; MOVEI T1,"." ;PUNCUATE my mother always told me!
; PUSHJ P,.TCHAR## ;so I did.
PUSHJ P,.TCRLF## ;Finish out line
POPJ P, ;Finish up error scan
;** Here when we have to tell the user about a no-match situation.
NONOD: SKIPN ERRWD ;Do we want to print no-node errors?
POPJ P, ;No, just return
AOS MATCH ;Printed an error, increment match count
MOVE T1,['NWKNNN'] ;Get the prefix characters
PUSHJ P,ERMSP ;Go to our error message processor
POPJ P, ;Prefix only...
MOVE T1,[POINT 7,[ASCIZ \Node \]] ;If here, print the
PUSHJ P,.TSTRG## ;rest of the message
MOVE T1,SPCLST(L1) ;Put the node name into T1 for Scan
PUSHJ P,.TSIXN## ;and print it
MOVE T1,[POINT 7,[ASCIZ \ not in Network
\]]
PJRST .TSTRG## ;and the rest of the message
;** Here to handle too many non-fatal errors
; this is determined by MAXNFE in NDATA
NFEERR: MOVE T1,['NWKTME'] ;Too many non-fatal errors
MOVE T2,["?",,[ASCIZ \Too many errors
\]]
SETZB T3,T4 ;Clear for Scan
PUSHJ P,.ERMSG## ;Tell the user the bad news
JRST FINISH ;and then just die
;** Here to print standard error message prefixes
; Modified version of Scan's .ERMSG routine to allow us to put
; extra things in the line like a node spec or illegal parts of a
; node spec...
;
; T1 = The message prefix
; -1(P) = The address of the extra print routine
; uses T2-4
ERMSP: PUSH P,T1 ;Save the prefix
MOVE T1,NFECNT ;How many non-fatal errors did we have?
CAILE T1,MAXNFE ;Did we have too many?
JRST NFEERR ;Yes, tell the user and die
AOS NFECNT ;No, count the error
SKIPE HPOS ;If in middle of a line
PUSHJ P,CRLFH ;Then position to start of new line
MOVEI T1,"%" ;Get the lead character (never called if fatal)
PUSHJ P,.TCHAR## ;Issue the lead character
PUSHJ P,.VERBO## ;Get /MESSAGE setting
MOVE T4,T1 ;and copy it to a safer place
POP P,T1 ;Get the prefix back
TXNE T4,JWW.PR ;See if /VERBOS:PREFIX
PUSHJ P,.TSIXN## ;Yes, issue the prefix
PUSHJ P,.TSPAC## ;Space to the text area
TXNE T4,JWW.FL ;See if /MESSAGE:FIRST
AOS (P) ;Yes, Skip return to print the rest
POPJ P, ;and return to there
;** Here to tell the user he has entered a bad node spec.
; This happens when we get a PPN, device, or extension in a node spec
; We will tell him and then prompt him with a * as we change into
; run mode by poking our OFFSET word
SPECER: PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,['NWKBNS'] ;The prefix
PUSHJ P,ERMSP ;Process the message
JRST SPECE1 ;and exit if prefix only
MOVEI T1,[ASCIZ \Bad NODE spec \]
PUSHJ P,.TSTRG## ;Type the generic message
MOVE T4,.FXMOD(T3) ;Get the Scan block modifier word
TDNN T4,[FX.NDV] ;Do we have a device?
JRST [MOVE T1,.FXDEV(T3) ;Get the device name
PUSHJ P,.TSIXN## ;Yes, type the device name
MOVEI T1,":" ;Get a ":"
PUSHJ P,.TCHAR## ;we printed a device
JRST .+1 ] ;Continue
MOVE T1,.FXNAM(T3) ;Get the name
PUSHJ P,.TSIXN## ;and print it always
TDNN T4,[FX.NUL] ;Null extension?
JRST [MOVEI T1,"." ;Get a period
PUSHJ P,.TCHAR## ;No, type the period
HLLZ T1,.FXEXT(T3) ;Get the extension
PUSHJ P,.TSIXN## ;No, type it
JRST .+1 ] ;Continue
TDNE T4,[FX.DIR] ;Was a directory typed?
JRST [MOVE T1,.FXDIR(T3) ;Yes, get the PPN
PUSHJ P,.TPPNW## ;and type it
JRST .+1] ;Continue
SPECE1: PUSHJ P,.TCRLF## ;Finish the error message with a <CRLF>
PUSHJ P,.POP4T## ;Restore the temps
MOVSI T1,SP.DEC!SP.ANF ;Get spec found flags
MOVEM T1,SPCFLG(T4) ;Say that we found the nodes
AOS T4 ;Fake out the count
POPJ P, ;and fake a return to WILDS
;** Here when a node has gone offline when we are processing it
OFLINE: SKIPN ERRWD ;Print "No Node" errors
POPJ P, ;No, fake loop
AOS MATCH ;So we don't get the
;"No nodes meet constraints"
MOVE T1,['NWKNWD'] ;No, The prefix
PUSHJ P,ERMSP ;Error message routine
JRST OFLIN3 ;and exit to the main loop
OFLIN2: MOVEI T1,[ASCIZ \Node (\] ;text
PUSHJ P,.TSTRG## ;Type the string
MOVE T1,CN ;Get the node number
PUSHJ P,.TOCTW## ;Type it
MOVEI T1,")" ;Get a <right paren>
PUSHJ P,.TCHAR## ;Type it
MOVEI T1,[ASCIZ \ is going on or offline\] ;Strange state msg
PUSHJ P,.TSTRG## ;Type the rest of the message
OFLIN3: PJRST CRLFH ;fake the end of the main loop
SUBTTL Control/C and other interrupt handling!
;Here on a ^C or other interrupt
CONC: PUSHJ P,.PSH4T## ;Save the temps
HLRZ T1,INTBLK+.ERCCL ;Get the interrupt type
TRNN T1,ER.ICC ;Was it a ^C interrupt?
JRST CONC1 ;No, check the next type
PUSHJ P,.ISLGI## ;Are we logged in?
JRST FINISH ;No, exit!
PUSHJ P,.POP4T## ;Yes, restore the temps and make it
EXIT 1, ;look like a plain ^C
;Here if the user types a CONTINUE command
PUSH P,INTBLK+.EROPC ;Put the return address on the stack
SETZM INTBLK+.EROPC ;and clear it in the interrupt block
POPJ P, ;Finally, return to what we were doing
CONC1: CAIE T1,ER.FUL ;is the disk full
JRST CONC2 ;No, check the next possibility
PUSHJ P,.PSH4T## ;Save the temps
MOVE T1,['NWKNMR']
MOVE T2,["?",,[ASCIZ \No more room on file structure\]]
SETZB T3,T4 ;Clear T3 and T4
PUSHJ P,.ERMSG## ;Print the Message
PUSHJ P,.POP4T## ;Restore the temps
JRST FINISH ;Exit...(Die)
CONC2: CAIE T1,ER.QEX ;Did he exceed his disk quota?
JRST CONC3 ;No, check the next possibility
MOVE T1,['NWKDQE']
MOVE T2,["?",,[ASCIZ \Disk Quota exceeded\]]
SETZB T3,T4 ;clear T3 and T4
PUSHJ P,.ERMSG## ;Print the message
PUSHJ P,.POP4T## ;Restore the temps
JRST FINISH ;Exit...(die)
CONC3: CAIE T1,ER.TLX ;Did he exceed his time limit?
JRST CONC4 ;No, check the last possibility
MOVE T1,['NWKTLE']
MOVE T2,["?",,[ASCIZ \Time Limit exceeded\]]
SETZB T3,T4 ;Clear T3 and T4
PUSHJ P,.ERMSG## ;Print the message
PUSHJ P,.POP4T## ;Restore the temps
EXIT 1, ;Do a continuable exit
;Here if the user types a CONTINUE command
PUSH P,LASTPC ;Put the return address on the stack
SETZM LASTPC ;and clear it in the interrupt block
POPJ P, ;Finally, return to what we were doing
CONC4: CAIE T1,ER.EIJ ;Did he encounter a fatal error
;of the fourth kind?
JRST CONC5 ;No, let the user have it
MOVE T1,['NWKFER']
MOVE T2,["?",,[ASCIZ \Fatal Error at PC \]]
SETZB T3,T4 ;Clear T3 and T4
PUSHJ P,.ERMSG## ;Print the message
HRRZ T1,LASTPC ;Get the last PC
SUBI T1,1 ;Backup to the error PC
PUSHJ P,.TOCTW## ;and type the PC
PUSHJ P,.POP4T## ;restore the temps
JRST FINISH ;Exit to the monitor
CONC5: POP P,T1 ;Restore T1
PUSH P,LASTPC ;Put the last PC on the stack
SETZM LASTPC ;Clear it in the interrupt block
POPJ P, ;Return to the user program
XLIST ;For a neater listing
LIT ;Force literals to be in high segment
LIST ;
END START