.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 ;/ 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