;Multi-column directory program by Joshua Brodsky ;Completed 12/30/80 as a gift to Mr. George Glenn. Final version 4.25. ;Revised 12/4/81 for submission to DECUS. TITLE DIREC - Multi-column directory lister. SEARCH MONSYM,MACSYM ;This program is capable of printing any number of columns per listing ;From 2 up. 5 columns work best on 80-column terminals, but if you ;use a 132 column terminal, 8 columns will fit. COLUMN==5 ;Columns per listing. ;Define accumulator names: A==1 ;Multi-purpose AC's. B==2 FLAGS==3 ;Flags for JFNS here. INDEX==16 LINE==5 ;Line number variable. T1==6 ;Temporary storage. T2==7 T3==10 FILES==11 ;Count of files printed. TABS==12 ;Count of tabs. GENER==13 ;Number of generations. ;Gener is used to calculate how many files were printed, and did not ;have their own line. NUL==14 ;Blank used as a null. ;AC's 15 and 16 are not used. P==17 ;Stack pointer. START: RESET ;Reset all RSCAN JRST ERROR CAIL 1,7 JRST READ MOVEI 1,.PRIIN CFIBF MOVE A,[GJ%OLD+GJ%IFG+GJ%FLG+GJ%SHT] ;Flags,short,wildcards MOVE B,[POINT 7,FILE] ;Default specification JRST GET ;Go join read for GTJFN READ: REPEAT 6, READ2: MOVEI A,GTBLK SETZ B, GET: GTJFN ;Join default to GTJFN JRST ERROR ;Error address MOVE INDEX,A ;Save flags for GNJFN MOVEI 1,-1 RFCOC TXO 2,1B34 TXZ 2,1B35 TXO 3,1B2 TXZ 3,1B3+1B8+1B9 SFCOC MOVEI 1,.PRIIN BKJFN JRST ERROR PBIN CAIE 1,"/" JRST ..REC MOVEI 1,^D17 PBOUT SETOM PRINTR ..REC: SETZ LINE, SETZ FILES, SETZ TABS, SETZ GENER, SETZ NUL, MOVE P,[IOWD ^D1000,POINTR] ;Set up stack pointer PUSH P,NUL ;Start with a NULL ;This section prints the structure and directory. It can be deleted ;without affecting the rest of the program. HRROI A,[ASCIZ/ /] PSOUT ;Indent for directory MOVEI A,.PRIOU ;Set up JFNS HRRZ B,INDEX ;Clear flags from JFN MOVE FLAGS,[1B2+1B5+JS%PAF] ;Output only directory JFNS ;Print it. HRROI A,[ASCIZ/ /] ;New line PSOUT ;Output it. SETUP: MOVE A,[POINT 7,BUFF] ;Set up buffer pointer HRRZ B,INDEX ;Clear flags from JFN ;A 6 is put in the left half of AC2 to fool the main loop into ;printing the full name on the first file. HLL B,[6,,0] ;And put 6 instead ;Main loop. Here the file names and their pointers are saved. LOOP: TXNN B,GN%NAM+GN%EXT+GN%DIR+GN%STR JRST GEN TXNN B,GN%NAM+GN%DIR+GN%STR JRST EXT TXNE B,GN%DIR+GN%STR JRST [SETOM .REC JRST OK] NAME: MOVE FLAGS,[1B8+1B11+1B14+JS%PAF] ;Name changed. Give all IDPB NUL,A ;Null byte for printing PUSH P,A ;Save current pointer JRST JFNS1 ;Put name in buffer EXT: MOVE FLAGS,[1B11+1B14+JS%PAF] ;Extension+gen only IDPB NUL,A ;Null byte for printing PUSH P,A ;Save pointer MOVEI NUL,^D32 ;Indent for EXT IDPB NUL,A ;(Save two spaces) IDPB NUL,A SETZ NUL, ;Reset NUL for later JRST JFNS1 ;and print. GEN: MOVE FLAGS,[1B14] ;Generation only MOVEI NUL,^D44 ;Put a comma IDPB NUL,A ;in the buffer SETZ NUL, ;Reset NUL for later ADDI GENER,1 ;Add file #, not line # JFNS1: JFNS ;Store name in buffer MOVE T1,A ;Save a in T1 MOVE A,INDEX ;Get index handle ADDI LINE,1 ;Update line # GNJFN ;Get next JFN JRST OK ;End of files? MOVE B,A ;Put JFN+FLAGS in AC2 MOVE A,T1 ;Restore a JRST LOOP ;and loop back. ;This section makes final adjustments before printing. ;Now that the main loop is over, AC14 (NUL) is used as a temporary AC. OK: MOVE T2,LINE ;Save line in T2 SUB LINE,GENER ;Subtract # of GENS IDIVI LINE,COLUMN ;Divide by # of columns ;You may recall about IDIV that if there is a remainder, it is put in ;the next accumulator after the one being divided. SKIPE T1 ;If even division, skip ADDI LINE,1 ;Otherwise, add 1 to 7 REPEAT COLUMN, ;This section prints the files from the buffer according to the ;pointers, which are taken according to the number of columns. PRINT: ADDI FILES,1 ;Add 1 to files. CAMLE FILES,LINE ;Printed all files? JRST DONE ;Yes. Done. MOVE B,POINTR(FILES) ;Take pointer @FILES MOVEI A,.PRIOU MOVEI 3,^D15 ;Max 15 characters SETZ 4, SOUT ;And print that name CAIL 3,^D7 ;Too few chars? JSR FRETAB ;Print an extra tab JSR TAB ;Print a TAB or CR. MOVE T3,FILES ;Save files. Use T3 MOVEI NUL,2 ;Set NUL to 2 ;This is part of the print loop which controls the number of columns. LOOPA: ADD T3,LINE ;Add number of lines MOVE B,POINTR(T3) ;and get that pointer. JUMPE B,PRINTX ;If NUL, recycle. MOVEI A,.PRIOU MOVEI 3,^D15 SETZ 4, SOUT ;Print name. CAIL 3,^D7 ;Too few chars JSR FRETAB ;Print extra tab. JSR TAB ;TAB or CR. ADDI NUL,1 ;Add 1 to NUL CAIG NUL,COLUMN ;More than columns? JRST LOOPA ;No, go back. JRST PRINT ;Yes. Goto main loop ;Eventually, if the number of files is not divisible by the number ;of columns, the last column will have a few blank lines at the end. ;This will prevent the program from printing random characters there. PRINTX: MOVEI TABS,COLUMN-1 ;Equivelnt of CR. JSR TAB JRST PRINT ;And go back to loop ;This subroutine keeps track of the tabulation between file names. TAB: Z ;Address to store PC ADDI TABS,1 ;Add one to TAB count CAIL TABS,COLUMN ; < than # of columns? JRST RET ;No, print CR MOVEI A,^D9 ;Yes, print TAB PBOUT JRST @TAB ;And return. RET: MOVEI A,^D13 ;Print CR and PBOUT MOVEI A,^D10 ;Linefeed. PBOUT SETZ TABS, ;Reset TAB count JRST @TAB ;And return. ;FRETAB prints a tab unaccounted for by TAB: (used for files too short). FRETAB: Z MOVEI 1,^D9 PBOUT JRST @FRETAB ;This section completes the program and prints the number of files. DONE: MOVEI TABS,COLUMN-1 ;Equivelent of CR JSR TAB TMSG < TOTAL NUMBER OF FILES IS > MOVEI A,.PRIOU ;Output number to TTY MOVEI FLAGS,^D10 ;With a RADIX of 10 MOVE B,T2 ;Retrieve number files NOUT ;Output number JRST ERROR ;Error address TMSG < > MOVE 1,.REC JUMPN 1,[SETZM .REC TMSG < > JRST ..REC] MOVEI 1,-1 SIBE JRST [ CAIL 2,3 JRST READ2 MOVEI 1,-1 CFIBF JRST DONE2] DONE2: MOVE 1,PRINTR JUMPE 1,DONE3 MOVEI 1,^D19 PBOUT DONE3: HALTF ;Stop. Done! JRST DONE3 JRST DONE3 ERROR: HRROI 1,ERRSTR MOVE B,[.FHSLF,,-1] ;Most recent error SETZ FLAGS, ;No limit of letters ERSTR ;Print error JFCL ;Ignore errors JFCL HRROI 1,ERRSTR ESOUT HALTF ;Stop. JRST START ;Restart address ERRSTR: BLOCK 10 BUFF: BLOCK ^D10000 ;Storage for file names POINTR: BLOCK ^D1000 ;Storage for pointers .REC: Z ;This contains the default file specification to be used when none is ;typed in after the command (put in the RSCAN buffer). ;It can be changed without any other modification. Right now it is *.*.* . FILE: ASCIZ/*.*.*/ ;Default specification PRINTR: Z GTBLK: GJ%OLD+GJ%IFG+.GJALL .PRIIN,,.PRIOU BLOCK 2 POINT 7,[ASCIZ/*/] POINT 7,[ASCIZ/*/] BLOCK 4 END START ;End.