Google
 

Trailing-Edge - PDP-10 Archives - BB-FP64A-SB_1986 - 10,7/nettst/netlib.mac
There are 5 other files named netlib.mac in the archive. Click here to see a list.
UNIVER	NETUNV - SYMBOLS FOR INTERFACING TO NETWORK UUOS
SUBTTL	RIC WERME, JUNE 1977

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENCS.
;
;COPYRIGHT (C) 1978,1979,1980 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.

;RANDOM DEFINITIONS:
N=11				;COMMON AC FOR NODE INDEX
F.UERR==1B0			;ERROR FLAG RETURNED BY NETLIB UUOS
SCBN==^D30			;NUMBER OF SCBS WE PRESENTLY SUPPORT

OPDEF	PJRST	[JRST]


COMMENT\
THE NETSYM MACRO MUST BE CALLED BY THE MAIN PROGRAM TO DEFINE ALL THE NETWORK
UUOS ONCE. THIS WILL GUARANTEE UNIQUE ASSIGNMENTS FOR ALL OF THEM. OTHER
MODULES THAT WANT TO USE THEM MUST DECLARE THEM EXTERNAL.
\
DEFINE	NETSYM<
UUO(NSYMV)			;NSYMV AC,SYM(N). PUTS SYM VALUE IN AC
UUO(NSVEC)			;NSVEC SYM(N). SETS VECTOR TO ACCESS FOR N
UUO(NVGTW)			;NVGTW LEN,OFFSET(N). GETS WORD DATA FROM ACCESSED VECTOR
UUO(NVGTB)			;NVGTB LEN,OFFSET(N). GETS BYTE DATA
UUO(NCMP)			;NCMP LEN,OLDTAB(N). COMPARES DATA READ IN WITH OLD
INTERN NSYMV,NSVEC,NVGTW,NVGTB,NCMP
>
COMMENT\
CMPBUF AND CMPLOT GENERATE COMPARE BUFFERS FOR THE NCMP UUO. A COMPARE
BUFFER IS THE VECTOR NCMP USES TO COMPARE AGAINST THE DATA IN STCDAT.
CMPBUF GENERATES COMPARE BUFFERS FOR A SINGLE VECTOR FOR ALL -11S IN THE
NETWORK. TO DO THIS, IT FIRST GENERATES AN ACCESS VECTOR THAT POINTS TO EACH
COMPARE BUFFER. THE ACCESS VECTOR IS INDEXED BY THE NODE INDEX AND THE SELECTED
ENTRY HAS T1 IN THE INDEX REGISTER FIELD. ESSENTIALLY THE ACCESS VECTOR
ALLOWS REFERENCING A CELL IN A TWO DIMENSIONAL ARRAY WITH A SINGLE INSTRUCTION.

THE PARAMETERS FOR CMPBUF ARE:

NAM	A THREE LETTER NAME OF THE COMPARE BUFFER. ITS ACTUAL ADDRESS WILL BE
	NAM'OLD.

FLG	A CHARACTER STRING, ONE CHARACTER PER ENTRY IN THE COMPARE BUFFER. THE
	CHARACTER N IN THE STRING WILL CAUSE THE ASSOCIATED WORD IN THE BUFFER
	TO NOT CAUSE NCMP TAKE THE ERROR RETURN IF THE CELL'S VALUE CHANGES.
	ANY OTHER CHARACTER (P IS RECCOMENDED) WILL CAUSE THE DIFFERENCE LOOP
	TO PROCESS THAT CELL.


COMPARE BUFFER ACCESS:

	MOVEI	N,NODE INDEX
	MOVEI	T1,CELL OFFSET
	MOVE	T1,@BUFFER ADDR(N)	;SEE CMPLOT FOR MORE DETAIL
THE CMPLOT MACRO GENERATES SEVERAL CALLS TO CMPBUF AND IS MEANT TO BE USED IN
SITUATIONS WHERE A NODE HAS SEVERAL SIMILAR DATA STRUCTURES TO BE WATCHED SIMULTANEOUSLY.
FOR EXAMPLE, ALL -11'S HAVE MORE THAN ONE SCB AND A COMPARE BUFFER MUST EXIST
FOR EACH SCB IN EACH -11. CMPLOT GENERATES AN ACCESS VECTOR INDEXED BY THE
DATA STRUCTURE NUMBER THAT POINTS TO THE ACCESS VECTORS GENERATED BY CALLS TO
CMPBUF.

CMPLOT PARAMTERS ARE:

NAM	THE NAME OF THE TOP LEVEL ACCESS VECTOR, WHAT THE PROGRAM
	REFERENCES, WILL BE NAM'OLD, JUST LIKE FOR CMPBUF.

FLG	SAME AS FOR CMPBUF

SUB	THIS IS USED TO GENERATE SUB MACRO NAMES FOR INDIVIDUAL CALLS TO
	CMPBUF. IT IS USED IN THE EXPANSION OF SUB'COUNT'OLD, I. E. IF
	SUB IS OC, THE COMPARE BUFFER ACCESS VECTORS WILL BE LABELED OC0OLD,
	OC1OLD, ETC.

NUM	THE NUMBER OF TIMES TO CALL CMPBUF, HENCE THE LENGTH OF THE TOP
	LEVEL ACCESS VECTOR.


IF THE CALL "CMPBUF(BUF,NPP,BU,4)" WAS MADE, A POSSIBLE ACCESS WOULD BE:

	MOVEI	T2,1		;FROM THE SECOND DATA STRUCTURE OF THIS CLASS
	MOVEI	T1,2		;WE WANT THE THIRD ITEM
	MOVEI	N,3		;FROM THE NODE WHOSE NODE INDEX IS 3
	MOVE	T1,@BUFOLD(T2)	;GET THE DATA FROM A THREE DIMENSIONAL ARRAY
THE MOVE INSTRUCTION WILL ACCESS THESE LOCATIONS:
BUFOLD+1/@BU1OLD(N)
BU1OLD 2/COMPARE BUFFER ADDR(T1)
COMPARE BUFFER ADDR+3/DATA!
\
DEFINE	CMPLOT(NAM,FLG,SUB,NUM)<
YY.==-1
NAM'OLD:
    REPEAT NUM,<
	CONC(SUB,\<YY.==YY.+1>,<OLD(N)>)
    >
YY.==-1
    REPEAT NUM,<
	CONC(<CMPBUF(SUB>,\<YY.==YY.+1>,<,FLG)>)
    >
>

DEFINE	CMPBUF(NAM,FLG)<
    XLIST
    XX.==0			;;INIT COUNTER
    IRPC FLG,<XX.==XX.+1>	;;COUNT LENGTH OF BLOCK
    ZZ.==-1
NAM'OLD:
    REPEAT NNOD,<
	NAM'OLD+NNOD+XX.*<ZZ.==ZZ.+1>(T1)>
    REPEAT NNOD,<
	IRPC FLG,<
	    IFE "FLG"-"N",<1B0;>0>
    >
    LIST
>
COMMENT\
THE NODLST MACRO IS LARGELY SO WE CAN CALCULATE THE NUMBER OF NODES CMPBUF
HAS TO BUILD BUFFERS FOR. IT IS MOSTLY A LIST OF CALLS ON A DUMMY MACRO
(X(ID,NAM)) WHERE ID IS THE NODE ID AND NAM IS THE FILENAME OF THE .STB FILE
FOR THAT NODE. NODLST ALSO INITIALIZES THE SYMBOL ZZ. FOR THOSE CALLERS WHO NEED
TO COUNT THE NODE INDEX OR WHATEVER.
\

DEFINE NODLST<
	XLIST
	ZZ.==-1
	X(EJWMN,DN8716)
	X(CYNIC,DN8266)
	X(IT,DC7515)
	X(NEXT,DN8727)
	X(NOVA,DN8731)
	X(ENCORE,DN8732)
	X(CTCH22,DN8222)
	LIST
>

NNOD=0			;CALCULATE THE NUMBER OF NODES WE HAVE
DEFINE X(A,B)<NNOD==NNOD+1>
	NODLST

PRGEND
TITLE	NETLIB - NETWORK UUO SUBROUTINE PACKAGE
SUBTTL	RIC WERME, JUNE 1977


	SEARCH	TULIP,	NETUNV	;TULLIB DEFINITIONS
	SEARCH	JOBDAT, MACTEN, UUOSYM	;STANDARD DEFINITIONS
	SALL			;PRETTY LISTINGS
	.DIRECT	FLBLST		;PRETTIER LISTINGS

VERSION(1,,2,,%NETLIB)
ENTRY	SETNOD,UNSYMV,UNSVEC,UNVGTW,UNVGTB

COMMENT\
NETLIB IS A COLLECTION OF SUBROUTINES, DATA AND UUOS THAT ALLOW PROGRAMS
TO ACCESS RUNNING -11'S SYMBOLICALLY. TO USE NETLIB, THERE ARE SEVERAL THINGS
THAT MUST BE KEPT IN MIND BY THE USER AND ARE DOCUMENTED ON THE NEXT
FEW PAGES.


INTERNAL SYMBOL DEFINITIONS

ALL -11 SYMBOLS TO BE ACCESSED MUST BE DECLARED VIA THE SYM MACRO WITHIN
NETLIB AT LOCATION SYMLST. THE CALLING PROGRAM MAY THEN REFERENCE THEM AS
PARGUMENTS TO NETWORK UUOS (DESCRIBED BELOW) AS ORDINARY EXTERNAL SYMBOLS,
HOWEVER NO MATHEMATICAL OPERATIONS ARE PERMITTED ON THEM.


INTERNAL SUBROUTINES

LODSYF	THESE WILL READ ALL .STB FILES TO ALLOW THE NETWORK UUOS TO MAP THE
LODSYM	-11'S SYMBOL NAME INTO ITS ACTUAL VALUE. LODSYM WILL READ THE .STB
	FILES ONLY IF THEY HAVEN'T BEEN READ BEFORE; LODSYF WILL DO SO ALWAYS
	AND IS USEFUL TO READ IN NEW .STB FILES. IO CHANNEL 17 IS USED.

INTERNAL DATA

NODNAM	THIS IS A VECTOR OF NODE IDS INDEXED BY THE NODE INDEX. IT IS GENERATED
	VIA THE NODLST MACRO AND NOT BY THE NODE. UUO TO ALLOW THE ID'S OF OFFLINE
	NODES TO BE ACCESED.

STCDAT	THE DATA READ BY THE NVGTW AND NVGTB UUOS IS RETURNED HERE.


EXTERNAL DEPENDENCIES:

OFILE	NETLIB OUTPUTS ASCII MESSAGES WHEN NODES CHANGE STATE AND THEREFORE
	EXPECTS THAT THE OUTPUT STREAM TO BE SETUP ACCORDINGLY.

EFILE	NODE. UUO ERRORS THAT NETLIB CAN'T HANDLE ARE LOGGED ON THE ERROR
	STREAM.

MONTIM	THIS IS CALLED BY NETLIB BEFORE IT LOGS THE CHANGE OF STATE OF AN
	-11. A PERFECTLY VALID IMPLEMENTATION IS FOR IT TO SIMPLY RETURN,
	HOWEVER, IT IS DESIGNED TO ALLOW THE USER TIMESTAMP STATE CHANGES.
NETWORK UUOS:

THESE UUOS ARE DESIGNED TO ALLOW SYMBOLIC ACCESS TO THE DATA KEPT BY
THE TOPS-10 NETWORK SOFTWARE RUNNING IN PDP-11S. SYMBOLS TO BE REFERENCED
MUST BE DECLARED VIA THE SYM MACRO AT SYMLST; NODES TO BE REFERENCED
AND .STB FILES PRODUCED BY A BASTARDIZED VERSION OF DDT11 MUST BE
DECLARED VIA THE NODLST MACRO. BEFORE ANY REFERENCES MAY BE MADE,
LODSYM MUST BE CALLED TO SCAN THE .STB FILES FOR THE SYMBOLS WE'RE
INTERESTED IN.

IN GENERAL, SYMBOLS ARE REFERENCED BY SYMBOL NAME (E.G. LBLK0) AND, IN N<RH>, A
"NODE INDEX", THE NODE'S POSITION IN THE NODLST MACRO DEFINITION.
SINCE ONE USUALLY WANTS THE SAME INFORMATION FROM ALL NODES, N
SHOULD BE AN AOBJN POINTER.

ERRORS (GENERALLY SYMBOL NOT DEFINED, NODE NOT RUNNING, ETC.) ARE
INDICATED BY THE SIGN BIT OF AC "F" BEING SET.

UUOS AND THEIR REASON FOR EXISTANCE:

NSYMV	A,SYM	THIS LOADS AC WITH THE VALUE OF SYM. THIS IS A VERY BASIC
		OPERATION AND MAY NOT BE EXTREMELY USEFUL EXCEPT FOR
		LOOKING AT ASSEMBLY PARAMETERS LIKE OURNNM.

NSVEC	SYM	THE MOST COMMON TYPE OF DATA ACCESS WILL PROBABLY BE VECTOR
		ACCESS, E.G. LBLK0+LB.OCN. SINCE IT IS HARD TO INCLUDE
		TWO SYMBOLS IN A SINGLE E FIELD, TWO UUOS ARE REQUIRED, AND
		THIS SETS THE VECTOR FOR THE NODE INCLUDED IN SYM.

NVGTW	LEN,SYM	THESE ACCESS THE VECTOR SETUP BY NSVEC. LEN WORDS OR BYTES WILL
NVGTB	LEN,SYM	RETRIEVED FROM THE NODE REFERENCED BY SYM. THE DATA READ IN WILL
		APPEAR IN STCDAT.

NCMP	LEN,ADR	THIS COMPARES THE DATA IN STCDAT WITH THE DATA IN
		THE OLD AREA POINTED AT BY ADR. IF THE INTERESTING
		LOCATIONS (SEE THE CMPBUF MACRO) DIFFER, THEN THE ERROR
		RETURN WILL BE TAKEN.
\
STB==17				;IO CHANNEL TO READ IN SYMBOL TABLE FILES

;NODE STATES:
%NDINI==0			;INITIAL STATE
%NDONL==1			;ONLINE (NODE UUO GOT DATA BACK)
%NDOFL==2			;OFFLINE (NODE UUO ERROR 2)
%NDHNG==3			;HUNG (NODE UUO ERROR 6)


;ROUTINE TO CALL BEFORE DOING A NUMBER OF NODE UUOS. THIS WILL READ
;ALL THE .STB FILES IF NECESSARY, LOCK THE JOB IN CORE, AND SETUP THE N REGISTER
;TO BE AN AOBJN POINTER TO THE NODE INDEXES

SETNOD::PUSHJ	P,LODSYM	;ENSURE SYMBOLS ARE SETUP
	MOVEI	T1,LK.LLS!LK.LNE!LK.LNP ;LOCK LOSEG
	LOCK	T1,		;CAUSE NODE. UUO NEEDS IT
	  EDISIX [CPOPJ##,,[SIXBIT\? LOCK UUO ERROR %.#!\]
		WOCT	T1]
	MOVSI	N,-NNOD		;RUN THROUGH ALL THE NODES
	POP	P,T1		;NOW CALL THE CALLER
	PUSHJ	P,1(T1)		;GIVING A SUCCESS "RETURN"
	MOVEI	T1,1
	UNLOK.	T1,
	  EDISIX [[SIXBIT\"% UNLOK. UUO &ERROR %.#!\]
		WOCT	T1]
	POPJ	P,		;ALL DONE WITH COMMAND
;NSYMV UUO

UNSYMV::PUSHJ	P,GTSYMV	;GET VALUE
	  JFCL			;UDEFINED, RETURN -1
	MOVEM	U2,(U3)		;RETURN IN USER'S AC
	POPJ	P,


;NSVEC UUO. SEPARATE ACCESS VECTORS ARE KEPT FOR EACH NODE, SO SEVERAL
;MAY BE SELECTED AT ONCE AND THEN PLAYED AROUND WITH AFTERWARDS.

UNSVEC::PUSHJ	P,GTSYMV	;GET START OF VECTOR
	  PJRST	NUUOER		;UNDEFINED, SKIP IT
	MOVEM	U2,VECADR(N)	;SAVE AS CURRENT ACCESS VECTOR
	PJRST	NUUOSC		;RETURN, WE EXPECT A NVGTW UUO NEXT.



;UNVGTB UUO
UNVGTB:	POPJ	P,		;LATER


;NVGTW UUO

UNVGTW::PUSHJ	P,SAVT##	;HAVE TO CALL USER TYPE ROUTINE
	PUSHJ	P,GTSYMV	;GET OFFSET VALUE
	  PJRST	NUUOER
	MOVEI	T1,(U2)		;COPY OFFSET TO WHERE GETNOD EXPECTS
	ADD	T1,VECADR(N)	;MAKE START ADDRESS
	CAIN	U3,0		;MAKE A 0 BE EQUIVALENT
	 MOVEI	U3,1		; TO A 1
	MOVEI	T2,(U3)		;GET NUMBER OF WORDS TO EXAMINE
	LSH	T2,1		;MAKE NUMBER OF BYTES
	PUSHJ	P,GETNOD	;GET IT
	  PJRST	NUUOER
	MOVNI	T1,(U3)		;MAKE AN AOBJN WORD FOR BELOW
	MOVSI	T1,(T1)
	MOVEI	T2,STCDAT-1	;COMPRESS DATA ON TOP OF BYTES
UNVGW1:	MOVE	T3,STCDAT+1(T1)	;GET HIGH BYTE
	LSH	T3,10		;POSITION IT
	IOR	T3,STCDAT(T1)	;MAKE WORD
	PUSH	T2,T3		;PUT BACK IN STCDAT
	ADDI	T1,1		;DIDDLE AOBJN POINTER TO NEXT WORD
	AOBJN	T1,UNVGW1	;DO REST
	PJRST	NUUOSC		;RETURN SUCCESSFULLY
;NCMP UUO

UNCMP::	PUSHJ	P,SAVT##	;NEED TO USE T1
	MOVNI	T1,(U3)		;GET MINUS LENGTH TO CHECK
	MOVSI	T1,(T1)		;MAKE IT AN AOBJN POINTER
	TXZ	F,F.UERR	;ASSUME INNOCENT UNTIL...
UNCMPL:	HRRZ	T2,STCDAT(T1)	;GET DATA WE READ IN
	SKIPGE	T3,@(U1)	;GET OLD DATA, SEE WE ARE INTERESTED IN COMPARE
	 JRST	UNCMPA		;NOT INTERESTED, JUST STORE
	CAIE	T2,(T3)		;HAVE THEY CHANGED?
	 TXO	F,F.UERR	;YES, FLAG THAT
UNCMPA:	HRRM	T2,@(U1)	;SAVE NEW VALUE
;	SUB	T2,T3		;COMPUTE CHANGE IN DATA
;	HRRZM	T2,STCDAT(T1)	;SAVE DIFFERENCE
	AOBJN	T1,UNCMPL	;DO REST OF DATA
	POPJ	P,


;ROUTINE TO RETURN NODE SPECIFIC VALUE FOR A SYMBOL.
;CALL	U1/ SYMBOL INDEX (VALUE OF SYMBOL NAME)
;RETURN U2/ 36 BIT VALUE IF DEFINED, -1 IF NOT
;	SKIP RETURN IF DEFINED, NONSKIP IF NOT.

GTSYMV:	SKIPL	U2,@SYMIND(N)	;GET VALUE (THIS REFERENCES AC U1!!!)
	 AOS	(P)		;DEFINED, GIVE SKIP RETURN
	POPJ	P,
SUBTTL	SUBROUTINES

;ROUTINE TO READ ALL .STB FILES AND INCORPORATE EVERYTHING INTO SYMVAL
;THIS RUNS ONLY ONCE - ONCE THE SYMBOLS ARE SETUP, THIS ROUTINE IS
;A NOP UNTIL SYMSET IS SET TO -1 AGAIN.

LODSYF::SETOM	SYMSET		;FORCE REREAD
LODSYM::AOSE	SYMSET		;HAVE WE BEEN HERE BEFORE?
	 POPJ	P,		;YES, NOP
	PUSHJ	P,SAVE2##	;NEED A PERMANENT AC
	PUSH	P,.JBFF##	;SO WE CAN RELEASE BUFFER SPACE LATER
	SETOM	SYMVAL		;MARK ALL SYMBOLS UNDEFINED
	MOVE	T1,[SYMVAL,,SYMVAL+1]
	BLT	T1,SYMVAL+NNOD*NSYM-1
	MOVSI	P1,-NNOD	;SCAN ALL NODES
	MOVE	P2,[SYMVAL(T2)]	;TO STORE SYMBOL VALUES
LODSYL:	FSETUP	@NODFIH(P1)	;SETUP STBFIL
	FIOPEN	STBFIL		;OPEN ONE OF THE .STB FILES
LODSY1:	RCH	T1		;READ SIXBIT NAME
	RCH	T3		;READ VALUE
	MOVSI	T2,-NSYM	;SETUP TO SEE IF WE ARE INTERESTED IN THIS ONE
	CAME	T1,SYMLST(T2)	;MATCH?
	 AOBJN	T2,.-1		;NO, TRY NEXT
	JUMPGE	T2,LODSY1	;JUMP IF NO MATCH
	MOVEM	T3,@P2		;SAVE SYMBOL VALUE
	JRST	LODSY1		;LOOK FOR ANOTHER

;HERE ON EOF OR LOOKUP ERROR - STEP TO NEXT FILE
LODLKE:	ERRLK	STBFIL		;TELL USER WHAT HAPPENED
LODSYA:	FREL	STBFIL		;RELEASE OLD FILE
	ADDI	P2,NSYM		;POINT TO NEXT SYMBOL BLOCK
	MOVE	T1,(P)		;RELEASE BUFFER AREA
	MOVEM	T1,.JBFF##
	AOBJN	P1,LODSYL	;DO NEXT .STB FILE
	POP	P,T1		;DISCARD .JBFF VALUE

	MOVSI	N,-NNOD		;SET UP CONVENIENCE TABLE OF NODE #'S
	MOVEI	U1,OURNNM	;TO REFERENCE IN SYMIND DATA STRUCTURE
LODSY2:	MOVE	T1,@SYMIND(N)	;MACRO DISLIKES ME USING NSYMV HERE
	MOVEM	T1,NODNNM(N)	;REMEMBER FOR GETNOD
	AOBJN	N,LODSY2	;DO REST
	POPJ	P,
;HERE TO EXAMINE MEMORY FROM ANOTHER NETWORK NODE
GETNOD:	PUSHJ	P,SETUPN	;BEGIN BUILDING MSG<LINE><CODE><ADR>
	EXP	1		;CODE FOR EXAMINE REQUESTS IS 1
	MOVEM	T1,T3		;SAVE ADDRESS
	ADDI	T1,(T2)		;MAKE LIMIT ADDRESS
	PUSHJ	P,PUTADR	;PUT LIMIT ADDRESS INTO THE MESSAGE
	PUSHJ	P,NODSET	;DO NODE UUO
	  POPJ	P,		;PASS ERROR UP LINE
	CAIE	T1,12		;CODE FOR EXAMINE DATA IS 12
	  JRST	STCERR
	PUSH	P,T3		;SAVE ADDRESS WE WENT FOR
	HLRZ	T3,NODARG+3	;GET BYTE COUNT FROM MSG
	SUBI	T3,5		;SUBTRACT BYTES WE ALREADY READ
	MOVEI	T2,STCDAT-1	;WHERE TO PUT DATA
	IBP	T4		;SKIP ADDRESS FIELD
	IBP	T4
	IBP	T4
GTNOD3:	ILDB	T1,T4		;GET NEXT BYTE OF DATA
	PUSH	T2,T1		;SAVE THIS BYTE
	SOJG	T3,GTNOD3
GTNOD4:	POP	P,T1		;GET ADDRESS WE WENT FOR
	PJRST	CPOPJ1

;HERE TO BEGIN A NODE UUO MSG <LINE><CODE><ADDRESS>
; CALL	MOVE	T1,<ADR>
;	PUSHJ	P,SETUPN
;	EXP	<CODE>
SETUPN:	PUSH	P,T1		;SAVE ADDRESS
	MOVE	T4,[POINT 8,STCMSG]	;POINTER TO STATION CONTROL MSG
	MOVEI	T1,0		;0 = SELF, 1-N IS LINE NUMBER
	IDPB	T1,T4		;MSG IS FOR NODE
	MOVE	T1,@-1(P)	;GET CODE
	IDPB	T1,T4
	POP	P,T1		;GET ADDRESS BACK
	PUSHJ	P,PUTADR	;PUT ADDRESS INTO THE MESSAGE
	AOS	(P)		;SKIP ARGUMENT
	POPJ	P,
;HERE TO DO A NODE UUO
; CALL	MOVEI	T1,<COUNT>	;OF BYTES IN MSG TO SEND
;	RETURNS WITH T4 POINTING TO INPUT MSG AND CODE IN T1
NODSET:	PUSH	P,[POINT 8,STCMSG]
	MOVEI	T1,1		;INITIALIZE LENGTH COUNTER
	IBP	(P)		;ADVANCE DUMMY POINTER
	CAME	T4,(P)
	  AOJA	T1,.-2
	HRLI	T1,STCMSG
	MOVSM	T1,NODARG+2
	POP	P,T1		;CLEAN OFF STACK
	MOVE	T1,[12,,4]	;NUMBER OF WORDS IN ARGUMENT
	MOVEM	T1,NODARG
	MOVE	T1,NODNNM(N)	;NODE NUMBER
	MOVEM	T1,NODARG+1
	MOVE	T1,[100,,STCIMS]	;INPUT MSG SLOT
	MOVEM	T1,NODARG+3
	MOVE	T1,[3,,NODARG]	;FUNCTION IS SEND STC MSG
	NODE.	T1,
	  JRST	NODERR
	HLRZ	T1,NODARG+3	;CHECK FOR MONITOR GLITCH -
	CAIN	T1,100		;SOMETIMES THIS ISN'T UPDATED
	 DISIX	[[SIXBIT\%[F&UNNY BYTE COUNT RETURNED FROM NODE %]#!\]
		PUSHJ	P,MONTIM##
		WNAME	NODNAM(N)]
	MOVEI	T1,%NDONL	;MARK NODE ONLINE IF IT ISN'T ALREADY
	EXCH	T1,NODSTT(N)	;SAVE, GET OLD
	JRST	.+1(T1)		;DISPATCH TO DECIDE WHETHER TO LOG EVENT
	 JRST	NODSE2		;FROM INITIAL SAY NOTHING
	 JRST	NODSE2		;ONLINE
	 JRST	NODSE1		;OFFLINE
NODSE1:	 DISIX	[[SIXBIT\%[N&ODE % ONLINE.]#!\]
		PUSHJ	P,MONTIM##
		WNAME	NODNAM(N)]
NODSE2:	MOVE	T4,[POINT 8,STCIMS]	;POINTER TO INPUT MESSAGE
	ILDB	T1,T4		;GET FIRST BYTE (= LINE# OR SELF)
	JUMPN	T1,NODERR
	ILDB	T1,T4		;GET MESSAGE SUBTYPE
	PJRST	CPOPJ1##

STCERR:	OUTSTR	[ASCIZ	\STC error - msg =\]
	HLRZ	T4,NODARG+3
	SKIPA	T3,[POINT 8,STCIMS]
STCER3:	WCHI	","
	ILDB	T1,T3
	WOCT	T1
	SOJG	T4,STCER3
	POPJ	P,
NODERR:	MOVEI	T2,7		;FIRST OUT OF RANGE ERROR CODE
	CAIL	T2,(T1)		;EXPECT THIS TO NOT SKIP
	 MOVEI	T2,(T1)		;REASONABLE ERROR, USE IT FOR DISPATCH
	JRST	@.+1(T2)
	 NODEPT			;CODE 0 - SHOULDN'T HAPPEN
	 NODEPT
	 NODOFF			;CODE 2 - OFFLINE
	 NODEPT
	 NODEPT
	 NODEPT
	 NODHNG			;CODE 6 - TIMEOUT
	 NODEPT			;OUT OF RANGE

NODEPT:	EDISIX	[CPOPJ##,,[SIXBIT\? % NODE UUO &ERROR %, %#!\]
		WNAME	NODNAM(N)
		WOCT	T1
		WSIX	@NODETB(T2)]

NODETB:	[SIXBIT\&ERROR CODE 0!\]
	[SIXBIT\&ILLEGAL ARGUMENT LIST!\]
	[SIXBIT\&NODE OFFLINE!\]
	[SIXBIT\&NOT PRIVILEGED!\]
	[SIXBIT\&STATION CONTROL NOT AVAILABLE!\]
	[SIXBIT\&NOT LOCKED IN CORE!\]
	[SIXBIT\&TIMEOUT!\]
	[SIXBIT\&UNKNOWN ERROR!\]

NODOFF:	MOVEI	T1,%NDOFL	;MARK NODE AS OFFLINE
	EXCH	T1,NODSTT(N)	;AND GET OLD STATE
	CAMN	T1,NODSTT(N)	;ANNOUNCE IT IF STATE CHANGED
	 POPJ	P,		;NOTHING HAPPENED
	PUSHJ	P,MONTIM##	;TIMESTAMP IT
	DISIX	[CPOPJ##,,[SIXBIT\[N&ODE % OFFLINE]#!\]
		WNAME	NODNAM(N)]

NODHNG:	MOVEI	T1,%NDHNG	;LIKE NODOFF
	EXCH	T1,NODSTT(N)
	CAMN	T1,NODSTT(N)
	 POPJ	P,
	PUSHJ	P,MONTIM##
	DISIX	[CPOPJ##,,[SIXBIT\[N&ODE % HUNG]#!\]
		WNAME	NODNAM(N)]
PUTADR:	PUSH	P,T1
	IDPB	T1,T4		;PUT LOW ORDER BYTE OF ADR INTO MSG
	ROT	T1,-^D8
	IDPB	T1,T4
	ROT	T1,-^D8
	IDPB	T1,T4
TPOPJ:	POP	P,T1
	POPJ	P,


;HERE TO RETURN SUCCESS/ERROR CONDITIONS TO UUO CALLERS

NUUOER:	TXOA	F,F.UERR	;LIGHT ERROR BIT
NUUOSC:	TXZ	F,F.UERR	;CLEAR ERROR BIT TO SAY SUCCESS
	POPJ	P,
;NODE NAME AND .STB FILE DATA BASE:

DEFINE	X(A,B)<<SIXBIT\A\>>

NODNAM::NODLST			;TABLE OF SIXBIT NAMES

DEFINE X(A,B)<
CONC(NOD,\<ZZ.==ZZ.+1>,:)
	FILE	STB,I,STBFIL,<NAME(B),EXT(STB),STATUS(.IOBIN),LOOKUP(LODLKE),EOF(LODSYA)>
	>

	NODLST			;BUILD FILE BLOCKS

DEFINE X(A,B)<CONC(NOD,\<ZZ.==ZZ.+1>)>
NODFIH:	NODLST			;TABLE OF ADDRESSES OF HISEG FILE BLOCKS
;SYMBOL TABLE DATA:

DEFINE	SYM(NAM)<
    XLIST
    IRP NAM<
	NAM==<ZZ.==ZZ.+1>
	<SIXBIT\NAM\>
	INTERN	NAM
    >
    LIST
>


	ZZ.==-1		;PRIME SYM MACRO
;TABLE OF SIXBIT SYMBOL NAMES WE ARE INTERESTED IN ACCESSING:
SYMLST:	SYM<LBLK0,LBLK1,LBLK2,LBLK3>
	SYM<LB.STS,LB.OCN,LB.ROK,LB.SLE>
	SYM<OURSCB,TENSCB,SCB0,SCB1,SCB2,SCB3,SCB4,SCB5,SCB6,SCB7>
	SYM<SCB10,SCB11,SCB12,SCB13,SCB14,SCB15,SCB16,SCB17>
	SYM<SCB20,SCB21,SCB22,SCB23,SCB24,SCB25,SCB26,SCB27>
	SYM<SCB30,SCB31,SCB32,SCB33,SCB34,SCB35,SCB36,SCB37>
	SYM<SB.FLG,SB.HXN,SB.IMQ,SB.OMQ,SB.NNM>
	SYM<OURNNM>
NSYM==.-SYMLST

SYMIND:	ZZ.==-1			;POINTERS TO EACH NODE'S SYMBOLS
REPEAT NNOD,<
	SYMVAL+NSYM*<ZZ.==ZZ.+1>(U1) ;SEE UNSYMV
>
SNDMSG:	BLOCK	<SNDLEN==^D100>/5

NODBL2:	2			;ALWAYS NUMBER OF ARGS
	0			;NODE NAME STORED HERE

NODBL5:	4			;LENGTH
	0			;NODE NAME ALSO STORED HERE
	0			;RESERVED FOR FUTURE
	3			;DEVICE WE'RE INTERESTED IN

SYMSET:	-1			;SEMAPHORE TO FILL SYMBOL DATA ONLY ONCE
SYMVAL:	BLOCK	NNOD*NSYM	;SYMBOL VALUES LIVE HERE
NODNNM:	BLOCK	NNOD		;SETUP BY LODSYM (HACK)

NODSTT:	BLOCK	NNOD		;STATE OF EACH NODE (SEE NODSET)
VECADR:	BLOCK	NNOD		;ACCESS VECTOR DATA
STCDAT::BLOCK	20
NODARG:	BLOCK	5
STCMSG:	BLOCK	20
STCIMS:	BLOCK	110
STBFIL:	BLOCK	FBSIZE		;LOSEG FILE BLOCK FOR STB FILE

PRGEND
TITLE	FILSPC - SIMPLE FILENAME PARSER

	SEARCH	TULIP,	NETUNV	;TULLIB DEFINITIONS
	SEARCH	JOBDAT, MACTEN, UUOSYM	;STANDARD DEFINITIONS
	SALL			;PRETTY LISTINGS
	.DIRECT	FLBLST		;PRETTIER LISTINGS

TWOSEG
RELOC	400000
VERSION(1,A,1,,%FILSPC)

XP(FB,11)			;REGISTER THAT CONTAINS ADDRESS OF FILEBLOCK TO FILL
ENTRY	SIXLXC,SIXLXR,FILLXC,FILLXR

SIXLXC::LCH	T1		;BACKUP TO COMPENSATE FOR LEXINT
	JRST	SIXLXR

FILLXC::LCH	FB
FILLXR::SKIPA	FB,T1		;GET FILE BLOCK ADDRESS
SIXLXR::SKIPA	T1,[SIXSCN,,FILSPC]
	MOVEI	T1,FILSPC
	PJRST	LEXINT##

;PRODUCTIONS TO PARSE THE CLASSIC FILE SPECIFIER (NODE_DEV:FILE.EXT[P,PN]
;IN ITS BIGGEST FORM)
;CALL WITH REGISTER FB POINTING TO THE LOSEG FILE BLOCK TO FILL.
	TBLBEG(FILSPC)

	PROD(	<SG>		,FILI, ,      )	;INIT FILE PARSER FLAGS
NXTATM:	PROD(	<SG>		,CALL, ,SIXSCN)	;GET A NAME
	PROD(	"_"		,NODE,*,NXTATM)	;UNDERSCORE MEANS A NODE
	PROD(	":"		,DEV ,*,NXTATM)	;COLON MEANS A DEVICE
	PROD(	"."		,NAME,*,NXTATM)	;AND PERIOD MEANS NAME
	PROD(	"["		,NAMX,*,PPNSCN)	;THEN BRACKET MEANS NAME OR EXT
	PROD(	<SG>		,NAMX, ,      )	;ANYTHING ELSE IS SAME
PPNDON:	PROD(	<SG>		,SRET, ,      )	;QUIT WHILE AHEAD

PPNSCN:	PROD(	<SG>		,GPRJ, ,      )	;GET PROJECT NUMBER
	PROD(	<SG>		,PROJ,*,      )	;SAVE PROJECT. PROJ WILL FAKE CALL
	PROD(	"]"		,    ,*,      )	;OPTIONAL CLOSE BRACKET
	PROD(	<SG>		,PROG, ,PPNDON)	;MERGE WITH PROJECT

SIXSCN:	PROD(	<BLANK>		,    ,*,.     )	;SKIP BLANKS
	PROD(	<SG>		,SIXI, ,      )	;SETUP SIXBIT PACKER
	PROD(	<LETTER!DIGIT>	,SIXS,*,.     )	;SAVE ANY ALPHANUMERICS
SKPBLA:	PROD(	<BLANK>		,    ,*,.     )	;IGNORE BLANKS
	PROD(	<SG>		,RET , ,      )	;AND RETURN

	TBLEND
SUBTTL	FILE SPECIFIER ROUTINES

A.NODE:	MOVE	T2,T1		;MONITOR CAN'T GET TO NODE IN T1
	MOVEI	T1,2		;NUMBER OF ARGS.
	MOVE	T4,[2,,T1]	;POINTER FOR NODE. UUO
	NODE.	T4,		;CONVERT NAME TO BINARY
	  EDISIX [A.RET##,,[SIXBIT\? N&O NODE NAMED %#!\]
		WNAME	T2]
	HRLI	T3,(T4)		;SAVE NODE # FROM FUTURE DESTRUCTION
	POPJ	P,

A.DEV:	TLNN	T3,-1		;DID WE SEE A NODE NAME?
	 JRST	ADEV		;NOPE, JUST SAVE WHAT WE HAVE
	HLRZ	T2,T1		;CAN WE JUST CONVERT THE DEVICE NAME?
	CAIN	T2,'TTY'	;CHECK FOR TTYS 'CAUSE THEY'RE TRICKY
	 JRST	ATTY		;SIGH. FREEN IT
	LSH	T1,-^D12	;POSITION UNIT NUMBER AS LAST CHAR.
	ANDI	T1,77		;AND DISCARD EVERYTHING ELSE
	LSHC	T3,-^D<18+3>	;ISOLATE FIRST CHARACTER OF NODE NUMBER
	LSH	T3,3		;ADD SPACING FOR SIXBIT
	LSHC	T3,^D9		;BRING BACK SECOND CHAR AND POSITION
	IORI	T1,'00 '(T3)	;MAKE NETWORK UNIT NUMBER
	HRLI	T1,(T2)		;PUT DEVICE TYPE BACK IN
	MOVEI	T3,0		;WE STILL HAVEN'T SEEN A FILENAME
	JRST	ADEV		;SAVE THE NAME WE MADE UP

ATTY:	HRLZ	T2,T1		;GET JUST LINE NUMBER
	JUMPE	T2,[EDISIX [A.RET##,,[SIXBIT\? I&LLEGAL &TTY& NAME#!\]]]
ATTY1:	LSH	T2,3		;DISCARD SIXBIT PART
	LSHC	T1,3		;MOVE AN OCTIT TO T1
	JUMPN	T2,ATTY1	;DO REST OF OCTITS
	ANDI	T1,777		;DISCARD GARBAGE
	HLL	T1,T3		;MAKE NODE,,LINE
	GTXTN.	T1,		;MAKE INTO TTY NAME
	  JRST	[EDISIX [A.RET##,,[SIXBIT\? TTY& NOT CONNECTED TO THIS SYSTEM#!\]]]
ADEV:	MOVEM	T1,FILDEV(FB)	;SAVE DEVICE NAME
	POPJ	P,
A.NAME:				;GOT NAME, PRSDFL WILL BE OFF AND MUST BE SET
A.NAMX:	TROE	T3,-1		;SET FILE SEEN FLAG AND CHECK TO SEE IF IT WAS
	JRST	A.EXT		;YES, MUST BE EXTENSION
	JUMPE	T1,CPOPJ##	;DON'T OVERWRITE DEFAULT
	MOVEM	T1,FILNAM(FB)	;SAVE FILE NAME
	POPJ	P,

A.EXT:	MOVEM	T1,FILEXT(FB)	;SAVE EXTENSION
	POPJ	P,

A.GPRJ==OCTLXC##
A.PROJ:	HRLZM	T1,FILPPN(FB)	;SAVE PROJECT (LEFT HALF)
	PJRST	OCTLXR##	;AND CALL OCTLXR AGAIN FOR THE SECOND HALF

A.FILI:	TDZA	T3,T3		;LH: NODE #, RH: FILE SEEN FLAG
A.PROG:	HRRM	T1,FILPPN(FB)	;AND REMEMBER IT
	POPJ	P,		;BEFORE RETURNING


;ROUTINE TO HANDLE DATA FLOW WHILE PARSING A SIXBIT WORD. RETURNS:
;	T1/	SIXBIT DATA
;	T2/	BYTE POINTER POINTING TO LAST BYTE
A.SIXS:	TRNE	P3,LGLSIX	;THIS IS CUTE. WE MAY HAVE ONE OF 3 TYPES OF CHARS:
				;NUM, RANGE 60-71 (SIXBIT 20-31)
				;UC, RANGE 101-132 (41-72)
				;LC, RANGE 141-172 (41-72)
				;SO, IF IT IS LEGAL SIXBIT, WE HAVE TO COMPLEMENT
				;BIT 40:
	XORI	P2,40		;LIKE THAT, WHILE LEAVING LOWER CASE ALONE
	TLNE	T2,770000	;MORE CUTENESS. THIS FIELD IS 0 AFTER T1 IS FILLED
	IDPB	P2,T2		;STUFF INTO T1
	POPJ	P,		;AND BACK FOR MORE

A.SIXI:	MOVE	T2,[POINT 6,T1]	;SETUP POINTER TO WHERE WE'LL ACCUMULATE THE NAME
	SETZ	T1,		;AND CLEAR THAT OF ANY GARBAGE IT MIGHT HAVE
	POPJ	P,		;BACK TO SCAN FIRST CHARACTER

END