!
!THIS PROGRAM IS USED TO BOOT THE NAME TABLE FOR THE RING NAME SERVER
!IT HAS THE SAME INTERFACE AS THE CAMBRIDGE FILE SERVER (ENOUGH TO
!ACCOMPLISH THIS TASK). ALL REQUESTS TO IT TO READ A FILE CAUSE STREAM
!1 TO BE SELECTED AND READ, THIS SHOULD BE THE SOURCE FORM OF THE NAME
!SERVER TABLE I.E. A SERIES OF LINES OF THE FORM:-
!
! name address port type function
!
! name should be enclosed in quotes (' or ") if it contains
! non-alphanumerics or starts with a digit.
!
! type and function are optional, if present type should be
! one of the strings - SSP, BSP, DEV, SLOW-SSP or SLOW-BSP
!
! Comments may be enclosed in [ to ] or | to end-of-line.
!
! Numbers should be decimal or #Xhex-number
!
! The list of names should be terminated with the name END
!
SYSTEMROUTINESPEC ALARM(INTEGER TICKS)
BEGIN
!DATA FOR OUTPUT TO RING SIDE
!****************************
RECORDFORMAT DF(BYTEINTEGERARRAY A(0:200))
RECORDFORMAT MEF(RECORD (MEF) NAME LINK, C
BYTEINTEGER LEN,TYPE, INTEGER ADDRESS, C
PORT, RECORD (DF) DATA)
RECORDFORMAT FSREQUEST(INTEGER SSPCOM,REPLY PORT,C
FSCOMMAND,TAG, INTEGERARRAY UID(1:4), C
INTEGER START1,START2,NUM1,NUM2,READ PORT)
RECORDFORMAT FSREPLY(INTEGER SSPREP,DUMMY,RETURN CODE, C
TAG,NUM1,NUM2)
OWNRECORD (MEF) NAME BUF
RECORDFORMAT PEF(BYTEINTEGER SER,REPLY,FN,PORT, C
RECORD (MEF) NAME MES, BYTEINTEGER X,Y)
RECORDFORMAT PE2(BYTEINTEGER SER,REPLY,FN,PORT, C
INTEGER LPORT,HPORT)
RECORD (PE2) NAME PP
OWNRECORD (PEF) P
CONSTINTEGER BMAX=240
OWNINTEGER BUFLEN,TOTAL,XERROR,ADDRESS,X
CONSTINTEGERNAME INT=K'160060'
CONSTINTEGERNAME OWN ID=K'160030'
CONSTINTEGER RINGSER=10
CONSTINTEGER BUFFERMANAGER=17
CONSTINTEGER REQUESTBUFFER=0
CONSTINTEGER RELEASEBUFFER=1
CONSTINTEGER INPUT DONE=2
CONSTINTEGER DO OUTPUT=X'C1'; !NOTIFY WHEN GONE AND RELEASE BUFFER
CONSTINTEGER SET PORTS=0
CONSTINTEGER OUTPUT ERROR=1
OWNRECORD (FSREQUEST) FSREQ
RECORDFORMAT IBF(INTEGER D1,D2,D3, STRING (64) NAME)
OWNRECORD (IBF) NAME IB
RECORDFORMAT IBA(BYTEINTEGERARRAY A(1:72))
OWNRECORD (IBA) IBLOCK
CONSTINTEGER LINEMAX=80
OWNBYTEINTEGERARRAY LINE(1:LINEMAX)
OWNINTEGER LINEPNT,EOF,NUMBER
CONSTINTEGER MAXPNT=64; !MAX NAME BUFLEN
STRING (MAXPNT) NAME
OWNINTEGER LINENO,NULL COUNT, BYTE COUNT
OWNINTEGER I,CH,N; !OF BYTES OUTPUT
CONSTINTEGER SYNAME=0
CONSTINTEGER SYNUMBER=1
CONSTINTEGER SYEND=2
CONSTINTEGER SYERROR=3
OWNINTEGER IPNT,IMAX
CONSTSTRING (8) ARRAY FLAGNAME(1:5)= "SSP", C
"BSP","DEV","SLOW-SSP","SLOW-BSP"
CONSTINTEGERARRAY FLAGVAL(1:5)=10,9,11,26,25
OWNINTEGER CLOCK=0
CONSTINTEGER ON=1
CONSTINTEGER OFF=0
ROUTINESPEC FREE BUFFER
ROUTINE ERROR(INTEGER N)
SWITCH ERR(1:5)
PRINTSTRING("******* ERROR ")
IF N>5 THEN ->END
->ERR(N)
ERR(1):PRINTSTRING("MISSING NAME"); ->END
ERR(2):PRINTSTRING("MISSING DEVICE NUMBER"); ->END
ERR(3):PRINTSTRING("MISSING PORT NUMBER"); ->END
ERR(4):PRINTSTRING("INVALID FLAGS MNEMONIC"); ->END
ERR(5):PRINTSTRING("EXTRA ON END OF LINE"); ->END
END:
PRINTSTRING(" IN LINE-"); WRITE(LINENO, 3)
NEWLINE
END
ROUTINE READCH(INTEGERNAME CH)
CH=LINE(LINEPNT)
LINEPNT=LINEPNT+1
END
ROUTINE GETSIGCHAR(INTEGERNAME CH)
UNTIL CH#' ' AND CH # ',' AND CH#9 CYCLE
READCH(CH)
REPEAT
END
ROUTINE GETLINE
INTEGER CH
LINEPNT=0
UNTIL CH=NL OR CH=4 CYCLE
READSYMBOL(CH)
IF LINEPNT<LINEMAX-1 AND CH#4 START
LINEPNT=LINEPNT+1
LINE(LINEPNT)=CH
FINISH
REPEAT
IF CH=4 START
LINEPNT=LINEPNT+1
LINE(LINEPNT)=NL
FINISH
IF LINEPNT=1 AND CH=4 THEN EOF=1
LINEPNT=1
LINENO=LINENO+1
END
ROUTINE STORENAME
IB_NAME=NAME
IMAX=LENGTH(NAME)+7
END
INTEGERFN HEX(INTEGER CH)
IF '0'<=CH<='9' THEN RESULT =CH-'0'
IF 'A'<=CH<='F' THEN RESULT =CH-'A'+10
RESULT =-1
END
INTEGERFN GETSYMB
INTEGER CH,QUOTE,PNT
GETSIGCHAR(CH)
IF CH='|' START
UNTIL CH=NL CYCLE
READCH(CH)
REPEAT
FINISH
IF CH=NL THEN RESULT = (SYEND)
IF CH='[' START
WHILE CH#']' CYCLE
READCH(CH)
IF CH=NL THEN RESULT =(SYEND)
REPEAT
FINISH
IF CH='#' START
READCH(CH)
IF CH#'X' THEN RESULT =SYERROR
NUMBER=0; READCH(CH)
WHILE HEX(CH)>=0 CYCLE
NUMBER=NUMBER<<4+HEX(CH)
READCH(CH)
REPEAT
LINEPNT=LINEPNT-1
RESULT =SYNUMBER
FINISH
IF '0'<=CH<='9' START
NUMBER=0
WHILE '0'<=CH<='9' CYCLE
NUMBER=NUMBER*10+CH-'0'
READCH(CH)
REPEAT
LINEPNT=LINEPNT-1
RESULT =(SYNUMBER)
FINISH
QUOTE=' '
IF CH='''' OR CH='"' THEN QUOTE=CH AND READCH(CH)
PNT=0
CYCLE
IF CH=QUOTE THEN EXIT
IF CH=' ' OR CH=',' OR CH=9 OR CH=NL START
LINEPNT=LINEPNT-1
EXIT
FINISH
IF PNT<MAXPNT START
PNT=PNT+1
CHARNO(NAME,PNT)=CH
FINISH
READCH(CH)
REPEAT
LENGTH(NAME)=PNT
RESULT =(SYNAME)
END
ROUTINE GETIBLOCK
INTEGER I,SY,FUNCTION,FLAGS
IPNT=0
LOOP:
GETLINE
FUNCTION=0
FLAGS=8; !FUNCTION NOT SET
IF EOF=1 THEN RETURN
!DECODE LINE
SY=GETSYMB
IF SY=SYEND THEN ->LOOP; !IGNORE EMPTY LINES
IF SY#SYNAME THEN ERROR(1) AND ->LOOP
IF NAME="END" THEN EOF=1 AND RETURN
STORENAME
SY=GETSYMB
IF SY#SYNUMBER THEN ERROR(2) AND ->LOOP
IBLOCK_A(1)=NUMBER
SY=GETSYMB
IF SY#SYNUMBER THEN ERROR(3) AND ->LOOP
IBLOCK_A(3)=NUMBER>>8
IBLOCK_A(4)=NUMBER & 255
SY=GETSYMB
IF SY=SYNAME START
CYCLE I=1,1,5
IF NAME=FLAGNAME(I) THEN FLAGS=FLAGVAL(I)
REPEAT
IF FLAGS=8 THEN ERROR(4) AND ->LOOP
SY=GETSYMB
FINISH
IF SY=SYNUMBER START
FUNCTION=NUMBER
SY=GETSYMB
FLAGS=FLAGS - (FLAGS & 8)
FINISH
IBLOCK_A(5)=FUNCTION>>8
IBLOCK_A(6)=FUNCTION & 255
IF SY#SYEND THEN ERROR(5) AND ->LOOP
IBLOCK_A(2)=FLAGS
END
ROUTINE GETCH
IF IPNT=IMAX START
GETIBLOCK;
FINISH
IF EOF=1 START
CH=0
NULL COUNT=NULL COUNT+1
RETURN
FINISH
BYTE COUNT=BYTE COUNT+1
IPNT=IPNT+1
CH=IBLOCK_A(IPNT)
END
ROUTINE POFFWAIT(INTEGER SERVICE)
CYCLE
P_SER=0; POFF(P)
IF SERVICE=0 OR P_REPLY=SERVICE THEN RETURN
IF P_REPLY=RING SER AND P_FN=INPUT DONE THEN FREE BUFFER ELSEC
START
IF P_REPLY=0 THEN CLOCK=OFF
FINISH
REPEAT
END
ROUTINE REQ BUFFER
P_SER=BUFFER MANAGER; P_REPLY=OWN ID
P_FN=REQUEST BUFFER; P_X=0
PON(P)
END
ROUTINE GETBUFFER
REQ BUFFER
POFFWAIT(BUFFER MANAGER)
END
ROUTINE FREE BUFFER
P_SER=BUFFER MANAGER; P_REPLY=OWN ID
P_FN=RELEASE BUFFER
PON(P)
END
ROUTINE TO RING
P_SER=RING SER; P_REPLY=OWN ID
P_FN=DO OUTPUT
PON(P)
END
ROUTINE SEND BUFFER
P_MES_ADDRESS=ADDRESS
TO RING
CYCLE
POFF WAIT(RING SER)
IF P_FN=INPUT DONE THEN FREE BUFFER AND CONTINUE
EXIT
REPEAT
IF P_FN=OUTPUT ERROR THEN XERROR=1
END
ROUTINE SEND REPLY
RECORD (FSREPLY) NAME REPLY
REPLY==P_MES_DATA
REPLY_SSPREP=X'6500'
REPLY_DUMMY=0
REPLY_RETURN CODE=0
REPLY_TAG=FSREQ_TAG
REPLY_NUM1=0
REPLY_NUM2=TOTAL
P_MES_LEN=5
P_MES_PORT=FSREQ_REPLY PORT
P_MES_ADDRESS=ADDRESS
SEND BUFFER
END
ROUTINE PUTCH(INTEGER CH)
IF XERROR=1 THEN RETURN
IF BUFLEN=BMAX START
P_MES==BUF
P_MES_LEN=(BUFLEN+1)>>1-1
P_MES_PORT=FSREQ_READ PORT
SEND BUFFER
IF XERROR=1 THEN RETURN
GETBUFFER
BUFLEN=0; X=1
BUF==P_MES
FINISH
BUF_DATA_A(BUFLEN+X)=CH
X=-X
BUFLEN=BUFLEN+1
IF X>0 THEN TOTAL=TOTAL+1; !16 BIT WORDS
END
IB==IBLOCK; !SO CAN ACCESS IBLOCK USING FORMAT AS PART STRING
MAP VIRT(BUFFER MANAGER,5, 4)
MAP VIRT(BUFFER MANAGER,6, 5)
CLOCK=OFF
PP==P
P_SER=RING SER; P_REPLY=OWN ID
P_FN=SET PORTS
PP_LPORT=64; PP_HPORT=64
PON(P)
CYCLE
IF CLOCK=OFF THEN ALARM(100) AND CLOCK=ON
POFFWAIT(0)
IF P_REPLY=0 START
IF INT='A' THEN STOP
CLOCK=OFF
CONTINUE
FINISH
IF P_REPLY=RING SER AND P_FN=INPUT DONE START
FSREQ=P_MES_DATA;
ADDRESS=P_MES_ADDRESS
FREEBUFFER
LINENO=0; IPNT=0; IMAX=0
TOTAL=0
IF FSREQ_FSCOMMAND = 7 START
SELECTINPUT(1)
EOF=0; XERROR=0;
GETBUFFER; BUFLEN=0; X=1
BUF==P_MES
CYCLE I=1,1,24; PUTCH(0); REPEAT
NULL COUNT=0
BYTE COUNT=24
UNTIL XERROR=1 OR TOTAL=FSREQ_NUM2 CYCLE
GETCH; PUTCH(CH)
REPEAT
CLOSEINPUT
IF XERROR#1 START
P_MES==BUF
P_MES_LEN=(BUFLEN+1)>>1-1
P_MES_PORT=FSREQ_READ PORT
SEND BUFFER
GETBUFFER
SEND REPLY
FINISH
PRINTSTRING("Name table loaded to"); WRITE(ADDRESS, 3)
IF XERROR#1 THEN PRINTSTRING("** FAILED ")
PRINTSTRING(" size="); WRITE(BYTE COUNT, 3)
PRINTSTRING(" free="); WRITE(NULL COUNT, 3)
NEWLINE
FINISH
FINISH
REPEAT
ENDOFPROGRAM