mirror of
https://github.com/PDP-10/its.git
synced 2026-01-21 10:13:35 +00:00
402 lines
11 KiB
Plaintext
Executable File
402 lines
11 KiB
Plaintext
Executable File
.BEGIN RFN ;-*-MIDAS-*-
|
||
|
||
SUBTTL Routines for parsing and printing filenames
|
||
|
||
;Basic conventions:
|
||
|
||
;We assume that there are accumulators A, B, C, D and E, not necessarily
|
||
;consecutive, and that the stack is in P.
|
||
;No routine clobbers ACs other than the
|
||
;ones it is documented to clobber, and none touches even temporarily
|
||
;any AC other than A, B, C, D, E and P.
|
||
;All code generated is pure.
|
||
;The main routines, RFN, PFN, PFNBRF and PFNMCH, never skip.
|
||
|
||
;This file contains two routines, RFN to read filenames and PFN to print.
|
||
;Both expect a b.p. for ILDB'ing or IDPB'ing the text, in D.
|
||
;Both expect a pointer to a filename block in B.
|
||
;A filename block consists of four words, which hold the
|
||
;left-justified sixbit DEVICE, FN1, FN2 and SNAME in that order.
|
||
|
||
;The RFN routine assumes that the user has defined the label RSIXTP
|
||
;(RSIX-Terminator-P) which should expect a character in A
|
||
;and skip if it should terminate a filename, or start a switch.
|
||
;It will not be called with control characters.
|
||
;Thus, you might want it to skip when given ",", "_" or "/".
|
||
;PFN similarly assumes that there is a routine PSIXTP will will
|
||
;skip for a character in A that needs a ^Q printed in front of it.
|
||
;Normally, RSIXTP and PSIXTP can be the same routine.
|
||
|
||
;If you want switches to be processed in filenames,
|
||
;set $$SWITCH to 1 and define the label SWITCH as a routine to read a switch.
|
||
;It will be called with the first character of the switch in A.
|
||
;It can read more characters off D, or by calling RFN"RUC
|
||
;If it skips, RFN assumes that the character in A should be reprocessed.
|
||
;A slash is followed by a single switch, while parentheses enclose
|
||
;any number of switches. However, neither slash nor "(" will be
|
||
;recognized unless RSIXTP skips for it. This gives the caller
|
||
;run-time control of whether switches are to be processed.
|
||
|
||
;If $$MNAME is set, the user must define MNAME to point to
|
||
;a word holding this machine's name in SIXBIT. RFN"RMNAME initializes it.
|
||
;If $$PFNBRF is set, the user must define MSNAME to point to
|
||
;a word holding the "default" SNAME (the one not to be mentioned).
|
||
|
||
;These symbols should be defined by the user to select parts of this file:
|
||
IFNDEF $$RFN,$$RFN==0 ;Include RFN, the routine for reading
|
||
; filenames.
|
||
IFNDEF $$SWITCH,$$SWITCH==0 ;Include routines for processing "/" and
|
||
; "(-)" switches.
|
||
IFNDEF $$PFN,$$PFN==0 ;Include PFN, the routine for printing
|
||
; filenames.
|
||
IFNDEF $$PFND,$$PFND==0 ;Include PFND, like PFN but device of "DSK"
|
||
; or fn2 of ">" is suppressed.
|
||
IFNDEF $$PFNBRF,$$PFNBRF==0 ;Include routine to print filenames briefly.
|
||
IFNDEF $$RUC,$$RUC==0 ;1 => don't define RUC; use a
|
||
; user-supplied definition.
|
||
IFNDEF $$MNAME,$$MNAME==0 ;1 => assume MNAME is defined and holds
|
||
; this machine's name.
|
||
|
||
IFN $$SWITCH,$$RFN==1
|
||
IFN $$PFNBRF,$$PFNBRF==1
|
||
|
||
DEV==0 ;Indices into the filename block.
|
||
FN1==1
|
||
FN2==2
|
||
SNM==3
|
||
|
||
.AUXIL ;Don't mention all our internal symbols in crefs.
|
||
|
||
;PRINT VERSION NUMBER
|
||
.TYO6 .IFNM1
|
||
.TYO 40
|
||
.TYO6 .IFNM2
|
||
PRINTX/ included in this assembly.
|
||
/
|
||
|
||
DEFINE SYSCAL NAME,ARGS
|
||
.CALL [SETZ ? SIXBIT/NAME/ ? ARGS ((SETZ))]
|
||
TERMIN
|
||
|
||
IFN $$RFN,[ ;Routines for reading filenames.
|
||
|
||
;Read a file spec off the b.p. in D into the file block that B points at.
|
||
;A filename block has four words, which get the device name, sname, fn1 and fn2.
|
||
;The terminating character is left in A.
|
||
;In E's left half we return flags indicating which of the four names were
|
||
;specified: 1,, for the device; 2,, for the FN1; 4,, for the FN2; 10,, for the SNAME.
|
||
|
||
RFN: PUSH P,B
|
||
PUSH P,C
|
||
MOVE C,B ;Put the filename block addr in C since RSIXG returns in B.
|
||
PUSH P,FN1(C) ;Save default FN1, FN2 for ^X, ^Y.
|
||
PUSH P,FN2(C)
|
||
SETZ E, ;Number of names stored yet is 0.
|
||
RFN0: PUSHJ P,RUC
|
||
RFN2: PUSHJ P,RSIXG ;Read one filename.
|
||
JRST RFN1
|
||
PUSHJ P,RFNN ;If it's not null, store it.
|
||
RFN1: CAIE A,": ;Check char that ended name,
|
||
CAIN A,";
|
||
JRST RFN0
|
||
CAIN A,40 ;If was space, : or ;, read another name.
|
||
JRST RFN0
|
||
IFN $$SWITCH,[
|
||
CAIN A,"/ ;If stopped on "/" or "(", call switch rtn.
|
||
JRST RFNSL ;Read 1 switch.
|
||
CAIN A,"(
|
||
JRST RFNPAR ;Read many switches until ).
|
||
];IFN $$SWITCH
|
||
CAIE A,^X
|
||
CAIN A,^Y ;If was ^X or ^Y,
|
||
JRST RFNX ;use the default FN1 or FN2 as next name.
|
||
SUB P,[2,,2]
|
||
POP P,C
|
||
POP P,B
|
||
POPJ P,
|
||
|
||
;STORE THE NAME IN B.
|
||
RFNN: CAIN A,":
|
||
JRST RFNC ;: => USE AS DEVICE.
|
||
CAIN A,";
|
||
JRST RFNS ;; => USE AS SNAME.
|
||
AOJA E,RFNT(E) ;ELSE USE AS NEXT NAME IN NORMAL SEQUENCE.
|
||
|
||
;Table for storing a name normally.
|
||
;N'th entry used for N'th name.
|
||
RFNT: JRST RFNF1 ;1st name, set FN1
|
||
JRST RFNF2 ;Second, set FN2.
|
||
JRST RFNC ;Third, set device.
|
||
JRST RFNS ;Fourth, set sname.
|
||
SOS E ;Fifth one, ignore, and don't let count advance past 5.
|
||
POPJ P, ;So this word isn't part of the dispatch.
|
||
|
||
IFN $$SWITCH,[ ;Code for processing switches, when a "/" or "(" is seen.
|
||
|
||
RFNPAR: PUSHJ P,RUC ;Get next char. Is it a ")"?
|
||
RFNPA1: CAIN A,")
|
||
JRST RFN0 ;Paren ends switches.
|
||
CAIE A,0
|
||
CAIN A,^M
|
||
JRST RFN1 ;CR ends spec even in switch list.
|
||
PUSHJ P,SWITCH ;Try to gobble the switch.
|
||
JRST RFNPAR ;Char in A used up, get another.
|
||
JRST RFNPA1 ;Char in A not part of switch; is it ")"?
|
||
|
||
RFNSL: PUSHJ P,RUC
|
||
CAIE A,0
|
||
CAIN A,^M ;/<CR> ENDS SPEC.
|
||
JRST RFN1
|
||
PUSHJ P,SWITCH ;Otherwise, process it as switch.
|
||
JRST RFN0 ;No skip => char in A was gobbled by switch.
|
||
JRST RFN2 ;Skip => let next RSIXG gobble the char now in A.
|
||
|
||
];IFN $$SWITCH
|
||
|
||
;Here to store the word in B as the SNAME.
|
||
RFNS: MOVEM B,SNM(C) ;Set the sname.
|
||
TLO E,1_SNM ;Say the sname has been specified in this filespec.
|
||
MOVSI B,'DSK ;Consider setting the device to DSK:
|
||
TLNN E,1_DEV ;If dev was just spec'd, don't override the spec'd one.
|
||
MOVEM B,DEV(C) ;It is a feature that this doesn't set 1_DEV,
|
||
POPJ P, ; it lets the user tell exactly what was given.
|
||
|
||
;Here to store the word in B as the device name.
|
||
RFNC: MOVEM B,DEV(C) ;Set the dev name,
|
||
TLO E,1_DEV ;and say the device name was explicitly specified.
|
||
POPJ P,
|
||
|
||
;Here to store the word in B as the FN1.
|
||
RFNF1: MOVEM B,FN1(C) ;Set the FN1, say was spec'd.
|
||
TLO E,1_FN1
|
||
POPJ P,
|
||
|
||
;Here to store the word in B as the FN2.
|
||
RFNF2: MOVEM B,FN2(C) ;Set the FN2, say was spec'd.
|
||
TLO E,1_FN2
|
||
POPJ P,
|
||
|
||
;Here to process a ^X or ^Y, by taking the stacked default FN1 or FN2 and using it as input.
|
||
RFNX: ADDI A,(P) ;POINT TO THE STACKED DEFAULT FN1 OR FN2
|
||
MOVE B,-^Y(A) ;AND GET IT.
|
||
PUSHJ P,RFNN ;STORE IT NORMALLY.
|
||
JRST RFN0 ;GET NEXT NAME.
|
||
|
||
;Subroutines for filename reading.
|
||
|
||
IFE $$RUC,[
|
||
;Read char into A from b.p. in D and convert to upper case.
|
||
;Filename reading does all its input via RUC.
|
||
;If $$RUC is set, we assume that the user has defined RUC,
|
||
;and call the user's definition.
|
||
RUC: ILDB A,D
|
||
CAIL A,140
|
||
SUBI A,40
|
||
POPJ P,
|
||
];IFE $$RUC
|
||
|
||
;Read SIXBIT word into B from b.p. in D, leaving terminating char in A.
|
||
;Expects first character in A already.
|
||
;Terminates on a Space or control character or Rubout.
|
||
;Skips if the word was non-null.
|
||
RSIX: PUSH P,C
|
||
MOVE C,[440640,,B] ;Extra bit in b.p. set says RSIX, not RSIXG.
|
||
JRST RSIXG1
|
||
|
||
;Similar but stop on :, ;, and any characters which RSIXTP skips for.
|
||
;We assume that the user has defined RSIXTP to accept a character in A
|
||
;and skip or not, clobbering no ACs.
|
||
RSIXG: PUSH P,C
|
||
MOVE C,[440600,,B] ;BP FOR STORING THE SIXBIT.
|
||
RSIXG1: SETZ B, ;NO CHARS SO .
|
||
RSIX0: CAIN A,^Q
|
||
JRST RSIX2 ;^Q QUOTES A CHAR WHICH WOULD TERMINATE.
|
||
CAIE A,177
|
||
CAIG A,40
|
||
JRST RSIX1 ;SPACE OR CTL CHAR => STOP.
|
||
TLNE C,40
|
||
JRST RSIX3 ;RSIX WAS CALLED, ALL OTHER CHARS NORMAL.
|
||
CAIE A,":
|
||
CAIN A,"; ;RSIXG, STOP ON : AND ;.
|
||
JRST RSIX1
|
||
PUSHJ P,RSIXTP
|
||
JRST RSIX3
|
||
RSIX1: SKIPL C ;TERMINATE: SKIP IF GOT >= 1 CHAR.
|
||
AOS -1(P)
|
||
POP P,C
|
||
POPJ P,
|
||
|
||
RSIX2: PUSHJ P,RUC ;^Q => READ THE QUOTED CHAR.
|
||
RSIX3: SUBI A,40 ;INSERT NORMAL CHAR IN THE 6BIT.
|
||
TLNE C,77^4 ;IGNORE CHARS AFTER THE FIRST 6.
|
||
IDPB A,C
|
||
PUSHJ P,RUC
|
||
JRST RSIX0
|
||
|
||
];IFN $$RFN
|
||
|
||
IFN $$PFN,[ ;Routines for printing filenames.
|
||
|
||
;Convert the filenames in the filename block which B points at
|
||
;to ASCII, depositing it down the b.p. in D, followed by a ^@
|
||
;which D is not advanced over.
|
||
;A filename block is four words containing the device, fn1, fn2 and sname.
|
||
|
||
;It is assumed that PSIXTP (PSIX-Terminator-P) is defined as a
|
||
;routine which, given a character in B, skips if a ^Q should be
|
||
;printed before that character. Space, colon and semicolon get ^Q'd
|
||
;in any case. Thus, you can usually make PSIXTP and RSIXTP the same.
|
||
|
||
;PFNMCH is the same as PFN except that if the device is DSK
|
||
;it prints the name of this machine (from MNAME) instead.
|
||
|
||
IFN $$MNAME,[
|
||
|
||
PFNMCH: PUSH P,A
|
||
PUSH P,C
|
||
MOVE C,DEV(B)
|
||
CAMN C,[SIXBIT/DSK/]
|
||
MOVE C,MNAME
|
||
JRST PFN1
|
||
]
|
||
|
||
PFN: PUSH P,A
|
||
PUSH P,C
|
||
MOVE C,DEV(B) ;Print device name, colon, and space.
|
||
PFN1: PUSHJ P,PSIXF
|
||
MOVEI A,":
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
MOVE C,SNM(B) ;Print sname, semicolon, and space.
|
||
PUSHJ P,PSIXF
|
||
MOVEI A,";
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
MOVE C,FN1(B) ;Print fn1 and space.
|
||
PUSHJ P,PSIXF
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
MOVE C,FN2(B) ;Print fn2.
|
||
PUSHJ P,PSIXF
|
||
SETZ A, ;Store terminating ^@ but don't advance D over it.
|
||
MOVE C,D
|
||
IDPB A,C
|
||
POP P,C
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
;Print SIXBIT word in C down b.p. in D,
|
||
;putting ^Q's before appropriate characters.
|
||
;Clobbers C.
|
||
PSIXF: LDB A,[360600,,C] ;Extract first character
|
||
LSH C,6 ;and flush it.
|
||
ADDI A,40
|
||
CAIE A,":
|
||
CAIN A,";
|
||
JRST PSIXF1
|
||
CAIN A,40
|
||
JRST PSIXF1
|
||
PUSHJ P,PSIXTP
|
||
JRST PSIXF2
|
||
PSIXF1: PUSH P,A
|
||
MOVEI A,^Q
|
||
IDPB A,D
|
||
POP P,A
|
||
PSIXF2: IDPB A,D
|
||
JUMPN C,PSIXF ;ALL THE REST BLANK => DONE.
|
||
POPJ P,
|
||
|
||
];IFN $$PFN
|
||
|
||
IFN $$PFNBRF,[ ;Routine to print filenames, as briefly as possible.
|
||
|
||
;PFNBRF is called like PFN, but it omits names which have their default values.
|
||
;It is assumed that MSNAME is defined to be the address of a word
|
||
;holding the "default" SNAME.
|
||
PFNBRF: PUSH P,A
|
||
PUSH P,C
|
||
MOVE C,DEV(B) ;Print device name, colon, and space.
|
||
IFN $$MNAME,CAME C,MNAME
|
||
CAMN C,[SIXBIT /DSK/]
|
||
JRST PFNBR1
|
||
JUMPE C,PFNBR1
|
||
PUSHJ P,PSIXF
|
||
MOVEI A,":
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
PFNBR1: SKIPE C,SNM(B) ;Print sname, semicolon, and space.
|
||
CAMN C,MSNAME
|
||
JRST PFNBR2
|
||
PUSHJ P,PSIXF
|
||
MOVEI A,";
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
PFNBR2: MOVE C,FN1(B) ;Print fn1 and space.
|
||
PUSHJ P,PSIXF
|
||
SKIPN FN2(B)
|
||
JRST PFNBR3
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
MOVE C,FN2(B) ;Print fn2.
|
||
PUSHJ P,PSIXF
|
||
PFNBR3: SETZ A, ;Store terminating ^@ but don't advance D over it.
|
||
MOVE C,D
|
||
IDPB A,C
|
||
POP P,C
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
];IFN $$PFNBRF
|
||
|
||
IFN $$PFND,[ ;Routine to print filenames, omitting true defaults.
|
||
|
||
;PFND is called like PFN, but it omits the device if it is "DSK" and the
|
||
; fn2 if it is ">".
|
||
PFND: PUSH P,A
|
||
PUSH P,C
|
||
SKIPE C,DEV(B) ;Print device name, colon, and space.
|
||
CAMN C,[SIXBIT /DSK/]
|
||
JRST PFND1
|
||
PUSHJ P,PSIXF
|
||
MOVEI A,":
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
PFND1: SKIPN C,SNM(B) ;Print sname, semicolon, and space.
|
||
JRST PFND2
|
||
PUSHJ P,PSIXF
|
||
MOVEI A,";
|
||
IDPB A,D
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
PFND2: MOVE C,FN1(B) ;Print fn1.
|
||
PUSHJ P,PSIXF
|
||
SKIPE C,FN2(B) ;Print space, fn2.
|
||
CAMN C,[SIXBIT />/]
|
||
JRST PFND3
|
||
MOVEI A,40
|
||
IDPB A,D
|
||
PUSHJ P,PSIXF
|
||
PFND3: SETZ A, ;Store terminating ^@ but don't advance D over it.
|
||
MOVE C,D
|
||
IDPB A,C
|
||
POP P,C
|
||
POP P,A
|
||
POPJ P,
|
||
|
||
];IFN $$PFND
|
||
|
||
IFN $$MNAME,[ ;Routine to initialize MNAME.
|
||
|
||
RMNAME: SYSCAL SSTATU,[REPEAT 6,[? %CLOUT,,MNAME]]
|
||
.LOSE %LSSYS
|
||
POPJ P,
|
||
|
||
];IFN $$MNAME
|
||
|
||
.END RFN
|