Mercurial > hg > Members > kono > nitros9-code
view level1/cmds/copy.asm @ 1020:c1a5613ffe7b
changes
author | boisy |
---|---|
date | Thu, 06 Mar 2003 01:41:03 +0000 |
parents | c04528763543 |
children | 84ea83668304 |
line wrap: on
line source
******************************************************************** * Copy - File copy utility * * $Id$ * * Ed. Comments Who YY/MM/DD * ------------------------------------------------------------------ * 9 From Tandy OS-9 Level One VR 02.00.00 * 10 Reworked RML * 11 Added useful options, made more robust BGP 03/01/11 nam Copy ttl File copy utility ifp1 use defsfile use rbfdefs endc DOHELP set 0 tylg set Prgrm+Objct atrv set ReEnt+rev rev set $01 edition set 11 mod eom,name,tylg,atrv,start,size STACKSZ equ 128 estimated stack size PARMSZ equ 256 estimated parameter size DDIRBSIZ equ 64 destination directory buffer size org 0 rdbufptr rmb 2 parmptr rmb 2 srcpath rmb 1 dstpath rmb 1 devtyp rmb 1 bufsiz rmb 2 srcflsiz rmb 4 abortflg rmb 1 quiet rmb 1 single rmb 1 rewrite rmb 1 filecnt rmb 1 srccnt rmb 1 srcmode rmb 1 wopt rmb 1 srcfname rmb 2 dstfptr rmb 2 wfileptr rmb 2 wfilelen rmb 2 lstfopen rmb 2 pointer to name of last file attempted open lstfopln rmb 2 length of last file atteppted open srcattr rmb 1 fdbufcpy rmb 16 optbuf rmb 32 wdest rmb DDIRBSIZ portion after '-w=' rmb DDIRBSIZ additional space * Note: copy buffer must come just before the stack IFGT Level-1 copybuff rmb 8*1024 8K default buffer for Level 2 ELSE copybuff rmb 512 512 byte default buffer for Level 1 ENDC rmb STACKSZ+PARMSZ size equ . name fcs /Copy/ fcb edition SrcPmpt fcc /Ready SOURCE, hit C to continue: / SrcPmptL equ *-SrcPmpt DstPmpt fcc /Ready DESTINATION, hit C to continue: / DstPmptL equ *-DstPmpt CrRtn fcb C$CR IFNE DOHELP HlpMsg fcb C$LF fcc /Use: Copy [<opts>] <srcpath> [<dstpath>] [<opts>]/ fcb C$LF fcc / -a = abort on error/ fcb C$LF fcc / -p = don't print files copied (use with -w)/ fcb C$LF fcc / -r = rewrite destination/ fcb C$LF fcc / -s = single drive copy/ fcb C$LF fcc / -w=<dir> = copy to <dir>/ fcb C$LF fcc / -x = copy from exec dir/ fcb C$CR HlpMsgL equ *-HlpMsg ENDC PLIncmp fcc /copy: destination must be complete pathlist/ fcb C$CR TooMany fcc /copy: must specify output directory if more than 2 files/ fcb C$CR Copying fcc /copying / CopyingL equ *-Copying CopyTo fcc / to / CopyToL equ *-CopyTo Cont fcc !Continue (y/n) ?! ContL equ *-Cont CantCpy fcc /copy: can't open / CantCpyL equ *-CantCpy SpcDsh fcc / - / SpcDshL equ *-SpcDsh * +-----------------+ <-- Y (highest address) * ! ! * ! Parameter ! * ! Area ! * ! ! * +-----------------+ <-- X, SP * ! ! * ! ! * ! Data Area ! * ! ! * ! ! * +-----------------+ * ! Direct Page ! * +-----------------+ <-- U, DP (lowest address) * * D = parameter area size * PC = module entry point abs. address * CC = F=0, I=0, others undefined start pshs u,x leax <wdest,u pshs x clrnxt clr ,u+ cmpu ,s bne clrnxt leas 2,s puls x,u leay copybuff,u point Y to copy buffer offset in U stx <parmptr save parameter pointer sty <rdbufptr save pointer to buffer tfr s,d place top of stack in D pshs y save Y on stack subd ,s++ get size of space between copybuf and X subd #STACKSZ+PARMSZ subtract out our stack std <bufsiz size of our buffer lbsr SkipSpcs move past any spaces on command line cmpa #C$CR CR? lbeq ShowHelp if so, show help GetNChr lda ,x+ cmpa #C$CR CR? lbeq CpyFiles branch if so cmpa #'- option? beq GetDash inc <filecnt must be a file lbsr SkipNSpc else go past non-spaces ChkDash lbsr SkipSpcs and any following spaces bra GetNChr and check for Cr GetDash lda #C$SPAC sta -1,x GetDash2 ldd ,x+ load option char and char following anda #$5F cmpa #'S single drive copy? bne IsItA branch if not inc <single lbra FixCmdLn IsItA cmpa #'A abort option? bne IsItP branch if not inc <abortflg bra FixCmdLn IsItP cmpa #'P supress output? bne IsItX branch if not inc <quiet bra FixCmdLn IsItX cmpa #'X execution dir? bne IsItW branch if not lda #EXEC. else get EXEC. sta <srcmode and save as source mode bra FixCmdLn IsItW cmpa #'W directory specification? bne IsItR branch if not tst <wopt already specified? bne BadOpt show help if so cmpb #'= 2nd char =? bne BadOpt show help if not inc <wopt else tag wopt as specified ldb #C$SPAC get space stb -$01,x write over w stb ,x+ and = sign, inc X to dest dir * check for valid char after -w= lda ,x cmpa #C$SPAC lbeq ShowHelp cmpa #C$COMA lbeq ShowHelp cmpa #C$CR lbeq ShowHelp leay <wdest,u point Y to parameber buffer sty <dstfptr save pointer to destination file tfr y,d transfer Y to D addd #DDIRBSIZ add size pshs b,a save updated ptr value ldb #C$SPAC get space L0339 lda ,x get byte at X stb ,x+ store space at X and inc sta ,y+ save loaded byte at Y and inc cmpy ,s are we at end? beq L035D branch if so (buffer too small) cmpa #C$SPAC else is char in A a space? beq L0350 branch if so cmpa #C$COMA coma? beq L0350 branch if so cmpa #C$CR cr? bne L0339 get next byte if not L0350 leax -1,x sta ,x restore previous A lda #PDELIM get pathlist delimiter sta -$01,y save slash at end (for building path later) sty <wfileptr save pointer for -w pathlist file copying leas $02,s kill stack lbra ChkDash L035D leas $02,s ldb #$BF else buffer size too small orcc #Carry lbra Exit IsItR cmpa #'R rewrite? bne BadOpt branch if not inc <rewrite FixCmdLn lda #C$SPAC get space sta -$01,x and wipe out option character cmpb #'0 lblt ChkDash start dash option processing again lbra GetDash possibly another option following? BadOpt puls x lbra ShowHelp CopyToW ldx <srcfname get ptr to next file to process * In case the source file name has a / in it (i.e. /dd/x/y/fname), * we go past the file and then back up to either the first / we * encounter, or a space (be sure we don't go past parmptr) lda ,x cmpa #C$CR carriage return? lbeq ExitOk yep, no more files lbsr SkipNSpc skip over filename * X points to first char after file name (space, comma or CR) L038B cmpx <parmptr are we at start of command line? beq PlugIt2 if so, we can't go further back lda ,-x get byte cmpa #PDELIM path delimiter? beq PlugIt branch if so cmpa #C$SPAC space? beq PlugIt branch if so cmpa #C$COMA comma? beq PlugIt branch if so bra L038B else get next char PlugIt leax 1,x go forward 1 PlugIt2 ldy <wfileptr get address past xxxx/ (specified by -w=) lbsr StrCpy copy filename std <wfilelen save file length lda #C$CR get CR sta ,y and terminate * ldx <wopt * stx <wfileptr rts * At this point options are processed, so we need to start copying files CpyFiles tst <filecnt we should have at least one file on cmdline lbeq ShowHelp if not, exit with error ldx <parmptr get our parameter pointer off stack lbsr SkipSpcs skip any leading spaces tst <wopt -w specified? beq L03C5 branch if not stx <srcfname else save start of parameter pointer as next file clr <single no single option with -w L03BE bsr CopyToW copy file at <srcfname to -w buffer bra OpenSrc * This code handles single file copy (i.e. copy file1 file2) * or a single disk copy (i.e. copy -s abc) L03C5 lbsr GetSDFl else get source/destination files bcc L03D4 branch if we got both ok tst <single is this a single drive copy? lbne PListErr if not, user didn't specify enough files lbcs Exit if error, exit * test for right number of files L03D4 lda <filecnt get total file count cmpa #2 should be no more than two files ble OpenSrc leax TooMany,pcr lbsr WrLine lbra ExitOk OpenSrc ldx <srcfname get file to open pshs x lbsr StrLen get length std <lstfopln save length puls x lda #READ. read mode ora <srcmode or in any additional modes (i.e. EXEC.) stx <lstfopen save pointer to last file open var os9 I$Open open source file bcc L03FA branch if open ok cmpx <srcfname did open go past pathlist? bne OpenFail branch if so lbsr SkipNSpc else skip over failed filename lbsr SkipSpcs and any trailing spaces OpenFail stx <srcfname save updated pathlist pointer (points to next file on cmd line) lbra ShutDown L03FA sta <srcpath save source path pshs a save path lbsr SkipSpcs destroy any leading spaces stx <srcfname and save pointer to next source filename lbsr StrLen get length std <lstfopln save length puls a get path off stack leax <fdbufcpy,u point to FD buffer ldy #FD.SEG number of bytes ldb #SS.FD os9 I$GetStt get file's file descriptor bcs L041B branch if error tst <single single drive copy? beq L041B branch if not lda [<dstfptr,u] get first char of destination filename ldb #E$BPNam prepare for possible error cmpa #PDELIM path has leading slash? lbne PListErr if not, show error L041B lda <srcpath get source path leax <optbuf,u point to options buffer clrb was: ldb #SS.Opt os9 I$GetStt get path options lbcs ShutDown branch if error lda ,x get device type sta <devtyp save ldb #$0F cmpa #DT.RBF rbf device? bne L0449 branch if not pshs u,x save regs lda <srcpath get source path ldb #SS.Size os9 I$GetStt get size lbcs ShutDown stx <srcflsiz save file size stu <srcflsiz+2 puls u,x restore regs ldb <PD.ATT-PD.OPT,x get source file's attributes L0449 stb <srcattr save lda #$01 lbsr SwapDsk check for single disk copy and prompt if necessary L0450 ldx <dstfptr point to destination file pshs x lbsr StrLen get length std <lstfopln save length puls x lda #WRITE. write mode ldb <srcattr get source attributes stx <lstfopen os9 I$Create create file bcc L048B branch if create ok tst <rewrite rewrite flag set? lbeq ShutDown branch if no cmpb #E$CEF file already exists? lbne ShutDown branch if any other error L047A os9 I$Delete delete file first lbcs ShutDown branch if error bra L0450 else try opening again L048B sta <dstpath save destination path tst <wopt w option specified? beq GetOpts branch iff not tst <quiet p option specified? bne GetOpts branch if so pshs a else save dest path on stack leax >Copying,pcr else print 'Copying...' ldy #CopyingL lbsr WritSOut write it to stdout ldx <wfileptr get pointer to file being copied ldy <wfilelen get file name length lbsr WritSOut print file name leax >CopyTo,pcr print ' to ' ldy #CopyToL lbsr WritSOut write it to stdout ldx <dstfptr get pointer to file being copied lbsr WrLine print file with CR puls a restore dest path GetOpts leax <optbuf,u point to option buffer clrb was: ldb #SS.Opt os9 I$GetStt get options lbcs ShutDown branch if error ldb ,x get device type cmpb #DT.RBF rbf? bne CopyLoop if not rbf device, don't get file size or fd seg L04B4 lda <devtyp get device type cmpa #DT.RBF rbf? bne CopyLoop branch if not pshs u save our statics ptr lda <dstpath else get dest path ldb #SS.Size and setstat option ldx <srcflsiz get file size of source ldu <srcflsiz+2 os9 I$SetStt and set dest file to same size lbcs ShutDown branch if error puls u restore U lda <dstpath get dest path leax <fdbufcpy,u point to file desc. buffer ldy #FD.SEG get size ldb #SS.FD os9 I$SetStt write src fd seg to dest file * Copy loop is here CopyLoop ldx <rdbufptr get ptr to read buffer clra A = 0 = source prompt if needed lbsr SwapDsk check for single disk copy and prompt if so lda <srcpath get source path ldy <bufsiz get buffer size os9 I$Read read it! bcs L0558 branch if error lda #$01 A = 1 = dest prompt lbsr SwapDsk check for single disk copy and prompt if so lda <dstpath get dest path os9 I$Write write it out! lbcs ShutDown branch if error lda <srcpath get source path ldb #SS.EOF os9 I$GetStt are we at end of file? bcc CopyLoop branch if not cmpb #E$EOF end of file error? beq L0561 branch if so L0558 cmpb #E$EOF end of file rror? bne ShutDown branch if not lda #$01 prompt destination flag lbsr SwapDsk check for single drive copy and prompt if necessary L0561 lda <dstpath get destination path os9 I$Close close that file bcs ShutDown branch if error clr <dstpath else clear dest path lda <srcpath get source path os9 I$Close close it bcs ShutDown branch if error clr <srcpath clear src path tst <wopt -w specified lbeq ExitOk branch if not lbra L03BE * Entry: X = ptr to data to write, Y = length WritSOut lda #$01 standard out os9 I$Write write it rts PListErr leax >PLIncmp,pcr bsr WrLine bra ExitOk ShutDown pshs b lda <srcpath get source path beq L05AA branch if none os9 I$Close close it L05AA lda <dstpath get dest path beq L05B1 branch if none os9 I$Close close it L05B1 clr <srcpath clear source path clr <dstpath and destination leax >CantCpy,pcr else show can't copy error ldy #CantCpyL bsr WritSOut write out ldx <lstfopen show filename that failed ldy <lstfopln get length bsr WritSOut leax >SpcDsh,pcr ldy #SpcDshL bsr WritSOut write out puls b PrintErr os9 F$PErr print error tst <wopt -w used? beq ExitOk branch if not tst <abortflg abort flag set? bne ExitOk branch if so AskAgain leax >Cont,pcr point to continue prompt ldy #ContL get length bsr WritSOut write clra ADDED +BGP+ ldx <rdbufptr get pointer at readbuf ldy #$0002 2 bytes os9 I$ReadLn read form stdin lda ,x get byte at X anda #$5F cmpa #'Y user wants to continue? lbeq L03BE branch if so cmpa #'N no? beq ExitOk branch if so bra AskAgain else ask again ShowHelp equ * IFNE DOHELP leax >HlpMsg,pcr point to help message ldy #HlpMsgL get length lda #$02 std error os9 I$WritLn write it ENDC ExitOk clrb clear carry Exit os9 F$Exit and exit * Write line passed in X WrLine ldy #$00A0 WrNBytes lda #$01 os9 I$WritLn rts * Prompt User for Source or Destination Disk SwapDsk tst <single single disk copy? beq NoSwap branch if not pshs y,x L0626 pshs a tsta bne L0635 leax >SrcPmpt,pcr point to source prompt ldy #SrcPmptL get size bra L063D write it and get input L0635 leax >DstPmpt,pcr point to dest prompt ldy #DstPmptL get size L063D bsr WrNBytes write it leax ,-s point to stack for temp buffer ldy #$0001 one byte clra from std in os9 I$Read read byte from user lda ,s+ get char eora #'C anda #$DF beq L0657 branch if C bsr L065E puls a bne L0626 L0657 bsr L065E puls a puls y,x NoSwap rts L065E pshs y,x,a lda #$01 leax >CrRtn,pcr ldy #80 os9 I$WritLn puls pc,y,x,a * StrLen * * Entry: * X = ptr to string (space, comma or CR terminated) * Exit: * D = length of string * X = ptr to byte after string StrLen pshs u ldu #$0000 StrLenLp lda ,x+ cmpa #C$SPAC beq StrLenEx cmpa #C$COMA beq StrLenEx cmpa #C$CR beq StrLenEx leau 1,u bra StrLenLp StrLenEx tfr u,d puls u,pc * StrCpy * * Entry: * X = ptr to src string * Y = ptr to dest string * Exit: * D = number of bytes copied * X = ptr to byte after original string * X = ptr to byte after copied string StrCpy pshs u ldu #$0000 CopyFnLp lda ,x+ cmpa #C$SPAC beq CopyFnEx cmpa #C$COMA beq CopyFnEx cmpa #C$CR beq CopyFnEx sta ,y+ leau 1,u bra CopyFnLp CopyFnEx tfr u,d puls u,pc * Skip over spaces and commas * * Entry: * X = ptr to string * Exit: * X = ptr to first non-whitespace char * A = non-whitespace char SkipSpcs lda ,x+ cmpa #C$SPAC beq SkipSpcs cmpa #C$COMA beq SkipSpcs leax -1,x rts * Skip over non-spaces and non-commas * * Entry: * X = ptr to string * Exit: * X = ptr to first non-whitespace char * A = non-whitespace char SkipNSpc lda ,x+ cmpa #C$SPAC beq EatOut cmpa #C$COMA beq EatOut cmpa #C$CR bne SkipNSpc EatOut leax -1,x rts * Get source file in <srcfname and destination file in <dstfptr GetSDFl leay <srcfname,u point X to next file pointer bsr SrchFile skip white spaces, look for name on cmd line bcs L067D branch if end inc <srccnt else increment souce count leay <dstfptr,u point Y to destination file bsr SkipSpcs destroy any leading spaces bsr SrchFile skip white spaces, look for name on cmd line L067D rts * Starting at X, parse for a filename, skipping leading white spaces SrchFile lda ,x cmpa #C$CR CR? beq L06A2 branch if so stx ,y else store X at Y SkipFile bsr SkipNSpc skip non-spaces ParseOk clrb clear B rts return L06A2 tst <srccnt any file specified? bne L06AA branch if so BadPName ldb #E$BPNam else no source was specified coma rts L06AA ldx <srcfname get pointer L06AC lda ,x+ get char cmpa #C$SPAC space? beq L06C4 branch if so cmpa #C$COMA comma? beq L06C4 branch if so cmpa #C$CR carriage return? beq L06C4 branch if so cmpa #PDELIM pathlist delimiter? bne L06AC branch if not clr <srccnt else clear file count stx ,y and store bra L06AC continue parsing L06C4 tst <srccnt file count 0? beq L06D2 branch if so tst <srcmode source mode? (exec or data dir) beq BadPName branch if data ldx <srcfname else get pointer stx ,y save bra ParseOk branch L06D2 lda -$02,x cmpa #PDELIM beq BadPName bra ParseOk emod eom equ * end