;***************************************************************************;
;                                                                           ;
;                                 COPY.SBR                                  ;
;                      AlphaBASIC XCALL to copy a file                      ;
;                                                                           ;
;***************************************************************************;
;Copyright (C) 1988 UltraSoft Corp.  All Rights Reserved.
;
;Written by: David Pallmann
;
;Copy a file and return status.
;
;       XCALL COPY, source_file$, dest_file$, status {, size}
;
;Where: source_file$ .......... is a string containing the full or partial
;                               specification of the source file to copy.
;       dest_file$ ............ is a string containing the full or partial
;                               specification of the destination file.
;       status ................ is a floating point variable.  Set to -1
;                               normally, or 0 if an error occurs.
;       size .................. is an optional floating point variable.  If
;                               specified, the size of the file is returned
;                               in blocks.
;Notes:
;
;       o  if string literals (e.g. "TEST.DAT ") are used instead of string
;          variables for source and destination filespecs, a trailing space
;          (as shown two lines above) is required - else you'll receive a
;          file specification error from AMOS.
;       o  compatible with LOKSER.
;       o  compatible with AMOS 2.0 & the extended file system.
;
;1.0(100)  01-Jun-87  created. /DFP
;1.0(101)  01-Jul-88  support random files. /DFP

       VMAJOR=1
       VMINOR=0
       VEDIT=101.

       OBJNAM  .SBR

       SEARCH  SYS
       SEARCH  SYSSYM

       BLOCKS=D5

       STRING=2
       FLOAT=4

       .OFINI
       .OFDEF  COUNT,2
       .OFDEF  TYPE1,2
       .OFDEF  ADDR1,4
       .OFDEF  SIZE1,4
       .OFDEF  TYPE2,2
       .OFDEF  ADDR2,4
       .OFDEF  SIZE2,4
       .OFDEF  TYPE3,2
       .OFDEF  ADDR3,4
       .OFDEF  SIZE3,4
       .OFDEF  TYPE4,2
       .OFDEF  ADDR4,4
       .OFDEF  SIZE4,4
       .OFSIZ  XCSIZE

       .OFINI
       .OFDEF  FROM,D.DDB+512.
       .OFDEF  TO,D.DDB+512.
;[101]  .OFDEF  MODULE,6
       .OFSIZ  MEMSIZ

START:  PHDR    -1,,PH$REE!PH$REU

CLEAR:  MOV     A4,A6
       MOV     #MEMSIZ-1,D6
10$:    CLRB    (A6)+
       DBF     D6,10$
       CLR     BLOCKS

CHECK:  CMPW    COUNT(A3),#3
       JLO     CNTERR
       CMPW    TYPE1(A3),#STRING
       JNE     TYPERR
       CMPW    TYPE2(A3),#STRING
       JNE     TYPERR
       CMPW    TYPE3(A3),#FLOAT
       JNE     TYPERR

SETUP:  LEA     A0,FROM(A4)
       MOV     ADDR1(A3),A2
       FSPEC   FROM(A4),WRT
       CALL    INIT
       LEA     A0,TO(A4)
       MOV     ADDR2(A3),A2
       FSPEC   TO(A4),WRT
       CALL    INIT

LOOKUP: LOOKUP  FROM(A4)
       JNE     FAIL
       MOV     FROM+D.FSZ(A4),BLOCKS
       LOOKUP  TO(A4)
       BNE     10$
       DSKDEL  TO(A4)
       JNE     FAIL
10$:    CMP     FROM+D.LSZ(A4),#512.    ; sequential or random file?    [101]
       JHIS    RANDOM.OPEN             ;  random                       [101]

SEQ.OPEN:
       OPENI   FROM(A4)
       JNE     FAIL
       OPENO   TO(A4)
       JNE     FAIL

SEQ.LOOP:
       CTRLC   CLOSE                   ; ^C entered                    [101]
       FILINB  FROM(A4)
       TST     FROM+D.SIZ(A4)
       JEQ     CLOSE
       FILOTB  TO(A4)
       BR      SEQ.LOOP

RANDOM.OPEN:
       MOV     BLOCKS,TO+D.ARG(A4)     ; set block count for DSKCTG    [101]
       DSKCTG  TO(A4)                  ; allocate output file          [101]
       JNE     FAIL                    ;  error                        [101]
       OPENR   FROM(A4),#F.EXC         ; open input file, exclusive    [101]
       OPENR   TO(A4),#F.EXC           ; open output file, exclusive   [101]
       CLR     FROM+D.REC(A4)          ; record zero of input file     [101]
       CLR     TO+D.REC(A4)            ; record zero of output file    [101]
       MOV     BLOCKS,D4               ; get block count
       MOV     FROM+D.BUF(A4),TO+D.BUF(A4) ; Two DDBs share same buffer [101]

RANDOM.LOOP:
       CTRLC   CLOSE                   ; ^C entered                    [101]
       INPUT   FROM(A4)                ; read block                    [101]
       OUTPUT  TO(A4)                  ; copy block                    [101]
       INC     FROM+D.REC(A4)          ; next input record             [101]
       INC     TO+D.REC(A4)            ; next output record            [101]
       SOB     D4,RANDOM.LOOP          ; loop till done                [101]

CLOSE:  CLOSE   FROM(A4)
       CLOSE   TO(A4)
       CTRLC   FAIL

SIZE:   CMPW    COUNT(A3),#4
       BLO     DONE
       MOV     ADDR4(A3),A0
       FLTOF   BLOCKS,@A0

DONE:   SET     D0
       BR      SETVAL

FAIL:   CLR     D0

SETVAL: MOV     ADDR3(A3),A0
       FLTOF   D0,@A0
       RTN

;error handling

CNTERR: TYPESP  ?Argument count
       BR      ERROR

TYPERR: TYPESP  ?Argument type

ERROR:  TYPECR  error in COPY.SBR
       EXIT

;do an "INIT" for the DDB @A0

INIT:   CLR     D.DVR(A0)               ;                               [101]
;[101]  MOVW    D.DEV(A0),D0
;[101]  BEQ     10$
;[101]  CMPW    D0,#[DSK]
;[101]  BEQ     10$
;[101]  MOVW    D.DEV(A0),MODULE(A4)
;[101]  CLRW    MODULE+2(A4)
;[101]  MOVW    #[DVR],MODULE+4(A4)
;[101]  SRCH    MODULE(A4),A1
;[101]  BNE     10$
;[101]  MOV     A1,D.DVR(A0)
10$:    LEA     A6,D.DDB(A0)
       MOV     A6,D.BUF(A0)
       ORB     #D$INI!D$ERC,D.FLG(A0)
       RTN

       END