dml@loral.UUCP (Dave Lewis) (09/10/86)
Long and long ago, Jim OMura of Toronto (You listening?) lamented the fact
that the OS-9 Dir utility neglected to print the current date in its header.
Some time after that, an 80-column Dir program from S.B. Goldberg appeared in
the Rainbow and I modified it to print the date and posted it here. Some bugs
appeared ("dir e x" didn't always work right) and the thing was FIXED at 80
columns. Then, OS-9 V2 came out, with its 32/80 column dir which STILL didn't
put the date in the header.
I pitched all the previous stuff and started hacking, and the end result is
presented here for your pleasure. It displays directories in 32, 51 and 80
column formats, prints the date in the header, accepts multiple arguments so
you can print out five or six directories in one run of the program, ALWAYS
finds the right drive when `e' is selected, and the "date last modified" is
arranged in the normal mm/dd/yy format instead of yy/mm/dd.
One problem: although it automatically selects between 32 and 80 columns on
OS-9 V2, it won't select 51 cols. for FHL's O-Pak. A debugging session reveals
that even when O-Pak is running and the /Term descriptor has been patched to
51 columns, the Get Status SS.SCSZ (screen size) call still returns 32 columns
which it's NOT supposed to do! If someone can find a solution to that problem
the Dir program will work fine. Until then, you can set the WIDESIZE EQUate
to 51 and use "dir w" for 51 columns.
Another puzzling thing -- under V2, O-Pak's cursor goes away after I set the
time. Where does it go? I put CCIO, CO32, GRFO, HIRES and STDCS in OS9Boot,
and put HIRES and TMODE .1 -upc pag=24 in the Startup file.
*****************************************************************
*
* Dir -- directory display utility for OS-9 Version 1 or 2.
* Automatically selects correct display mode for screen width
* under Version 2. Prints date in header and will display
* multiple directories.
*
* Dir [e] [x] [d] [w] [directory] [directory]...
*
* e -- displays data from file descriptor including size,
* LSN of file descriptor, attributes, date last modified
* x -- displays current execution directory
* d -- displays file size in decimal (default is hex)
* w -- forces wide-screen mode. Most useful under Version 1
* which lacks the screen size status call
*
* If you want to display either the current working directory
* or the execution directory AND any other directory, you must
* put a `.' in the command line at the appropriate position. If
* you want to display both the working and execution
* directories you must put a `.' for the working directory,
* then the `x' option, then a `.' for the execution directory.
*
*****************************************************************
*
* Copyright 1986 by Dave Lewis
* 4417 Idaho apt. 4
* San Diego CA 92116
*
NAM Dir
TTL Directory listing utility
*
IFP1
USE /D0/DEFS/OS9Defs
USE /D0/DEFS/RBFDefs
USE /D0/DEFS/SCFDefs
ENDC
*
DEFAULT EQU 32 Default screen width for V.1
WIDESIZE EQU 80 Size for `W' option
BREAKYR EQU 70 Switch year from 19XX to 20XX
*
MOD SIZE,NAME,$11,$81,EXEC,STORG
NAME FCS 'Dir'
FCB $06 Version byte
*
PATHLIST RMB 2 Current parameter position
EFLAG RMB 1 Dir `e' flag
XFLAG RMB 1 Dir `x' flag
NOTFIRST RMB 1 Zero on first directory
SCREENSZ RMB 1 Width of screen in columns
SCRWIDTH RMB 1 Screen width flag
COLWIDTH RMB 1 Width of a column
COLUMNS RMB 1 Columns used so far
SIZEBASE RMB 1 Numeric base for file size
NUMBASE RMB 1 Numeric base for output
DIRPATH RMB 1 Directory path number
ATPATH RMB 1 /Dn@ path number
SCRATCH RMB 12 For numeric conversion
FILENAME RMB 29 File name and sector number
FDS.LSN RMB 3 File descriptor sector #
FILEDATA RMB 32 Stuff from file descriptor
LINEBUF RMB 120 Output line buffer
RMB 200 Stack space
RMB 100 Parameter area
STORG EQU . Total storage required
*
HEADER1 FCB C$LF
FCS 'Directory of '
MONTHS FCB 13,20,28,33,38,41
FCB 45,49,55,64,71,79
FCS 'January'
FCS 'February'
FCS 'March'
FCS 'April'
FCS 'May'
FCS 'June'
FCS 'July'
FCS 'August'
FCS 'September'
FCS 'October'
FCS 'November'
FCS 'December'
*
HEADER2 FCS 'O'
FCB $86
FCS 'wn'
FCB $42
FCS 'er Last modified Attrib'
FCB $84
FCS 'utes Sect'
FCB $C3
FCS 'or '
FCB $81
FCS ' Size '
FCB $81
FCC ' Filename'
FCB C$LF
FCS '-------------------------------'
FCB $5E
FCS '----------------'
FCB $8D
FCC '-------------'
FCB $8D,0
*
DOT FCC '.'
FCB C$CR
*
* Find options and do appropriate stuff
*
DECSIZE LDA #10 Set file size display base
STA SIZEBASE to decimal
FINDARGS LDD ,X+ Get next command line char.
CMPA #C$SPAC Test for space
BEQ FINDARGS Keep looking if so
CMPA #'- Test for minus
BEQ FINDARGS Keep looking if so
CMPA #C$COMA Test for comma
BEQ FINDARGS Keep looking if so
CMPA #'. Test for "." (current dir)
BEQ FINDARG3 Go open path if so
CMPA #C$CR Test for end of command line
BNE FINDARG2 Continue if not
LEAX <DOT,PCR Point to `.' (current dir)
CLRB Might exit, ensure no error
TST NOTFIRST Is this the first directory?
BNE FA.EXIT If not, exit the process
RTS
*
FINDARG2 CMPB #'0 First character in a name?
BLO FINDARG4 If not, must be an argument
FINDARG3 LEAX -1,X Point back to the character
RTS
*
FINDARG4 ANDA #$5F Convert lower case to upper
CMPA #'E Is it an `E'?
BNE NOT.E Continue if not
STA EFLAG Set the `E' flag
BRA FINDARGS Look for more arguments
*
NOT.E CMPA #'X Is it an `X'?
BNE NOT.X Continue if not
LDA #EXEC. Set execute bit in `X' flag
STA XFLAG
BRA FINDARGS Look for more arguments
*
NOT.X CMPA #'W Is it a `W'?
BNE NOT.W Continue if not
LDB #WIDESIZE Force wide screen
BSR SETSIZE Reset screen size
BRA FINDARGS Look for more arguments
*
NOT.W CMPA #'D Is it a `D'?
BEQ DECSIZE Set size to decimal if so
*
LEAX <ERRSTRN,PCR Point to error string
LDA #2 Standard error path
LDY #30 Max characters to write
OS9 I$WRITLN Write error message
FA.EXIT LBRA MAINEXIT Quit the process
*
ERRSTRN FCC 'Dir: ERROR -- bad option'
FCB C$CR
*
SETSIZE LDA #8 Set up initial value
STB SCREENSZ Store raw screen size
CMPB #70 Test for 70+ columns
BHS SETSIZE2 Set screen values if so
RORA Shift A right, 1 -> bit 7
CMPB #50 Test for 50 -> 69 columns
BHS SETSIZE2 Set screen values if true
LSRA Shift A right again (now $42)
SETSIZE2 TFR A,B Copy value in A
ANDA #$F0 Mask off width flag
ANDB #$F Mask off column width offset
ADDB #8 Convert to column width
STD SCRWIDTH Set both variables
RTS
*
* Initialization routines - set up variables, establish
* screen size, etc.
*
EXEC STX PATHLIST Save X register
CLRA Set everything up for default
CLRB conditions
STD EFLAG CLear `e' and `x' flags
STD NOTFIRST Clear init flag
LDD #$100A Hex size, all else decimal
STD SIZEBASE Initialize base variables
LDD #$126 Stdout, SS.SCSIZ codes
OS9 I$GETSTT Get screen size
TFR X,D Put screen width in D
BCC EXEC.2 Continue if no error
CMPB #E$UNKSVC Version 1 won't recognize
BEQ V1DFAULT the call so default to 32
COMA Set carry for error
LBRA MAINEXIT Quit with error
V1DFAULT LDB #DEFAULT Set Version 1 default size
EXEC.2 BSR SETSIZE Set up screen size variables
*
DIRLOOP LDX PATHLIST Get parameter pointer
LBSR FINDARGS Process options
*
PSHS X Save start of path
LDA #DIR.+READ. Set access mode
LDB #'. If it points to `.' (current
CMPB ,X directory), add in the `x'
BNE NOTDOT flag for the execution
ADDA XFLAG directory (if set)
NOTDOT OS9 I$OPEN Open the directory
LBCS MAINEXIT Quit if error
STA DIRPATH Store path number
STX PATHLIST Store current position
*
LBSR CLEARBUF Clear output line buffer
LEAX HEADER1,PCR Point to start of header
LBSR MOVE.PL Move it into buffer
LDD PATHLIST Get end of pathlist
SUBD ,S Find length of pathlist
PULS X Retrieve path pointer
LBSR MOVE.$B Move it to buffer
*
LEAY 4,Y Put four spaces after the path
TST SCRWIDTH Check screen size
BEQ ONELINE Skip next if 70 col. or more
LEAY -4,Y Back over the spaces
LDB #C$LF Put a line feed ahead of
STB ,Y+ the date/time display
*
ONELINE LEAX FILEDATA,U Point to a buffer
OS9 F$TIME Get current date and time
LBCS MAINEXIT Quit if error
LDA 1,X Get month
LEAX MONTHS-1,PCR Point to month name list
LDA A,X Get offset for current month
LEAX A,X Index into name list
LBSR MOVE.PL Move it to line buffer
LEAY 1,Y Put a space after month name
LDB FILEDATA+2 Get day
CLRA Make it a 16-bit number
LBSR LEFTJUST Print in decimal, left just.
LDA #C$COMA Put a comma and a space
STA ,Y++ after the day
LDB FILEDATA Get year
CLRA Zero upper half of D
CMPB #BREAKYR Test for 19xx or 20xx year
BHI NINETEEN If last two digits of year
ADDB #100 are higher than break point
NINETEEN ADDD #1900 year is 19xx; if not, 20xx
LBSR LEFTJUST Write out the year
LEAY 2,Y Put two spaces after the year
*
LEAX FILEDATA+3,U Point to hour
LBSR WRITIME Write current time to buffer
LDA #C$LF Leave a blank line
STA ,Y+
BSR WRITBUFR Write out the buffer contents
INC NOTFIRST Next directory won't be #1
CLR COLUMNS Indicate empty buffer
BSR READNAME Read and discard the `.' and
BSR READNAME `..' entries in directory
TST EFLAG Was `e' option selected?
LBNE DIREHDR Start Dir `e' display
*
* Get next file name and count characters
*
DIRCOL.1 BSR READNAME Get next file name
BCC DIRCOL.2 No error, continue
TST COLUMNS End of file error, check buf
BEQ DIRLP.LB Do next directory
BSR WRITBUFR Write buffer if not empty
DIRLP.LB LBRA DIRLOOP Go do next directory
*
DIRCOL.2 LDB #$FF Start short to test byte 0
FINDLEN INCB Count one character
TST B,X Test next char. for end
BPL FINDLEN Not end, keep counting
ANDB #$1F Illegal over 32 characters
INCB Convert int to natural
ADDB COLUMNS Add name to current column
CMPB SCREENSZ Compare to screen width
BLO NONEWLIN Same line if there's room
BSR WRITBUFR Write out current line
CLR COLUMNS Indicate empty buffer
LEAX FILENAME,U Restore pointer to filename
BRA DIRCOL.2 New line, same filename
*
NONEWLIN INCB Count one beyond filename
STB COLUMNS Save new line size
BSR MOVE.PL Move filename into buffer
CLRA Start at zero
NEXTCOL ADDA COLWIDTH Point to start of next
CMPA COLUMNS display column, leaving at
BLS NEXTCOL least two spaces after name
*
TFR A,B Copy new column number
INCB Compensate for previous INC
SUBB COLUMNS Find offset to new position
STA COLUMNS Store new line length
CMPA SCREENSZ Compare to screen width
BHS DIRCOL.1 Don't move Y past end of line
LEAY B,Y Reposition Y if there's room
BRA DIRCOL.1 Get next file name
*
READNAME PSHS Y Save buffer pointer
READNM.2 LDY #32 Size of one directory entry
LEAX FILENAME,U Point to filename buffer
LDA DIRPATH Get directory path number
OS9 I$READ Read the next name
BCS READNM.3 Test for end-of-file error
TST ,X Not a valid file if the first
BEQ READNM.2 byte is a null
PULS Y,PC Pull and return
*
READNM.3 CMPB #E$EOF Test for end of file
BNE MAINEXIT Quit if another error
LDA DIRPATH Close directory path
OS9 I$CLOSE
BCS MAINEXIT Quit if error
COMA Set carry flag
PULS Y,PC Pull and return
*
MAINEXIT OS9 F$EXIT
*
WRITBUFR LDA #C$CR Terminate the line
STA ,Y+
LEAX LINEBUF,U Point to line buffer
LDY #120 Maximum bytes to write
LDA #1 Standard output path
OS9 I$WRITLN Write out a line
BCS MAINEXIT Quit if error
*
CLEARBUF LEAY LINEBUF,U Point to start of line buffer
LDD #$2077 Space in A, 119 in B
CLRBUF.2 STA B,Y Store it in buffer
DECB Count off one
BPL CLRBUF.2 Repeat until all bytes done
RTS
*
MOVE.PL LDA ,X+ Get next character
STA ,Y+ Store in line buffer
BPL MOVE.PL Repeat if bit 7 not set
ANDA #$7F Mask off bit 7
STA -1,Y Fix last character
RTS
*
MOVE.$B LDA ,X+ Get next character
STA ,Y+ Store in line buffer
DECB Count off one character
BNE MOVE.$B Repeat if not done
RTS
*
LEFTJUST PSHS X Save X register
BSR LEFTJUSX Go write out number
PULS X,PC Pull and return
*
LEFTJUSX LEAX FILENAME,U Point to 12 free bytes
LEFTJUS2 BSR DIVIDE Convert one digit
STD -2,S Test D by storing it
BEQ LEFTJUS3 Done if D is zero
BSR LEFTJUS2 Convert next digit
LEFTJUS3 LDA ,X+ Get latest digit from scratch
STA ,Y+ Store it in the write buffer
RTS
*
WRITIME BSR LEADZERO Write first part of date
BSR WRITIME2 Write colon and second part
WRITIME2 LDB #': Load colon
STB ,Y+ Store in buffer
*
LEADZERO LDD #$3030 Two zeros
STD ,Y++ Store in buffer
LDB ,X+ Get next object
ONEBYRTJ CLRA Zero upper half of D
*
RIGHTJUS PSHS Y,X Save X and Y
LEAX FILENAME,U Point to 12 free bytes
RIGHTJU2 BSR DIVIDE Convert one digit
PSHS D Save intermediate result
LDA ,X+ Get converted digit
STA ,-Y Store in write buffer
LDD ,S++ Retrieve and test D
BNE RIGHTJU2 Repeat if not zero
PULS X,Y,PC Restore registers and return
*
DIVIDE PSHS D Save the number
CLRA Zero upper 8 bits
LDB #9 Initialize shift counter
STD ,--X Set up counter, divisor LSB
LDB NUMBASE Get conversion base
STD ,--X Divisor MSB, quotient LSB
STA ,-X Initialize quotient MSB
PULS D Retrieve the number
*
DIVIDE2 CMPD 2,X Compare number to divisor
BLS DIVIDE3 Start dividing if <= divisor
INC 4,X Add one to shift counter
LSL 2,X Shift divisor left one bit
BCC DIVIDE2 Test again if divisor intact
ROR 2,X If divisor lost a 1, restore
DEC 4,X it and start dividing
*
DIVIDE3 LSL 1,X Shift quotient left one bit,
ROL ,X multiplying it by 2
CMPD 2,X Compare number to divisor
BLO DIVIDE4 If smaller, do nothing
SUBD 2,X Subtract divisor from number
INC 1,X Add one to quotient
DIVIDE4 LSR 2,X Shift divisor right one bit,
ROR 3,X dividing it by 2
DEC 4,X Count off one shift
BNE DIVIDE3 Repeat until shift count = 0
*
TFR B,A Move remainder to A
ADDA #$90 Convert binary number in A
DAA to an ASCII character
ADCA #$40 representing a digit
DAA
STA 4,X Put it `under' other stuff
LDD ,X Retrieve the quotient
LEAX 4,X Adjust X - now points just
RTS above the remainder digit
*
DIREHDR LEAX HEADER2,PCR Point to subheader
TST SCRWIDTH Start with a space if screen
BPL WRITHEAD is 50 to 69 columns wide
LEAY 1,Y Leave a space
WRITHEAD LBSR MOVE.PL Write out next header section
LDB ,X+ Get the format control byte
BITB SCRWIDTH Test vs. current screen width
BEQ WRITHD2 Continue if no match
ANDB #$3F Mask off screen size flags
LEAX B,X Add displacement to X
WRITHD2 TSTB If displacement was not zero,
BNE WRITHEAD continue storing the header
TST SCRWIDTH If the screen is 32 columns,
BLE WRITHD3 (not zero or negative)
LDB #C$LF insert a line feed
STB LINEBUF+30 after the Attributes column
WRITHD3 LBSR WRITBUFR Write out the completed line
*
LEAX FILEDATA,U Point to a buffer
LDA DIRPATH Get directory path number
CLRB Code for SS.OPT is 0
OS9 I$GETSTT Get options from PD
LBCS MAINEXIT Quit if error
LDA 1,X Get drive number
ADDA #'0 Convert to ASCII
STA 2,X Put in correct position
LDD #$2F44 Start with "/D"
STD ,X Store ahead of drive number
LDD #$400D Append "@" and CR to
STD 3,x drive designator
LDA #READ. Access mode is Read
OS9 I$OPEN Open the entire disk
LBCS MAINEXIT Quit if error
STA ATPATH Save /Dn@ path number
*
* Write out file data in `e' format
*
DIRE.WRT LBSR READNAME Read next filename
BCC DIREWR.2 Continue if not end of file
LDA ATPATH Get /Dn@ path number
OS9 I$CLOSE Close the disk
LBCS MAINEXIT Quit if error
LBRA DIRLOOP Go do next directory
*
DIREWR.2 LEAX FILEDATA,U Point to file data buffer
PSHS U,Y,X Save registers
LDX FDS.LSN Get MSW of sector number
LDA FDS.LSN+2 Get LSB of sector number
CLRB Convert sectors to bytes
TFR D,U Put in right register
LDA ATPATH Get /Dn@ path number
OS9 I$SEEK Position file pointer
LBCS MAINEXIT Exit if error
LEAX <POS.TBL,PCR Point to positioning data
STX COLWIDTH Don't need these 2 vars
PULS X Retrieve pointer to data buffer
LDY #32 Prepare to read 32 bytes
OS9 I$READ Read it
LBCS MAINEXIT Exit if error
PULS Y,U Restore registers
BSR POSITION Position Y register
LDB FILEDATA+FD.OWN Get file owner number
LBSR ONEBYRTJ Print 1 byte right-justified
*
* Write date and time last modified
*
BSR POSITION Adjust write pointer
LEAX FD.DAT,X Point to last-modified date
LDD ,X Rearrange date last modified
STB ,X from year/month/day to
LDB 2,X month/day/year
STA 2,X
STB 1,X
LBSR LEADZERO Display month with leading 0
BSR WRTDATE Display /day/year same way
LEAY 1,Y Put a space after the date
LBSR LEADZERO Write out the hour
LBSR LEADZERO Write out the minute
*
* Write out file attributes
*
BSR POSITION Adjust write pointer
LEAX <ATTRIBS,PCR Point to attribute display
LDB FILEDATA+FD.ATT Get file attributes
BRA WRDATA.2 Jump into the loop
*
POS.TBL FCB $23,3 Owner number
FCB $12,4 Date/time last modified
FCB $13,3 File attributes
FCB $44,8 Sector number
FCB $67,8 Size of file
FCB $12,2 Filename
*
ATTRIBS FCC 'dsewrewr' File attribute codes
FCB 0 Null to terminate
*
* Position Y register to write next object
*
POSITION PSHS X,D Save registers
LDX COLWIDTH Point to current entry
LDB 1,X Get offset for 70+ columns
LDA SCRWIDTH Load and test SCRWIDTH flag
BEQ POSITN.2 Set position if 70 or more
LDB ,X Get byte for other sizes
TSTA Check width again
BPL POSITN.2 Set it if less than 50 col.
LSRB If 51-69 columns shift offset
LSRB value into lower 4 bits
LSRB where it can be used
LSRB
POSITN.2 ANDB #$F Mask off upper four bits
LEAX 2,X Point to next table entry
STX COLWIDTH Store updated pointer
LEAY B,Y Move write pointer
PULS D,X,PC Pull and return
*
WRTDATE BSR WRTDATE2 Do it twice
WRTDATE2 LDB #'/ Put a '/' between entries
STB ,Y+
LBRA LEADZERO Write out next object
*
WRTATTR LSLB Shift out the next bit
BCS ATBITSET Write the letter if it was 1
LDA #'- Write a dash if it was a 0
ATBITSET STA ,Y+ Write the selected character
WRDATA.2 LDA ,X+ Load the next attribute code
BNE WRTATTR Repeat if not a null
*
TST SCRWIDTH Check screen width
BLE NOT32COL Skip next if 50+ columns
LDB #C$LF Insert a line feed
STB ,Y+
NOT32COL BSR POSITION Move Y register into place
LDA #16 Print sector number in hex
STA NUMBASE
LDD FDS.LSN+1 Get sector number
LBSR RIGHTJUS Write it out, right justified
LDA SIZEBASE Get base for file size
STA NUMBASE Store as output base
BSR POSITION Adjust write pointer
LDD FILEDATA+FD.SIZ Test MSW of file size
BNE K.BYTE Display Kbytes if nonzero
LDD FILEDATA+FD.SIZ+2 Get LSW of file size
LBSR RIGHTJUS Print out file size
SIZEDONE LDA #10 Restore decimal output base
STA NUMBASE
BSR POSITION Adjust write pointer
LEAX FILENAME,U Point to file name
LBSR MOVE.PL Move until bit 7 set
LBSR WRITBUFR Write out the buffer
LBRA DIRE.WRT Go do next file
*
K.BYTE LDA #'K Load a K
STA ,-Y Put it in the buffer
LEAY -1,Y Leave a space before it
LDD FILEDATA+FD.SIZ+1 Load center 2 bytes of file size
LSR FILEDATA+FD.SIZ Shift out the last
RORA two bits representing 1023
RORB and shift in two higher
LSR FILEDATA+FD.SIZ bits
RORA
RORB
ADDD #1 Add one Kbyte for the unused bits
LBSR RIGHTJUS Print out number of Kbytes
LEAY 2,Y Put Y back where it belongs
BRA SIZEDONE Re-join the main program
*
EMOD CRC bytes
SIZE EQU *
END
-------------------------------
Dave Lewis Loral Instrumentation San Diego
hp-sdd --\ ihnp4 --\
sdcrdcf --\ bang --\ kontron -\
csndvax ---\ calmasd -->-->!crash --\
celerity --->------->!sdcsvax!sdcc3 --->--->!loral!dml (uucp)
dcdwest ---/ gould9 --/
Nobody can fix the economy..nobody can be trusted..nobody's perfect..vote
for nobody!
-------------------------------