Trailing-Edge
-
PDP-10 Archives
-
BB-4157D-BM
-
sources/blio.bli
There are 12 other files named blio.bli in the archive. Click here to see a list.
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
! OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!COPYRIGHT (C) 1976,1977 BY DIGITAL EQUIPMENT CORPORATION
MODULE BLIO=
BEGIN
%(
THE CHANNEL TABLE
)%
MACRO TABMAX=16$, TABSIZ=15$; % MAX CHANNELS AND SIZE %
STRUCTURE CHTB[I,J]=[(I+1)*(J+1)]((.CHTB+.I*(J+1)+.J)<0,36>);
GLOBAL CHTB CHNLTAB[TABMAX,TABSIZ];
GLOBAL CHNLMAX;
EXTERNAL IOZERROR;
%(
C H A N N E L T A B L E M A C R O S
)%
%(
STATUS WORD BITS
)%
MACRO
FMODE=CHAN[0]$,
FDEV=CHAN[1]$,
FBUF=CHAN[2]$,
FBUFO=CHAN[2]<18,18>$,
FBUFI=CHAN[2]<0,18>$,
FOBUFH=CHAN[3]$,
FOPTR=CHAN[4]$,
FOCNT=CHAN[5]$,
FIBUFH=CHAN[6]$,
FIPTR=CHAN[7]$,
FICNT=CHAN[8]$,
FFILE=CHAN[9]$,
FEXT=CHAN[10]$,
FERR=CHAN[10]<0,12>$,
FBLK=CHAN[10]<0,18>$, % DEVICE BLK NO DSK=0 %
FPROT=CHAN[11]<27,9>$,
FDMODE=CHAN[11]<23,4>$,
FTIME=CHAN[11]<13,10>$,
FDATE=CHAN[11]<0,12>$,
FPPN=CHAN[12]$,
FPRJ=CHAN[12]<18,18>$,
FPRG=CHAN[12]<0,18>$,
FSIZ=CHAN[12]<18,18>$,
FSTATUS=CHAN[13]$,
FSWITCH=CHAN[14]$,
FNEWPR=CHAN[15]<0,10>$,
FUSER=0,18$, % ENTIRE USER FIELD %
FYEND=0,1$, % ENDFILE ALLOWED %
FYREW=1,1$, % REWIND ALLOWED %
FYREAD=2,1$, % READING ALLOWED %
FYWRITE=3,1$, % WRITING ALLOWED %
FYUPDAT=4,1$, % UPDATING ALLOWED %
FYDUMMY=5,1$, % DUMMY CHANNEL %
FYSIMUL=6,1$, % SIMULTANEOUS READ/WRITE ALLOWED %
FPRIMARY=7,1$, % PRIMARY DEFAULT VALUE %
% SYSTEM BITS OF STATUS WORD %
FSYS=18,18$, % ENTIRE SYSTEM FIELD %
FROPEN=18,1$, % FILE OPEN FOR INPUT %
FWOPEN=19,1$, % FILE OPEN FOR OUTPUT %
FEOF=20,1$, % ENDFILE ENCOUNTERED %
FIS35=21,1$, % BIT 35 IS SET %
FSET35=22,1$, % SET BIT 35 ON NEXT WRITE %
FSEQ=24,1$, % PROCESSING SEQUENCE NO. %
FPGMK=25,1$, % PROCESSING PAGE MARK %
FFISTAR=26,1$, % FILE NAME IS "*" %
FXSTAR=27,1$, % EXTENSION NAME IS "*" %
FUOPEN=28,1$, % FILE OPEN FOR UPDATE %
FDEVAS=29,1$, % DEVICE IS ASSIGNED THIS CHANNEL %
FIOERR=30,1$, % ERROR DETECTED %
FNSET=35,1$; % CHANNEL NOT SET %
MACRO
XFYEND=1^0$, % ENDFILE ALLOWED %
XFYREW=1^1$, % REWIND ALLOWED %
XFYREAD=1^2$, % READING ALLOWED %
XFYWRITE=1^3$, % WRITING ALLOWED %
XFYUPDAT=1^4$, % UPDATE ALLOWED %
XFYDUMMY=1^5$, % DUMMY CHANNEL %
XFYSIMUL=1^6$, % SIMULTANEOUS READ/WRITE ALLOWED %
XFPRIMARY=1^7$, % PRIMARY DEFAULT VALUE %
XFROPEN=1^18$, % FILE OPEN FOR INPUT %
XFWOPEN=1^19$, % FILE OPEN FOR OUTPUT %
XFEOF=1^20$, % ENDFILE ENCOUNTERED %
XFIS35=1^21$, % BIT 35 IS SET %
XFSET35=1^22$, % SET BIT 35 ON NEXT WRITE %
XFSEQ=1^24$, % PROCESSING SEQUENCE NO. %
XFPGMK=1^25$, % PROCESSING PAGE MARK %
XFFISTAR=1^26$, % FILE NAME IS "*" %
XFXSTAR=1^27$, % EXTENSION NAME IS "*" %
XFUOPEN=1^28$, % FILE IS OPEN FOR UPDATE %
XFDEVAS=1^29$, % DEVICE ASSIGNED %
XFIOERR=1^30$, % I/O ERROR DETECTED %
XFNSET=1^35$; % CHANNEL NOT SET %
%(
MACROS WHICH DEFINE THE CALLS TO SETTBL/GETTBL
)%
MACRO UMAX=0$, % MAXIMUM CHANNEL %
UMODE=1$, % DATA MODE %
UDEV=2$, % DEVICE IN SIXBIT %
UOBUFF=3$, % OUTPUT BUFFER HEADER POINTER %
UIBUFF=4$, % INPUT BUFFER HEADER POINTER %
UOBUFFR=5$, % ADDR OF OUTPUT BUFFER %
UOPTR=6$, % OUTPUT BUFFER BYTE POINTER %
UOCNT=7$, % OUTPUT BUFFER BYTE COUNT %
UIBUFFR=8$, % ADDR OF INPUT BUFFER %
UIPTR=9$, % INPUT BUFFER BYTE POINTER %
UICNT=10$, % INPUT BUFFER BYTE COUNT %
UFILE=11$, % FILE NAME IN SIXBIT %
UEXT=12$, % EXTENSION NAME IN SIXBIT %
UBLK=13$, % %
UERR=14$, % ERROR NUMBER %
UPROT=15$, % PROTECTION KEY %
UDMODE=16$, % CREATION DATA MODE %
UTIME=17$, % CREATION TIME %
UDATE=18$, % CREATION DATE %
UPPN=19$, % PPN %
USTAT=20$, % USER BITS OF STATUS WORD %
USSTAT=21$, % SYSTEM BITS OF STATUS WORD %
USWITCH=22$, % SWITCH WORD %
UREPROT=23$, % REPROTECTION WORD %
USIZ=24$; % FILE SIZE %
FORWARD
CLOSE, %(#30 PARAMETERS: A CHANNEL NUMBER
FUNCTION: CLOSES THE SPECIFIED CHANNEL,
RELEASES ITS DEVICE, AND RESETS THE
ASSOCIATED BITS IN THE CHNLTAB ENTRY
USES: XCT
EXTERNALS: CHNLTAB
)%
CMUDEC; %(#40 PARAMETERS: LEFT JUSTIFIED ALPHA CMU
CHARGE NO., OR 0.
LEFT JUSTIFIED ALPHA CMU
MAN NO., OR 0.
FUNCTION: CONVERTS GIVEN PARAMETERS TO
DEC PPN NUMBERS....RETURNS 0 FOR 0-VALUES.
VALUE: A DEC PPN---LEFT HALF PROJECT, RIGHT
HALF PROGRAMMER.
)%
EXTERNAL
DEFAULTS;
FORWARD
DUMCHN, %(#37 PARAMETERS: 1) A CHANNEL NUMBER
2) THE DUMMY-MODE TO SET
1 -> MARK AS DUMMY
0 -> MARK AS NOT-DUMMY
FUNCTION: MARKS THE SPECIFIED CHANNEL
AS A DUMMY CHANNEL (IF
MODE=1). DUMMY CHANNELS EAT UP
OUTPUT AND RETURN ENDFILES ON INPUT.
A CHANNEL MAY BE UNDUMMIED AT
ANY TIME, SINCE IT DOES NOT AFFECT
THE ENDFILE BITS ON READ. THE
SET35 BIT IS RESET ON DUMMY OUTPUT,
HOWEVER.
EXTERNALS: CHNLTAB
)%
ENDALL, %(#31 PARAMETERS: NONE
FUNCTION: CLOSES ALL I/O CHANNELS
USES: CLOSE
EXTERNALS: CHNLTAB
)%
ENTER, %(#43 PARAMETERS: A CHANNEL NUMBER
FUNCTION: PERFORMS AN ENTER UUO ON THE
SPECIFIED CHANNEL
VALUES: 1 => SUCCESS; 0 => FAILURE
)%
FILLIN, %( 26 FUNCTION: FILLS THE INPUT BUFFER FOR A
GIVEN CHANNEL
PARAMETERS: THE CHANNEL NUMBER
USES: XINPUT, IOERR
EXTERNALS: CHNLTAB
VALUES:
0 - END-OF-FILE OCCURED
1 - SUCCESSFUL INPUT
)%
GETCHAR, %( 5 FUNCTION: RETURNS A SINGLE ASCII CHARACTER
OBTAINED FROM THE TELETYPE.
PARAMETERS: NONE
USES: TTCALL (MONITOR UUO)
VALUES: THE CHARACTER, RIGHT JUSTIFIED
)%
GETPPN, %(#23 FUNCTION: RETURNS THE VALUE OF THE
CURRENT PROJECT-PROGRAMMER NUMBER.
USES: CALLI (MONITOR UUO)
VALUE: THE PPN PAIR AS PER DEC SPECS.
)%
GETSTAT, %(#32
)%
GETSW, %(#36 PARAMETERS: 1) A CHANNEL NUMBER
FUNCTION: RETURNS THE SWITCH WORD FOR THAT CHANNEL
EXTERNALS: CHNLTAB
)%
INVALID; %(# 4
)%
EXTERNAL
IOERR;
FORWARD
IOPACK, %( 39 )%
ISREADOK, %( 9
)%
ISWRITEOK, %( 18
)%
LOOKUP, %(#42 PARAMETERS: A CHANNEL NUMBER
FUNCTION: PERFORMS A LOOKUP UUO ON
THE SPECIFIED CHANNEL.
VALUES: 1 => SUCCESS; 0 => FAILURE
)%
OPEN, %( 17 PARAMETERS: A CHANNEL NUMBER
FUNCTION: EXECUTES AND OPEN INSTRUCTION ON THE DEVICE
ASSOCIATED WITH THAT CHANNEL
USES: XCTSKIP
EXTERNALS: CHNLTAB
VALUES 1-> SUCCESS; 0 -> FAILURE
)%
OPENIN, %( 16 PARAMETRS: A CHANNEL NUMBER
FUNCTION: OPENS A DEVICE IF PERMISSIBLE AND
PERFORMS A LOOKUP AND INBUF ON THAT CHANNEL
USES: XCTSKIP,XCT,IOERR,IOPANIC,OPEN
EXTERNALS: CHNLTAB,IOZERROR
IOERRS: (7) LOOKUP FAILED
(8) OPEN FAILED
VALUES: 1 -> SUCCESS; 0 -> FAILURE
)%
OPENOUT, %( 19
)%
OUTMSG, %(#38
)%
PADNULL; %(#25
)%
EXTERNAL
IOPANIC; %( 71 PARAMETERS: AN IOERR NUMBER
FUNCTION: USED AS A IOPANIC STOP FOR
ERROS WHICH HAVE NO RECOVERY
BUT SOMEHOW RETURNED
USES:PUTMSG,DECIMAL,TTYPUTS, CALLI ,12
)%
FORWARD
PUTCHAR, %( 28
)%
PUTMSG, %(#34 PARAMETERS: AN IOERR MESSAGE, BROKEN INTO
AS MANY 5-CHARACTER LEFT-JUSTIFIED
ASCII STRINGS AS NECESSARY. ANY
NUMBER OF SUCH PARAMETERS MAY BE
PROVIDED. ALL BUT THE LAST MUST
BE PRECISELY 5 CHARACTERS; THE
LAST MUST BE LESS THAN 5.
FUCNTION: TYPES OUT THE MESSAGE ON THE TTY
USES: TTYPUTS
)%
READ, %(#27
)%
RENAME, %(#41 PARAMETERS: 1) A CHANNEL NUMBER
2) A NEW FILE NAME, OR 0 TO
RETAIN OLD ONE
3) A NEW EXTENSION NAME, OR 0 TO
RETAIN OLD ONE
4) A NEW PROTECTION KEY OR
0 TO RETAIN OLD ONE
FUNCTION: RENAMES OR DELETES THE FILE JUST
CLOSED ON THE CHANNEL SPECIFIED
USES: RENAME UUO, UNPACK, PAC, IOERR
IOERRS: 26: UNDEFINED IOERR
34: NO UFD
35: WRITE PROTECTED
36: ACTIVE FILE
37: ALREADY EXISTING FILE
38: NO FILE SELECTED
39: NO DEVICE
VALUES: 0 => RENAME FAILURE
1 => RENAME SUCCESS
)%
RESET, %(# 3 FUNCTION: RESETS I/O CHANNELS AND SETS
UP DEFAULTS FOR CHANNEL ASSIGNEMNTS.
USES: CALLI (MONITOR UUO), RETABLE
)%
RETABLE, %( 35 PARAMETERS: NONE
FUNCTION: COMPLETELY CLEARS CHNLTAB AND
THEN SETS DEFAULT VALUES
EXTERNALS: CHNLTAB
USES: DEFAULTS
)%
SET35, %(#33 PARAMETERS: A CHANNEL NUMBER
FUNCTION: MARKS THE STATUS WORD SO THAT
THE WORD CONTAINING THE NEXT
CHARACTER TO BE PLACED BY A WRITE
WILL GET BIT 35 SET TO 1. NOTE
THAT THIS BIT IS RESET WHEN BIT 35
IS SET.
USES: CHNLTAB
)%
SETCHN, %(#10
)%
SIXBIT, %(# 7 RETURNS SIXBIT VALUE OF ITS ARGUEMENT
)%
TTYPUTS, %( 20
)%
WRITE, %(#21
%
XCT, %(#24 PARAMETERS: AN OP, A REGISTER, AND THE REST OF A 23-BIT ADDRESS
FUNCTION: CONSTRUCTS AN INSTRUCTION FROM
THE GIVEN DATA AND DOES AN
XCT AGAINST IT.
VALUE: 0
%
XCTSKIP, %(#13 PARAMETERS: AN OP, A REGISTER, AND THE REST OF A 23-BIT ADDRESS
FUNCTION: CONSTRUCTS AND INSTRUCTION FROM
THE GIVEN DATA AND DOES AN XCT
AGAINST IT.
VALUES: 1 -> SKIPPED; 0 -> DID NOT
%
XINPUT, %( 14 PARAMETERS: A CHANNEL NUMBER
FUNCTION: EXECUTES IN "INPUT" INSTRUCTION
USES: XCTSKIP
VALUES: 0-> ENDFILE; 1-> SUCCESS; 2-> IOERR
)%
XOUTPUT; %( 15 PARAMETERS: A CHANNEL NUMBER
FUNCTION: EXECUTES AND "OUTPUT" INSTRUCTION
USES: XCTSKIP
VALUES: 0 -. ENDFILE; 1 -> SUCCESS; 2-> IOERR
)%
GLOBAL ROUTINE CRLF(CHNL)=
%%
%
THIS ROUTINE OUTPUTS A CARRIAGE RETURN/LINE FEED PAIR
ON THE GIVEN CHANNEL. IT IS CHEAPER TO USE A ROUTINE
TO DO THIS AND CALL IT (USES 3 INSTRUCTIONS) THAN TO
USE A MACRO IN LINE (USES 8 INSTRUCTIONS).
%
%%
(WRITE(.CHNL,#015); WRITE(.CHNL,#012));
GLOBAL ROUTINE RESET=
%%
%
THIS ROUTINE RESETS ALL MONITOR I/O CHANNELS AND ALL
SORTS OF WONDERFUL THINGS WITH ONLY ONE
INSTRUCTION!!! HOW ABOUT THAT!!! FURTHERMORE IT CALLS
RETABLE TO CLEAR THE CHANNEL TABLE TO ZEROES. NOTE
THAT THIS ASSUMES ALL I/O ACTIVITY HAS BEEN CLEARED
UP. IF IT WASN'T, THE CALLI MADE SURE.
%
%%
BEGIN
MACHOP CALLI=#047;
CALLI (0,0,0,0);
RETABLE()
END;
GLOBAL ROUTINE INVALID(CHNL,ERR)=
%%
%
THIS ROUTINE CHECKS TO SEE IF THE CHANNEL NUMBER
GIVEN IS VALID. A VALID CHANNEL NUMBER IS EITHER ZERO
(TTY) OR IN THE RANGE 1 =< CHNL =< CHNLMAX. IF IT IS
OUTSIDE THIS RANGE THEN THE CHANNEL NUMBER IS PLUNKED
INTO IOZERROR AND THE ERROR HANDLER IS CALLED. NOTE
THAT IF CONTROL RETURNS FROM THE ERROR HANDLER "TRUE"
IS PASSED TO THE CALLER OF INVALID.
%
%%
(IF (.CHNL NEQ 0) AND (.CHNL LSS 0 OR .CHNL GTR .CHNLMAX) THEN
(IOZERROR_.CHNL; IOERR(.ERR); 1) ELSE 0);
ROUTINE GETCHAR=
%%
%
THIS ROUTINE IS CALLED IN THE CASE OF A READ FROM
CHANNEL 0. NOTE THAT THE TTCALL IS "INCHWL", OR INPUT
IN LINE MODE. THUS THIS ROUTINE WILL NOT RETURN
CONTROL UNTIL A CARRIAGE RETURN, FORM FEED, ALTMODE,
OR VERTICAL TAB HAS BEEN TYPED. SUCCESSIVE CALLS WILL
RETURN SUCESSIVE CHARACTERS UNTIL THE LINE BUFFER IS
EMPTY, AFTER WHICH THE NEXT CALL WILL WAIT UNTIL IT
IS FILLED AGAIN.
%
%%
BEGIN
MACHOP TTCALL=#051;
TTCALL(4,VREG,0,0);
.VREG
END;
GLOBAL ROUTINE GETSTS(CHNL)=
BEGIN
MACRO GETSTS=#062$;
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
LOCAL T;
IF INVALID(.CHNL,18) THEN 18^18 ELSE
IF NOT .FSTATUS<FDEVAS> THEN 0 ELSE
(XCT(GETSTS,@CHNL-1,T);
.T)
END;
GLOBAL ROUTINE SIXBIT(CHAR)=
(((IF .CHAR GEQ "\" THEN .CHAR AND #137 ELSE IF .CHAR LSS " " THEN #40 ELSE .CHAR)
+#40) AND #77);
ROUTINE ISREADOK(CHNL)=
%%
%
THIS ROUTINE RETURNS TRUE IF READING IS ALLOWED ON THE GIVEN
CHANNEL, OTHERWISE IT CALLES THE I/O ERROR ROUTINE
AND RETURNS WHATEVER VALUE IT RETURNS (USUALLY THE
ERROR CODE IN THE LEFT HALFWORD)
%
%%
BEGIN
REGISTER T;
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
T_.FSTATUS;
IF (.T<FUSER> AND (XFYREAD+XFYUPDAT+XFYSIMUL)) EQL 0 THEN
BEGIN
IOZERROR_.CHNL;
IOERR(2)
END
%(
E R R O R 2 : ATTEMPT TO READ FROM NOREADABLE
DEVICE.
)%
ELSE
IF .T<FWOPEN> AND NOT .T<FYSIMUL> THEN
BEGIN
IOZERROR_.CHNL;
IOERR(3)
END
%(
E R R O R 3: ATTEMPT TO READ FROM DEVICE BEING WRITTEN ON
)%
ELSE
1
END;
GLOBAL ROUTINE SETCHN (CHNL,MODE,DEV,FILE,EXT,PRJ,PRG,STATUS,SW,PROT)=
BEGIN
%(
THE FUNCTION OF THIS ROUTINE IS TO
INITIALIZE THE CHANNEL TABLE VALUES
GIVEN ASCII STRINGS FOR NAMES.
THE STRUCTURE OF THE CHANNEL TABLE IS:
0 MODE (ASCII, USUALLY)
1 DEVICE IN SIXBIT FO$MAT
2 BUFFER WORD (OUT,,IN)
3-5 OUTPUT BUFFER HEADER
6-8 INPUT BUFFER HEADER
9 FILENAME IN SIXBIT
10 EXTENSION IN SIXBIT
11 0 (SET LATER BY MONITOR)
12 PPN
13 STATUS
14 SWITCHES
15 RIGHTMOST 10 BITS: PROTECTION WORD
THE SWITCH WORD CONTAINS BITS FOR EACH OF THE SWITCHES
SET EITHER BY DEFAULT OR BY /N NOTATION. THE ASSIGNMENTS ARE:
P/S BIT SWITCH
<0,1> 35 /A
<1,1> 34 /B
<2,1> 33 /C
<3,1> 32 /D
<4,1> 31 /E
<5,1> 30 /F
<6,1> 29 /G
<7,1> 28 /H
<8,1> 27 /I
<9,1> 26 /J
<10,1> 25 /K
<11,1> 24 /L
<12,1> 23 /M
<13,1> 22 /N
<14,1> 21 /O
<15,1> 20 /P
<16,1> 19 /Q
<17,1> 18 /R
<18,1> 17 /S
<19,1> 16 /T
<20,1> 15 /U
<21,1> 14 /V
<22,1> 13 /W
<23,1> 12 /X
<24,1> 11 /Y
<25,1> 10 /Z
<26,1> 9 /0
<27,1> 8 /1
<28,1> 7 /2
<29,1> 6 /3
<30,1> 5 /4
<31,1> 4 /5
<32,1> 3 /6
<33,1> 2 /7
<34,1> 1 /8
<35,1> 0 /9
THE PARAMETERS PASSED ARE:
CHNL A CHANNEL NUMBER 1=< N =< 16
MODE A DATA MODE (E.G. 1=ASCII)
DEV A POINTER TO TWO WORDS CONTAINING A DEVICE NAME
FILE " " " " " " A FILE NAME
EXT " " " A WORD CONTAINING AN EXTENSION NAME
PRJ A PROJECT N(MBER
PRG A PROGRAMMER NUMBER
STATUS BITS 32-35 OF THE STATUS WORD
SW A 36-BIT SWITCH MASK
NOTE THE FOLLOWING ACTIONS ARE TAKEN ON ZERO VALUES:
CHNL- TTY CHANNEL (NO ACTION)
MODE- THE DEFAULT MODE IS USED
DEV- THE DEFAULT DEVICE IS USED. THIS IS TRUE IF
.DEV=0 OR ..DEV=0
FILE- THE DEFAULT FILES IS USED. THIS IS TRUE IF
.FILE=0 OR ..FILE=0
EXT - THE DEFAULT EXTENSION IS USED. AS IN FILE AND DEV.
PRJ )
PRG ) NO SPECIAL ACTION, BUT EITHER BOTH MUST BE ZERO OR
BOTH NONZERO. IF ZERO THE PPN WILL BE SET TO 0.
STATUS - USE DEFAULT STATUS
SW - NO SPECIAL ACTION. SINCE SW BITS ARE OR'ED IN, A
ZERO VALUE PRODUCES NO CHANGE
)%
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
MACRO F1ST=29,7$;
IF .CHNL EQL 0 % TTY % THEN 1 ELSE
IF .CHNL LSS 0 OR .CHNL GTR TABMAX THEN IOERR(4) ELSE
IF (.FSTATUS AND (XFUOPEN+XFROPEN+XFWOPEN)) NEQ 0 THEN IOERR(17) ELSE
! SET UP THE PPN FIELDS
IF (.PRJ EQL 0) XOR (.PRG EQL 0) THEN
IOERR(5) ELSE
%(
E R R O R 5: PROJ OR PROG SPECIFIED BUT NOT BOTH
)%
BEGIN
FPRJ_.PRJ;
FPRG_.PRG;
%(
E R R O R 4 : ATTEMPT TO USE CHANNEL > 16, OR < 1
)%
%(
SET MAXCHN TO HIGHEST CHANNEL NUMBER GIVEN SO FAR
)%
IF .CHNL GTR .CHNLMAX THEN CHNLMAX_.CHNL;
%(
E R R O R 1 7 : ATTEMPT TO SETCHN ON AN OPEN CHANNEL
)%
! SET STATUS BITS
IF .STATUS NEQ 0 THEN
FSTATUS_.STATUS;
FSTATUS<FNSET>_0; % TURN OFF INVALID BIT %
! SET MODE:
IF .MODE NEQ 0 THEN
FMODE_.MODE;
! SET DEVICE
IF .DEV NEQ 0 THEN
IF .@DEV NEQ 0 THEN FDEV_IOPACK((@DEV)<0,0>,6);
! SET OBUF POINTER
IF .STATUS<FYWRITE> OR .STATUS<FYUPDAT> THEN
FBUFO_FOBUFH;
! SET IBUF POINTER
IF .STATUS<FYREAD> OR .STATUS<FYUPDAT> THEN
FBUFI_FIBUFH;
! SET UP THE FILE NAME
IF .FILE NEQ 0 THEN
IF ..FILE NEQ 0 THEN
BEGIN
FFILE_IOPACK((@FILE)<0,0>,6);
IF ..FILE<F1ST> EQL "*" THEN FSTATUS<FFISTAR>_1;
END;
! SET UP THE EXTENSION
IF .EXT NEQ 0 THEN
IF ..EXT NEQ 0 THEN
BEGIN
FEXT_IOPACK((@EXT)<0,0>,3);
IF ..EXT<F1ST> EQL "*" THEN FSTATUS<FXSTAR>_1;
END;
! SET THE SWITCH WORD
FSWITCH_.FSWITCH OR .SW;
! SET THE PROTECTION WORD
IF .PROT NEQ 0 THEN FNEWPR_.PROT;
1
END
END;
GLOBAL ROUTINE XCTSKIP(OP,REG,ETC)=
BEGIN
%%
%
THE FUNCTION OF THIS ROUTINE IS TO EXECUTE A MONITOR
UUO WHICH DOES A SKIP-RETURN. THE VALUE OF THE
ROUTINE IS TRUE IF THE SKIP-RETURN WAS TAKEN AND
FALSE IF NOT TAKEN.
%
%%
MACHOP XCT=#256, MOVEI=#201;
MACRO OPCOD=27,9$, REGFLD=23,4$;
REGISTER T;
T_.ETC;
T<OPCOD>_.OP;
T<REGFLD>_.REG;
! WE NOW HAVE AN INSTRUCTION. SET R TRUE ASSUMING SKIP RETURN
MOVEI (VREG,1);
XCT (0,T);
MOVEI (VREG,0);
! IF NO SKIP OCCURED, R IS NOW FALSE;
.VREG
END;
ROUTINE XINPUT(CHNL)=
BEGIN
MACRO IN=#056$, STATZ=#063$;
%%
%
THIS ROUTINE EXECUTES AN "INPUT" INSTRUCTION AND
RETURNS ONE OF THREE VALUES:
0 = ENDFILE OCCURED
1 = SUCCESSFUL EXECUTION
2 = FAILURE FOR I/O ERROR OF SOME KIND
NOTE HOW SNEAKY WE ARE: BOTH 0 AND 2 ARE INTERPRETED
AS "FALSE" BY BLISS!!! SO WE CAN (AND DO) USE XINPUT
IN IF-EXPRESSIONS.
%
%%
IF XCTSKIP(IN,@CHNL-1,0) THEN
BEGIN
! IF "IN" SKIPS THEN WE HAVE AN ERROR
IF XCTSKIP(STATZ,@CHNL-1,#740000) THEN
0 ELSE 2
! IF "STATZ" SKIPS THEN WE HAVE ENDFILE, ELSE ERROR
END
ELSE
! "IN" DID NOT SKIP SO WE HAVE A NEW BLOCK
1
END;
ROUTINE XOUTPUT(CHNL)=
BEGIN
%%
%
THIS ROUTINE MISBEHAVES THE SAME AS XINPUT. GO BACK
AND READ IT THERE, I'M TIRED OF TYPING.
%
%%
MACRO OUT=#057$, STATZ=#063$;
IF XCTSKIP(OUT,@CHNL-1,0) THEN
BEGIN
! IF "OUT" SKIPS THEN WE HAVE AN ERROR
IF XCTSKIP(STATZ,@CHNL-1,#740000) THEN
0 ELSE 2
! IF "STATZ" SKIPS THEN WE HAVE PHYSICAL END OF DEVICE ELSE OTHER SCREWUPS
END
ELSE
! "OUT" DID NOT SKIP, SO WE GOT RID OF THAT BLOCK OK
1
END;
ROUTINE OPENIN(CHNL)=
BEGIN
%%
%
THIS ROUTINE OPENS A CHANNEL (VIA ROUTINE "OPEN") AND
THEN PERFORMS THE NECESSARY LOOKUP AND INBUF TO ALLOW
READ OPERATIONS.
%
%%
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
MACRO INBUF=#064$;
LOCAL T;
IF NOT (T_ISREADOK(.CHNL)) THEN RETURN .T;
IF OPEN(@CHNL) THEN
BEGIN
FSTATUS<FDEVAS>_1;
IF LOOKUP(.CHNL) THEN
BEGIN
SELECT #0, #1, #10, #13, #14 OF
NSET
.FMODE: XCT(INBUF,@CHNL-1,2);
TESN;
1
END
ELSE
%LOOKUP FAILED %
( IOZERROR_.CHNL; IOERR( SELECT .FERR OF
NSET
0: 7;
1: 27;
2: 28;
7: 29;
OTHERWISE: 30;
TESN))
%%
%
E R R O R 7 : LOOKUP FAILED
%
%%
END
ELSE
%OPEN FAILED %
(IOZERROR_.CHNL;IOERR(8))
%%
%
E R R O R 8 : OPEN FAILED
%
%%
END;
ROUTINE OPEN(CHNL)=
BEGIN
%%
%
THIS ROUTINE OPENS A CHANNEL AND RETURNS TRUE IF THE
CHANNEL OPENED OR FAILS IF IT DIDN'T
%
%%
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
MACRO OPEN=#050$;
IF .FSTATUS<FDEVAS> THEN 1 ELSE
XCTSKIP(OPEN,@CHNL-1,FMODE)
END;
ROUTINE ISWRITEOK(CHNL)=
BEGIN
%%
%
THIS ROUTINE EITHER RETURNS TRUE (IN WHICH CASE
WRITING IS PERMISSIBLE) OR CALLS THE IOERR HANDLER,
AND RETURNS ITS VALUE.
%
%%
REGISTER T;
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
IOZERROR_.CHNL;
T_.FSTATUS;
IF (.T<FUSER> AND (XFYWRITE+XFYUPDAT+XFYSIMUL)) EQL 0 THEN IOERR(9) ELSE
IF .T<FROPEN> THEN (IF NOT (.T<FYUPDAT> OR .T<FYSIMUL>) THEN IOERR(10) ELSE 1) ELSE
1
%%
%
E R R O R 9 : ATTEMPT TO WRITE ON NONWRITEABLE DEVICE
E R R O R 10 : ATTEMPT TO WRITE ON INPUT DEVICE
%
%%
END;
ROUTINE OPENOUT(CHNL)=
BEGIN
%%
%
THIS ROUTINE OPENS A CHANNEL FOR OUPUT BY DOING AN
OPEN UUO TO OBTAIN A DEVICE, AN ENTER TO CREATE THE
FILE, AND AN OUTBUF IF NECESSARY TO CREATE THE BUFFER
CHAIN (AND A DUMMY OUTPUT UUO TO INITIALIZE THE
BUFFERS).
%
%%
MACRO OUTBUF=#065$, OUTPUT=#067$;
LOCAL T;
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
IF NOT (T_ISWRITEOK(.CHNL)) THEN .T ELSE
BEGIN
IF OPEN(@CHNL) THEN
BEGIN
FSTATUS<FDEVAS>_1;
IF ENTER(.CHNL) THEN
BEGIN
SELECT #0, #1, #10, #13, #14 OF
NSET
.FMODE: (XCT (OUTBUF,@CHNL-1,3);
XCT (OUTPUT,@CHNL-1,0));
TESN;
1
END
ELSE
%ENTER FAILED%
(IOZERROR_.CHNL; IOERR(SELECT .FERR OF
NSET
1: 31;
2: 32;
3: 33;
7: 6;
OTHERWISE: 11;
TESN))
%%
%
E R R O R 11 : ENTER FAILED
%
%%
END
ELSE
%OPEN FAILED%
(IOZERROR_.CHNL;IOERR(12))
%%
%
E R R O R 12 : OPEN FAILED
%
%%
END
END;
GLOBAL ROUTINE TTYPUTS(STR)=
%%
%
THIS ROUTINE OUTPUTS A STRING TO THE TTY. THE VALUE
PASSED IS A POINTER TO THE STRING.
%
%%
BEGIN
MACHOP TTCALL=#051;
TTCALL (3,STR,0,1);
END;
GLOBAL ROUTINE WRITE (CHNL,CHAR)=
%%
%
THIS ROUTINE TAKES THE CHARACTER PASSED AND WRITES IT
KN THE SPECIFIED CHANNEL. IF THE CHANNEL IS A DUMMY
CHANNEL NO OPERATION TAKES PLACE. BUFFERS ARE
AUTOMATICALLY WRITTEN OUT AS THEY ARE FILLED. THE
CHANNEL AND FILE ARE OPENED IF NECESSARY. FOR ASCII
MODE FILES, BIT 35 OF THE WORD WHICH WILL ACCEPT THE
GIVEN CHARACTER MAY BE SET TO 1 IF THE <FSET35> BIT
OF THE STATUS WORD IS 1. THIS (THE <FSET35> BIT) IS
THEN CLEARED. RETURNS TRUE IF SUCCESSFUL AND FALSE IF
NOT. THE FIOERR BIT IS SET FOR FAILURES INVOLVING
VALID CHANNELS.
%
%%
BEGIN
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
LOCAL T;
IF INVALID(.CHNL,23) THEN 23^18 ELSE
IF .CHNL EQL 0 THEN (PUTCHAR(.CHAR);1) ELSE
BEGIN
FSTATUS<FIOERR>_1; % ASSUME WRONG UNTIL PROVEN OTHERWISE %
%%
%
IF WE HAVE A DUMMY CHANNEL, GO BACK WITHOUT DOING ANYTHING
%
%%
IF .FSTATUS<FYDUMMY> THEN (FSTATUS_ .FSTATUS AND NOT(XFSET35+XFIOERR);
RETURN 1);
IF NOT .FSTATUS<FWOPEN> THEN
BEGIN
IF NOT (T_OPENOUT(.CHNL)) THEN RETURN .T; % IF IT WASNT OPEN, THEN OPEN IT %
FSTATUS<FWOPEN>_1;
END;
IF .FOCNT EQL 0 THEN
% BUFFER IS FULL %
BEGIN
IF NOT XOUTPUT(.CHNL) THEN (IOZERROR_.CHNL;RETURN IOERR(23));
END;
FOCNT_.FOCNT-1;
%%
%
WE HAVE JUST DECREASED THE BUFFER COUNT. NOW PUT A
CHARACTER IN
%
%%
REPLACEI (FOPTR,.CHAR);
%%
%
IF USER SETS BIT <FSET35> THEN HE WANTS BIT 35 OF THE
CURRENT WORD SET TO A 1 FOR SEQUENCE NUMBERS.
%
%%
IF .FSTATUS<FSET35>THEN
BEGIN
(@FOPTR)<0,36>_.((@FOPTR)<0,36>) OR 1;
FSTATUS<FSET35>_0;
END;
FSTATUS<FIOERR>_0; % PROVEN OTHERWISE %
1
END
END;
GLOBAL ROUTINE GETPPN=
%%
%
THIS ROUTINE RETURNS THE PROJECT PROGRAMMER NUMBER
PAIR AS DETERMINED BY THE JOB LOGGED ON. IT USES THE
CALLI UUO.
%
%%
BEGIN
MACHOP CALLI=#047;
CALLI (VREG,#24) ; % CALL [SIXBIT /GETPPN/]%
.VREG
END;
GLOBAL ROUTINE XCT(OP,REG,ETC)=
BEGIN
MACHOP XCT=#256;
REGISTER T;
MACRO OPCOD=27,9$, REGFLD=23,4$;
T_.ETC;
T<OPCOD>_.OP;
T<REGFLD>_.REG;
XCT(0,T);
END;
GLOBAL ROUTINE PADNULL(CHNL)=
BEGIN
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
MACRO POS=30,6$;
MACRO SIZE=24,6$;
LOCAL T;
%(
THE FUNCTION OF THIS ROUTINE IS TO PADD THE CURRENT WORD
BEING FILLED TO NULLS, ALLOWING INSERTION OF SEQUENCE
NUMBERS IN THE NEXT WORD.
WE ACCOMPLISH THIS BY WRITING CHARS UNTIL THE BYTE POINTER
POSITION FIELD BECOMES LESS THAN THE SIZE FIELD, INDICATING THE NEXT REPLACEI WILL
WRITE INTO THE FIRST CHARACTER OF THE ENXT WORD.
)%
IF .FSTATUS<FWOPEN> THEN
WHILE .FOPTR<POS> GEQ .FOPTR<SIZE> DO
IF NOT (T_WRITE(.CHNL,0)) THEN RETURN .T;
1
END;
ROUTINE FILLIN(CHNL)=
BEGIN
LOCAL T;
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
IF NOT (T_XINPUT(.CHNL)) THEN
% WE HAVE EITHER AN ERROR OR AN ENDFILE %
BEGIN
IF .T EQL 0 THEN
BEGIN
% WE HAVE AN ENDFILE %
FSTATUS<FEOF>_1;
0
END
ELSE
BEGIN
% WE HAVE OTHER PROBLEMS %
(IOZERROR_.CHNL;IOERR(13))
!
! E R R O R 1 3 : READ ERROR
!
END
END
ELSE
% WE HAVE FILLED A BUFFER %
1
END;
GLOBAL ROUTINE READ(CHNL)=
BEGIN
LOCAL T;
REGISTER TEMP;
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
IF INVALID(.CHNL,22) THEN (FSTATUS<FIOERR>_1; 22^18) ELSE
IF .CHNL EQL 0 THEN GETCHAR() ELSE
%(
IF DUMMY CHANNEL OR EOF BIT ON THEN GIVE ENFILE
)%
BEGIN
IF (.FSTATUS AND (XFYDUMMY+XFEOF)) NEQ 0 THEN (FSTATUS<FEOF>_1; RETURN -1);
FSTATUS<FIOERR>_0; % ASSUME OK %
IF NOT .FSTATUS<FROPEN> THEN
BEGIN
IF NOT (T_OPENIN(.CHNL)) THEN RETURN .T;
FSTATUS<FROPEN>_1;
IF ((T_ FILLIN(.CHNL)) EQL 0 ) THEN RETURN -1 ELSE IF NOT .T THEN (FSTATUS<FIOERR>_1; RETURN .T);
END;
% AT THIS POINT WE PRESUMABLY HAVE SOMETHING IN THE BUFFER %
WHILE .FICNT EQL 0 DO
BEGIN
% BUFFER WAS EMPTY %
IF ((T_ FILLIN(.CHNL)) EQL 0 ) THEN RETURN -1 ELSE IF NOT .T THEN (FSTATUS<FIOERR>_1; RETURN .T);
END;
% DECREASE CHAR COUNT BY 1 %
FICNT_.FICNT-1;
T_ SCANI(FIPTR);
% SEE IF BIT 35 OF WORD WE JUST GOT CHAR FROM IS SET %
TEMP_.(@FIPTR)<0,36>;
FSTATUS<FSEQ>_ IF .TEMP THEN 1 ELSE .FSTATUS<FIS35>;
FSTATUS<FPGMK>_(.TEMP EQL #064321400001);
FSTATUS<FIS35>_.TEMP;
.T
END
END;
ROUTINE PUTCHAR(CHAR)=
BEGIN
MACHOP TTCALL=#051;
TTCALL(1,CHAR);
END;
GLOBAL ROUTINE CLOSE(CHNL)=
BEGIN
%(
THE FUNCTION HERE IS TO CLOSE THE SPECIFIED CHANNEL AND
RELESASE THE DEVICE. ALL RELEVANT STATUS BITS OF THE
CHANNEL TABLE ENTRY ARE CLEARED
)%
MACRO CLOS=#070$, RELEAS=#071$;
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
LOCAL T;
T_1;
IF INVALID(.CHNL,21) THEN 21^18 ELSE
IF .CHNL EQL 0 THEN 1 ELSE
(REGISTER F;
F_.FSTATUS;
IF (.F AND (XFUOPEN+XFROPEN+XFWOPEN)) NEQ 0 THEN
BEGIN
XCT(CLOS,.CHNL-1,0);
F_.F AND NOT (XFUOPEN+XFROPEN+XFWOPEN);
IF (T_.FNEWPR) NEQ 0 THEN
(IF .FPROT NEQ .T<0,9> THEN T_RENAME(.CHNL,0,0,.T<0,9>));
XCT(RELEAS,.CHNL-1,0);
F<FDEVAS>_0;
%(
IF REWIND ALLOWED, WE TURN OFF ENDFILE BITS OF INPUT
FILES. IF REWIND NOT ALLOWED, WE MARK CHANNEL
AS UNREADABLE AND UNWRITEABLE.
)%
F_.F AND NOT (XFIOERR+XFIS35+XFSET35+XFSEQ+XFPGMK);
IF .F<FYREW> THEN
%(
REWIND IS ALLOWED
)%
BEGIN
F<FEOF>_0; %TURN OFF ENDFILE BIT%
% IF OUTPUT CHANNEL WE DO NOT WANT TO RESET DUMMY BIT %
END
ELSE
BEGIN
%(
REWIND NOT ALLOWED
)%
F_.F AND NOT (XFYUPDAT+XFYREAD+XFYWRITE);
END;
END;
FSTATUS_.F;
.T)
END;
GLOBAL ROUTINE ENDALL=
BEGIN
INCR I FROM 1 TO .CHNLMAX DO CLOSE(.I);
1
END;
GLOBAL ROUTINE GETSTAT(CHNL)=
BEGIN
IF .CHNL LSS 0 OR .CHNL GTR .CHNLMAX THEN (1^35) ELSE
IF .CHNL EQL 0 THEN 0 ELSE
.CHNLTAB[.CHNL,13]
END;
GLOBAL ROUTINE SET35(CHNL)=
BEGIN
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
IF INVALID(.CHNL,19) THEN 19^18 ELSE
IF .FMODE GTR 1 THEN IOERR(20) ELSE
IF .CHNL EQL 0 THEN 1 ELSE (FSTATUS<FSET35>_1)
END;
GLOBAL ROUTINE PUTMSG(MSG)=
%(
THIS IS A SNEAKY ROUTINE. WHAT IT DOES IS DETERMINE THE
NUMBER OF PARAMETERS IT HAS BEEN GIVEN BY EXAMINING
THE "SUB" INSTRUCTION WHICH IS POINTED TO BY THE RETURN
ADDRESS IN THE STACK. IT THEN GOES BACK THIS MANY
POSITIONS AND DOES A TTYPUTS OF THE STRING STACKED
THERE. THE SNEAKY WAY IT DOES THIS IS ATTRIBUTED TO
BILL WULF. IF IT DOESN'T WORK YOU CAN BLAME HIM. IF
IT DOES, YOU MAY APPLAUD.
)%
BEGIN
LOCAL N,SSAV;
N_ IF .(@(MSG+1 %THE RETURN ADDRESS%))<27,9> %THE OPCODE%
NEQ #274 %A SUBTRACT INSTR% THEN 0 ELSE
.(@@(MSG+1))<0,18> %THE WORD POINTED TO
BY THE ADDR OF THE SUBTRACT%;
SSAV_.(MSG+1)<29,7>; % SAVE STATE BITS %
IF .N GTR 0 THEN (IF .MSG<1,7> NEQ 0 THEN (MSG+1)<29,7>_0;TTYPUTS(MSG-(.N-1)));
(MSG+1)<29,7>_.SSAV; % RESTORE STATE BITS %
END;
GLOBAL ROUTINE RETABLE=
BEGIN
CHNLMAX_TABMAX; % NUMBER OF CHANNELS %
CHNLTAB_TABSIZ; % SIZE OF ENTRY %
INCR J FROM 1 TO TABMAX DO % STEPS THRU CHNLS %
( BIND VECTOR CHAN=CHNLTAB[.J,0]<0,36>;
INCR I TO TABSIZ DO % STEPS THRU ENTRY %
CHAN[.I]_0);
INCR J FROM 1 TO TABMAX DO CHNLTAB[.J,13]<FNSET>_1;
DEFAULTS();
END;
GLOBAL ROUTINE GETSW(CHNL)=
BEGIN
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
IF INVALID(.CHNL,16) THEN 0 ELSE
IF .CHNL EQL 0 THEN 0 ELSE
.FSWITCH
END;
GLOBAL ROUTINE DUMCHN(CHNL,TYPE)=
BEGIN
BIND VECTOR CHAN=CHNLTAB[.CHNL,0]<0,36>;
IF INVALID(.CHNL,15) THE