dml@loral.UUCP (11/18/86)
This one fixes something that's bothered me for a long time. Whenever you make a directory, OS-9 allocates it 8 sectors, which is enough space for 62 entries. Most of the time this is a waste; a lot of directories never get more than 10 or 12 entries. Two sectors would be plenty of room. Then again, sometimes it's not enough. My main system disk has 87 entries in its CMDS directory now, and I keep writing more. I mentioned this to Jim Omura a while ago and he said he always wanted a Makdir that would automatically put the directory name in uppercase. That sounded like a good idea, so I incorporated that into this program too. The Root directory looked like it would be a problem, since Format puts that on, but it turned out to be simple -- just skip the code that creates the directory. This program DOES NOT fix, or set, directory size. It merely changes how many sectors are allocated for the directory's first segment. If you put in more entries than will fit in the first segment, OS-9 will still allocate more storage for them. However, if there are no free sectors adjacent to the initial segment, your directory will become fragmented, just like it would before if you put in 63 or more entries. Also, pay heed to the warnings in the program header. If you deallocate a sector that contains active directory entries, OS-9 can and probably will write over them. The next time you try to use those files, anything could happen. It won't let you set the size to zero sectors. There's also a good general-purpose numeric input routine built into the program. It's hard-coded for decimal input here, but it's easy to change. Just make a variable and store your base in it, and change the two LDA #10 instructions to LDA NUMBASE. To process hex base (or larger), make all a-z uppercase, SUBB #7, go to NOTNUMBR if the result is < $A, and compare the number to NUMBASE. If >= NUMBASE, it's NOTNUMBR. The routine works like this: Entry conditions: X --> first character of numeric string ("-->" means "points to") Exit conditions : X --> first unconvertable character D = 16-bit converted number Error conditions: CCR carry bit set if first character is not valid It's recursive so give it some leeway on the stack. It only needs two bytes per loop, though - it carries the interim sum in the D register. For a disk containing sources and binaries of this and a whole lot of other OS-9 programs, send $10.00 to: Dave Lewis 4417 Idaho apt 4 San Diego CA 92116 If the program assembles properly, the Ident should be: Header for: Makdir Module size: $01F9 #505 Module CRC: $09990E (Good) Hdr parity: $D3 Exec. off: $0067 #103 Data Size: $00F9 #249 Edition: $02 #2 Ty/La At/Rv: $11 $82 Prog mod, 6809 obj, re-en, R/O ***************************************************************** * * Makdir (improved) -- now puts directory name in uppercase and * allows user to specify how much space to allocate for the * directory. Defaults to 8 sectors, the same as the standard. * * Makdir [-l] [-s#] [-n#] [-r] pathname * * -l: Allows lowercase letters in directory name * -s: Allocates "#" sectors for directory. "#" represents a * decimal number. Overrides "N" option if both are present. * -n: Allocates enough space for at least "#" user entries. * Space for "." and ".." is automatically added. * -r: Operates on an existing directory, such as the root * directory of an empty disk. Use this option with extreme * caution, as it can set up a disk to clobber itself at * some random time in the future. To be safe, use it only * on empty directories. * * Options must precede the pathname; the option processing * routine stops looking for them after it finds the path. The * "-" (minus sign) is required on each option entry. * ***************************************************************** * NAM Makdir TTL Create Directory * * Copyright 1986 by Dave Lewis * 4417 Idaho apt 4 * San Diego CA 92116 * IFP1 USE /D0/DEFS/OS9Defs USE /D0/DEFS/SCFDefs USE /D0/DEFS/RBFDefs ENDC * REV EQU 2 TYPE EQU PRGRM+OBJCT ATTR EQU REENT+REV * MOD SIZE,NAME,TYPE,ATTR,EXEC,STORG NAME FCS 'Makdir' FCB 2 Version number * MEMORG RMB 2 Data area origin address OPTL RMB 1 Upper or upper/lower case SECTORS RMB 1 Number of sectors in directory OPTS RMB 1 Nonzero if "S" option OPTR RMB 1 Nonzero if "R" option DIRPATH RMB 1 Directory path number ATPATH RMB 1 Disk @ path number BMAPOFST RMB 2 Offset to first sector byte BMAPBIT RMB 1 Bit representing first sector DIRFDLSN RMB 3 LSN of directory file descriptor FIRSTSEG RMB 5 First segment entry in FD SCRATCH EQU . Scratch memory RMB 180 Stack space RMB 50 Command line arguments STORG EQU . * ERRMSG FCC 'ERROR: bad arguments' FCB C$CR * GETNUMBR CLRA Start with a zero CLRB GETNUMB1 PSHS D Save old sum LDB ,X+ Get next character SUBB #'0 Subtract ASCII bias BLO NOTNUMBR Not a digit if less than $30 CMPB #9 Highest decimal digit BHI NOTNUMBR Not a digit if over 9 CLRA Make a 16-bit number PSHS D Save new digit LDB 3,S Get old LSB LDA #10 Load base 10 MUL Multiply old LSB ADDD ,S Add in new digit STD ,S Save partial product LDB 2,S Get old MSB LDA #10 Load base again MUL Multiply old MSB TFR B,A Move up 8 bits CLRB Zero out LSB ADDD ,S Add partial product LEAS 4,S Adjust the stack BSR GETNUMB1 Go get the next digit ANDCC #^CARRY Clear error condition RTS Return to caller NOTNUMBR COMA Set carry for error LEAX -1,X Point back to invalid char PULS D,PC Pull current number and return * ARGERROR LEAX <ERRMSG,PCR Point to error message ERROR LDA #2 Write to standard error path LDY #40 Write 40 bytes maximum OS9 I$WRITLN Display error message BRA QUIT Go terminate * EXEC STU MEMORG Save pointer to memory area CLRA Initialize variables to zero CLRB STD OPTL Store default values STD OPTS in all option variables FINDARGS LDA ,X+ Get next character of args CMPA #C$SPAC Is it space? BEQ FINDARGS Keep looking if so CMPA #C$CR Is it <CR>? BEQ ARGERROR No pathname if so CMPA #'- Is it "-"? BNE MAIN Not an option, must be path LDA ,X+ Get option identifier ANDA #$5F Make upper case CMPA #'L Is it "L"? BNE NOT.L Try others if not STA OPTL Set upper/lower case mode BRA FINDARGS Look for more arguments NOT.L CMPA #'S Is it "S"? BNE NOT.S Check for others if not BSR GETNUMBR Read the number BCS ARGERROR Error if not at least 1 digit INC OPTS Indicate "S" option used TSTB Did some bozo enter 0? BNE FINDARG2 Number is OK, use it INCB Make it semi-idiot-proof FINDARG2 STB SECTORS Store new sector size BRA FINDARGS Look for more arguments NOT.S CMPA #'N Is it "N"? BNE NOT.N Try "R" if not BSR GETNUMBR Read the number BCS ARGERROR Error if no number TST OPTS Was "S" used to set size? BNE FINDARGS Disregard this one if so ADDD #9 Add two entries for "." and LSRA "..", seven for the three RORB bits that get shifted out, LSRA and then divide by eight RORB for the eight entries that LSRA fit in one sector RORB BRA FINDARG2 Store sector count like "S" NOT.N CMPA #'R Is it "R"? (last chance!) BNE ARGERROR Oooops! STA OPTR Set the "R" flag BRA FINDARGS Look for more arguments * MAIN LEAX -1,X Point back to start of path PSHS Y,X Save memory end and path pointers TST OPTR Is option "R" on? BNE SETSIZE Skip directory create if so TST OPTL Is option "L" on? BNE CREATE Skip uppercase conversion if so CASELOOP LDA ,X+ Get next pathlist character ANDA #$5F Make it uppercase if alpha CMPA #'A Test for alpha, low bound BLO TESTEOM Not alpha if less than "A" CMPA #'Z Test high bound BHI TESTEOM Not alpha if more than "Z" STA -1,X Store character if alpha TESTEOM CMPX 2,S Test for end of memory BLO CASELOOP Continue if not at end CREATE LDX ,S Retrieve pathlist pointer LDB #$AF Attributes: d-e-rewr OS9 I$MAKDIR Create a new directory BCS QUIT Abort if error TST SECTORS If directory size has been BNE SETSIZE specified, go set it up CLRB Return no error QUIT OS9 F$EXIT Terminate the process * FRAGERR LEAX <FRAGMSG,PCR Point to error message LBRA ERROR Print it out and quit * FRAGMSG FCC 'ERROR: Directory fragmented' FCB C$CR * SETSIZE PULS X Retrieve pathlist pointer LDA #DIR.+READ. Access mode: d------r OS9 I$OPEN Open path to new directory BCS QUIT Abort if error STA DIRPATH Save path number LDS ,S Recover the argument space LDB #SS.OPT Get Option getstat code LEAX SCRATCH+1,U Point to free memory OS9 I$GETSTT Get path options BCS QUIT Abort if error LDD #"/D Create "/D#@" string from STD ,-X the drive number LDD #"0@ Make the drive number ASCII ADDA 2,X and tack on the "@" STD 2,X Store it LDA #C$CR Terminate the line STA 4,X with a <CR> LDA #UPDAT. Access mode: ------wr OS9 I$OPEN Open the entire disk BCS QUIT Abort if error STA ATPATH Save /D#@ path number LDB SCRATCH+21 Get the directory's file LDX SCRATCH+22 descriptor's LSN STB DIRFDLSN Save it for later STX DIRFDLSN+1 All 24 bits of it BSR SEEKSEG1 Point to first segment entry OS9 I$READ Read first two entries BCS QUIT Abort if error LDD SCRATCH+3 Get size of second segment BNE FRAGERR Already fragmented if nonzero LDD FIRSTSEG Get MSB's of LSN STD SCRATCH Stick in scratch area LDB FIRSTSEG+2 Move the LSB too STB SCRATCH+2 CLRA Initialize bit counter LDB #3 Initialize loop index FINDBIT LSR SCRATCH Divide the LSN by 8, catching ROR SCRATCH+1 the remainder in ACC A ROR SCRATCH+2 This finds the byte and bit RORA representing the file's DECB first sector BNE FINDBIT Repeat if not zero * * Normalize the remainder, which now looks like: * * ACC A 7654 3210 C (carry bit) * bbb0 0000 X bbb = rem X = don't care * LSLA bb00 0000 b ROLA b000 000b b ROLA 0000 00bb b ROLA 0000 0bbb 0 STA BMAPBIT Save bit number LDD SCRATCH+1 Get byte number INCA Add $100 for sector 0 STD BMAPOFST Save absolute offset on disk * * Get ten bytes from the disk sector allocation map, * starting with the byte containing the bit that * represents the first sector in the directory (the * one containing the "." and ".." entries). * This represents space for at least 582 entries. * BSR SEEKMAP Point into allocation map OS9 I$READ Read the allocation data BCS QUIT2 Abort if error CLRA Make MSB zero LDB SECTORS Get new directory size SUBB FIRSTSEG+4 Subtract current size BMI REDUCE If negative go make it smaller TFR D,Y Number of sectors to Y LDB BMAPBIT Get sector offset in byte ADDB FIRSTSEG+4 Add sectors in file LEAU 9,X Point to end of data PSHS D Save start point OS9 F$SCHBIT Find free sectors BCS CANTEXP Error: no room to expand CMPD ,S++ Can it be extended in one BNE CANTEXP continuous segment? OS9 F$ALLBIT If so, allocate the space EXIT BCS QUIT2 Abort if error BSR SEEKMAP Point to where data came from OS9 I$WRITE Write updated map back BCS QUIT2 Abort if error LDX DIRFDLSN+1 Get LSB's of sector number BSR SEEKSEG1 Point to first segment LEAY -5,Y Only 5 bytes this time LDB SECTORS Get new directory size STB FIRSTSEG+4 Update segment entry CLRB Prevent pesky error message OS9 I$WRITE Write the new entry back QUIT2 LBRA QUIT The end, error or no error * REDUCE NEGB How much smaller? TFR D,Y Put reduction in Y LDB BMAPBIT Get offset to sector 1 ADDB SECTORS Add in desired size OS9 F$DELBIT Deallocate excess sectors BRA EXIT Go finish up * SEEKSEG1 LDB #16 Offset 16 into file descriptor PSHS B Store file position LSB LDB DIRFDLSN Get MSB of sector number PSHS X,B Push three bytes on the stack PULS X,U Pull it off realigned OS9 I$SEEK Seek to the descriptor BCS QUIT2 Abort if error LDU MEMORG Point to start of memory LEAX FIRSTSEG,U Point to segment buffer BRA SEEKMAP2 Steal LDY - it's big * SEEKMAP LDU BMAPOFST It's needed in register U LDX #0 Zero out upper 16 bits LDA ATPATH Get /D#@ path number OS9 I$SEEK Seek to file's bit map BCS QUIT2 Abort if error LDU MEMORG Point to memory area LEAX SCRATCH,U Point to data buffer SEEKMAP2 LDY #10 Transfer ten bytes RTS * CANTEXP LEAX <EXPMSG,PCR Point to error message LBRA ERROR Complain and quit * EXPMSG FCC 'ERROR: can't expand directory' FCB C$CR * EMOD Insert CRC bytes SIZE EQU * Total size of module END ------------------------------- Dave Lewis Loral Instrumentation San Diego hp-sdd --\ ihnp4 --\ sdcrdcf --\ bang --\ kontron -\ csndvax ---\ calmasd -->-->!crash --\ celerity --->------->!sdcsvax!sdcc3 --->--->!loral!dml (uucp) dcdwest ---/ gould9 --/ -------------------------------