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! -------------------------------