home *** CD-ROM | disk | FTP | other *** search
- ; SEQUENTIAL FILE I/O LIBRARY
-
- ; VRS 2.2 Jack Riley, Boulder Colorado(RCPM phone: (303)499-9169)
- ;
- ; This is a highly modified version of the original by unknown author
- ; believed to be Ward Christensen.
- ; It has been expanded to include the following new features:
- ; 1) An APPEND mode to the FILE macro to allow the opening of files
- ; with automatic positioning to the EOF. Both GET and PUT macros
- ; are expanded to allow full random access to the file. Random
- ; access reads and writes are used instead of sequential(and also
- ; in other modes of use of the FILE macro so 1.4 is now incompatible).
- ; 2) PUBLIC and NONLOC options have been added to the FILE macro
- ; to allow access to files not in the current user area or on the
- ; current disk drive. The GET and PUT macros also handle the switching
- ; needed to provide for multiple opens in multiple areas. The way
- ; they work is to momentarily switch the user area to the one needed
- ; for the file undergoing an IO operation. A return is made to the
- ; 'home' user area to allow for 'local' file accesses or switches
- ; to other areas to access other files. This is not completely
- ; satisfactory and one could wish for a more elegant method which
- ; should have been available under CPM. Also an additional byte
- ; has been added to the FCB generated by FILLFCB to contain the
- ; user area. The NONLOC option prevents an otherwise automatic
- ; sequence to look first in the current user area and on the current
- ; disk for the file, then switch the user area, then the disk to
- ; the default locations. When PUBLIC is included in an invocation
- ; of FILE, then code accessing default and current values is made.
- ; The allocations for these variables is shown below.
- ; DEFAULT$USER:
- ; DB 0 ; or other user area
- ; DEFAULT$DISK:
- ; DB 'x'-'A' ; where x is the default
- ; CUR$USER:
- ; DB 0FFH ; necessary initial value
- ; CUR$DISK:
- ; DB 0FFH ; " "
- ;
- ; The intention was to allow the default values to be modified
- ; at run time(one of the failings of MACRO-economics) so that
- ; determinations of the availability of hard disks, for example,
- ; could be included. Also it is sometimes nice to have these
- ; values at the very beginning of a program so that DDT-style
- ; customizations can be made.
- ; 3) A SECTBUF parameter has been added to FILE to turn off the
- ; standard character buffering previously provided. It seemed
- ; reasonable to provide this new open machinery even when
- ; simple sector buffering was intended. Also when SECTBUF=NONE
- ; all buffering is turned off and only the new open code is
- ; produced. This can also be done through use of the POPEN macro
- ; directly(without FCB's being generated).
-
- FILERR SET 0000H ;REBOOT AFTER ERROR
- @FALSE SET 0000H
- @TRUE SET NOT @FALSE
- @BDOS EQU 0005H ;BDOS ENTRY POINT
- @TFCB EQU 005CH ;DEFAULT FILE CONTROL BLOCK
- @TBUF EQU 0080H ;DEFAULT BUFFER ADDRESS
- ;
- ; BDOS FUNCTIONS
- @MSG EQU 9 ;SEND MESSAGE
- @OPN EQU 15 ;FILE OPEN
- @CLS EQU 16 ;FILE CLOSE
- @DIR EQU 17 ;DIRECTORY SEARCH
- @DEL EQU 19 ;FILE DELETE
- @MAK EQU 22 ;FILE MAKE
- @REN EQU 23 ;FILE RENAME
- @DMA EQU 26 ;SET DMA ADDRESS
- @FRD EQU 33 ;FILE RANDOM READ OPERATION
- @FWR EQU 34 ;FILE RANDOM WRITE OPERATION
- @CFS EQU 35 ;COMPUTE FILE SIZE
- @SETRR EQU 36 ;SET RANDOM RECORD
- ;
- @SECT EQU 128 ;SECTOR SIZE
- EOF EQU 1AH ;END OF FILE
- @CR EQU 0DH ;CARRIAGE RETURN
- @LF EQU 0AH ;LINE FEED
- TAB EQU 09H ;HORIZONTAL TAB
- ;
- @KEY EQU 1 ;KEYBOARD
- @CON EQU 2 ;CONSOLE DISPLAY
- @RDR EQU 3 ;READER
- @PUN EQU 4 ;PUNCH
- @LST EQU 5 ;LIST DEVICE
- ;
- ; KEYWORDS FOR "FILE" MACRO
- NONE EQU 1
- SECTBUFF EQU @TRUE
- NONLOC EQU @TRUE
- INFILE EQU 1 ;INPUT FILE
- OUTFILE EQU 2 ;OUTPUTFILE
- SETFILE EQU 3 ;SETUP NAME ONLY
- APPEND EQU 4 ;APPEND TO FILE
- ;
- ; THE FOLLOWING MACROS DEFINE SIMPLE SEQUENTIAL
- ; FILE OPERATIONS:
- ;
- FILLNAM MACRO FC,C
- ;; FILL THE FILE NAME/TYPE GIVEN BY FC FOR C CHARACTERS
- @CNT SET C ;;MAX LENGTH
- IRPC ?FC,FC ;;FILL EACH CHARACTER
- ;; MAY BE END OF COUNT OR NUL NAME
- IF @CNT=0 OR NUL ?FC
- EXITM
- ENDIF
- DB '&?FC' ;;FILL ONE MORE
- @CNT SET @CNT-1 ;;DECREMENT MAX LENGTH
- ENDM ;;OF IRPC ?FC
- ;;
- ;; PAD REMAINDER
- REPT @CNT ;;@CNT IS REMAINDER
- DB ' ' ;;PAD ONE MORE BLANK
- ENDM ;;OF REPT
- ENDM
- ;
- FILLDEF MACRO FCB,?FL,?LN
- ;; FILL THE FILE NAME FROM THE DEFAULT FCB
- ;; FOR LENGTH ?LN (9 OR 12)
- LOCAL PSUB
- JMP PSUB ;;JUMP PAST THE SUBROUTINE
- @DEF: ;;THIS SUBROUTINE FILLS FROM THE TFCB (+16)
- MOV A,M ;;GET NEXT CHARACTER TO A
- STAX D ;;STORE TO FCB AREA
- INX H
- INX D
- DCR C ;;COUNT LENGTH DOWN TO 0
- JNZ @DEF
- RET
- ;; END OF FILL SUBROUTINE
- PSUB EQU $
- FILLDEF MACRO ?FCB,?F,?L
- LXI H,@TFCB+?F ;;EITHER @TFCB OR @TFCB+16
- LXI D,?FCB
- MVI C,?L ;;LENGTH = 9,12
- CALL @DEF
- ENDM
- FILLDEF FCB,?FL,?LN
- ENDM
- ;
- FILLNXT MACRO
- ;; INITIALIZE BUFFER AND DEVICE NUMBERS
- @NXTB SET 0 ;;NEXT BUFFER LOCATION
- @NXTD SET @LST+1 ;;NEXT DEVICE NUMBER
- FILLNXT MACRO
- ENDM
- ENDM
- ;
- FILLFCB MACRO MD,FID,DN,FN,FT,BS,BA
- ;; FILL THE FILE CONTROL BLOCK WITH DISK NAME
- ;; DEFINE FILE USING MODE MD:
- ;; INFILE = 1 INPUT FILE
- ;; OUTFILE = 2 OUTPUT FILE
- ;; SETFILE = 3 SETUP FCB
- ;; FID IS AN INTERNAL NAME FOR THE FILE,
- ;; DN IS THE DRIVE NAME (A,B..), OR BLANK
- ;; FN IS THE FILE NAME, OR BLANK
- ;; FT IS THE FILE TYPE
- ;; BS IS THE BUFFER SIZE
- ;; BA IS THE BUFFER ADDRESS
- LOCAL PFCB
- ;;
- FID&TYP SET MD ;;SET MODE FOR LATER REF'S
- ;; SET UP THE FILE CONTROL BLOCK FOR THE FILE
- ;; LOOK FOR FILE NAME = 1 OR 2
- @C SET 1 ;;ASSUME TRUE TO BEGIN WITH
- IRPC ?C,FN ;;LOOK THROUGH CHARACTERS OF NAME
- IF NOT ('&?C' = '1' OR '&?C' = '2')
- @C SET 0 ;;CLEAR IF NOT 1 OR 2
- ENDIF
- ENDM
- ;; @C IS TRUE IF FN = 1 OR 2 AT THIS POINT
- IF @C ;;THEN FN = 1 OR 2
- ;; FILL FROM DEFAULT AREA
- IF NUL FT ;;TYPE SPECIFIED?
- @C SET 12 ;;BOTH NAME AND TYPE
- ELSE
- @C SET 9 ;;NAME ONLY
- ENDIF
- FILLDEF FCB&FID,(FN-1)*16,@C ;;TO SELECT THE FCB
- JMP PFCB ;;PAST FCB DEFINITION
- DS @C ;;SPACE FOR DRIVE/FILENAME/TYPE
- FILLNAM FT,12-@C ;;SERIES OF DB'S
- ELSE
- JMP PFCB ;;PAST INITIALIZED FCB
- IF NUL DN
- DB 0 ;;USE DEFAULT DRIVE IF NAME IS ZERO
- ELSE
- DB '&DN'-'A'+1 ;;USE SPECIFIED DRIVE
- ENDIF
- FILLNAM FN,8 ;;FILL FILE NAME
- ;; NOW GENERATE THE FILE TYPE WITH PADDED BLANKS
- FILLNAM FT,3 ;;AND THREE CHARACTER TYPE
- ENDIF
- FCB&FID EQU $-12 ;;BEGINNING OF THE FCB
- DB 0 ;;EXTENT FIELD 00 FOR SETFILE
- ;; NOW DEFINE THE 3 BYTE FIELD, AND DISK MAP
- DS 23 ;;X,X,RC,DM0...DM15,CR,R0,R1,R2 FIELDS
- DB 0FFH ;; DEFAULT CURRENT USER AREA
- ;;
- IF FID&TYP<=2 ;;IN/OUTFILE
- ;; GENERATE CONSTANTS FOR INFILE/OUTFILE
- FILLNXT ;;@NXTB=0 ON FIRST CALL
- IF BS+0<@SECT
- ;; BS NOT SUPPLIED, OR TOO SMALL
- @BS SET @SECT ;;DEFAULT TO ONE SECTOR
- ELSE
- ;; COMPUTE EVEN BUFFER ADDRESS
- @BS SET (BS/@SECT)*@SECT
- ENDIF
- ;;
- ;; NOW DEFINE BUFFER BASE ADDRESS
- IF NUL BA
- ;; USE NEXT ADDRESS AFTER @NXTB
- FID&BUF SET BUFFERS+@NXTB
- ;; COUNT PAST THIS BUFFER
- @NXTB SET @NXTB+@BS
- ELSE
- FID&BUF SET BA
- ENDIF
- ;; FID&BUF IS BUFFER ADDRESS
- FID&ADR EQU $
- DW FID&BUF
- ;;
- FID&SIZ EQU @BS ;;LITERAL SIZE
- FID&LEN EQU $
- DW @BS ;;BUFFER SIZE
- FID&PTR EQU $
- DS 2 ;;SET IN INFILE/OUTFILE
- ;; SET DEVICE NUMBER
- @&FID SET @NXTD ;;NEXT DEVICE
- @NXTD SET @NXTD+1
- ENDIF ;;OF FID&TYP<=2 TEST
- PFCB EQU $
- ENDM
- ;
- FILE MACRO FMODE,FID,DN,FN,FT,BS,BA,PU,NOLOC,SECTBUF
- ;; (SEE FILLFCB FOR PARAMETERS)
- FID&FLG SET 1
- IF NUL PU
- FID&PUB SET 0
- ELSE
- FID&PUB SET 1
- ENDIF
-
- @SETRC SET @SETRR
- IF FMODE=APPEND
- @SETRC SET @CFS
- GFILE FMODE,FID,DN,FN,FT,BS,BA,PU,NOLOC,SECTBUF,0
- FID&TYP SET OUTFILE ;;SET MODE FOR LATER REF'S
- ENDIF
- GFILE FMODE,FID,DN,FN,FT,BS,BA,PU,NOLOC,SECTBUF,@SETRC
- ENDM
- ;
- GFILE MACRO FMODE,FID,DN,FN,FT,BS,BA,PU,NOLOC,SECTBUF,@SETRC
- LOCAL PSUB,MSG,PMSG
- LOCAL PND,EOD,EOB,PNC,GLOOP,SAMEUSR
- ;; CONSTRUCT THE FILE CONTROL BLOCK
- ;;
- MD SET FMODE
- IF FMODE=APPEND
- IF @SETRC=0
- MD SET INFILE
- ELSE
- MD SET OUTFILE
- ENDIF
- ENDIF
- IF FID&FLG
- FILLFCB MD,FID,DN,FN,FT,BS,BA
- ENDIF
- IF MD=SETFILE ;;SETUP FCB ONLY, SO EXIT
- EXITM
- ENDIF
- ;; FILE CONTROL BLOCK AND RELATED PARAMETERS
- ;; ARE CREATED INLINE, NOW CREATE IO FUNCTION
- BLOCKING SET @TRUE
- IF NUL SECTBUF ;;INPUT FILE
- JMP PSUB ;;PAST INLINE SUBROUTINE
- IF MD=OUTFILE
- PUT&FID EQU $
- PUSH PSW ;;SAVE OUTPUT CHARACTER
- ELSE
- GET&FID EQU $
- ENDIF
- LHLD FID&LEN ;;LOAD CURRENT BUFFER LENGTH
- XCHG ;;DE IS LENGTH
- LHLD FID&PTR ;;LOAD NEXT TO GET/PUT TO HL
- MOV A,L ;;COMPUTE CUR-LEN
- SUB E
- MOV A,H
- SBB D ;;CARRY IF NEXT<LENGTH
- JC PNC ;;CARRY IF LEN GTR CURRENT
- ;; END OF BUFFER, FILL/EMPTY BUFFERS
- ELSE
- IF SECTBUF=NONE
- BLOCKING SET @FALSE
- ENDIF
- ENDIF
- IF BLOCKING
- LXI H,0
- SHLD FID&PTR ;;CLEAR NEXT TO GET/PUT
- PND EQU $
- ;; PROCESS NEXT DISK SECTOR:
- XCHG ;;FID&PTR TO DE
- LHLD FID&LEN ;;DO NOT EXCEED LENGTH
- ;; DE IS NEXT TO FILL/EMPTY, HL IS MAX LEN
- MOV A,E ;;COMPUTE NEXT-LEN
- SUB L ;;TO GET CARRY IF MORE
- MOV A,D
- SBB H ;;TO FILL
- JNC EOB
- ;; CARRY GEN'ED, HENCE MORE TO FILL/EMPTY
- LHLD FID&ADR ;;BASE OF BUFFERS
- DAD D ;;HL IS NEXT BUFFER ADDR
- XCHG
- MVI C,@DMA ;;SET DMA ADDRESS
- CALL @BDOS ;;DMA ADDRESS IS SET
- IF FID&PUB
- LDA FCB&FID+36 ;; GET USER AREA OF FILE
- CPI 0FFH
- JZ SAMEUSR
- MVI C,32
- MOV E,A
- CALL @BDOS ;; GO TO FILE USER AREA
- SAMEUSR EQU $
- ENDIF
- LXI D,FCB&FID ;;FCB ADDRESS TO DE
- IF MD=INFILE ;;READ BUFFER FUNCTION
- MVI C,@FRD ;;FILE READ FUNCTION
- ELSE
- MVI C,@FWR ;;FILE WRITE FUNCTION
- ENDIF
- CALL @BDOS ;;RD/WR TO/FROM DMA ADDRESS
- IF FID&PUB
- CALL RESET$SYSTEM
- ENDIF
- ORA A ;;CHECK RETURN CODE
- JNZ EOD ;;END OF FILE/DISK?
- ;; NOT END OF FILE/DISK, INCREMENT LENGTH
- LHLD FCB&FID+33 ;;INDEX TO RANDOM RECORD #
- INX H
- SHLD FCB&FID+33 ;;POINTER UPDATED
- LXI D,@SECT ;;SECTOR SIZE
- LHLD FID&PTR ;;NEXT TO FILL
- DAD D
- SHLD FID&PTR ;;BACK TO MEMORY
- JMP PND ;;PROCESS ANOTHER SECTOR
- ;;
- EOD EQU $
- ;; END OF FILE/DISK ENCOUNTERED
- IF MD=INFILE ;;INPUT FILE
- LHLD FID&PTR ;;LENGTH OF BUFFER
- SHLD FID&LEN ;;RESET LENGTH
- ELSE
- ;; FATAL ERROR, END OF DISK
- LOCAL EMSG
- MVI C,@MSG ;;WRITE THE ERROR
- LXI D,EMSG
- CALL @BDOS ;;ERROR TO CONSOLE
- POP PSW ;;REMOVE STACKED CHARACTER
- JMP FILERR ;;USUALLY REBOOTS
- EMSG EQU $
- DB @CR,@LF
- DB 'DISK FULL: &FID'
- DB '$'
- ENDIF
- ;;
- EOB EQU $
- ;; END OF BUFFER, RESET DMA AND POINTER
- LXI D,@TBUF
- MVI C,@DMA
- CALL @BDOS
- LXI H,0
- SHLD FID&PTR ;;NEXT TO GET
- ;;
- PNC EQU $
- IF NUL SECTBUF
- ;; PROCESS THE NEXT CHARACTER
- XCHG ;;INDEX TO GET/PUT IN DE
- LHLD FID&ADR ;;BASE OF BUFFER
- DAD D ;;ADDRESS OF CHAR IN HL
- XCHG ;;ADDRESS OF CHAR IN DE
- IF MD=INFILE ;;INPUT PROCESSING DIFFERS
- LHLD FID&LEN ;;FOR EOF CHECK
- MOV A,L ;;0000?
- ORA H
- MVI A,EOF ;;END OF FILE?
- RZ ;;ZERO FLAG IF SO
- LDAX D ;;NEXT CHAR IN ACCUM
- ELSE
- ;; STORE NEXT CHARACTER FROM ACCUMULATOR
- POP PSW ;;RECALL SAVED CHAR
- STAX D ;;CHARACTER IN BUFFER
- ENDIF
- LHLD FID&PTR ;;INDEX TO GET/PUT
- INX H
- SHLD FID&PTR ;;POINTER UPDATED
- ;; RETURN WITH NON ZERO FLAG IF GET
- ENDIF
- RET
- ENDIF ; IF BLOCKING
- ;;
- PSUB EQU $
- IF FID&FLG
- ;;PAST INLINE SUBROUTINE
- XRA A ;;ZERO TO ACC
- STA FCB&FID+12 ;;CLEAR EXTENT
- STA FCB&FID+32 ;;CLEAR CUR REC
- LXI H,FID&SIZ ;;BUFFER SIZE
- SHLD FID&LEN ;;SET BUFF LEN
- IF MD=INFILE ;;INPUT FILE
- SHLD FID&PTR ;;CAUSE IMMEDIATE READ
- ELSE ;;OUTPUT FILE
- LXI H,0 ;;SET NEXT TO FILL
- SHLD FID&PTR ;;POINTER INITIALIZED
- MVI C,@DEL
- LXI D,FCB&FID ;;DELETE FILE
- CALL @BDOS ;;TO CLEAR EXISTING FILE
- MVI C,@MAK ;;CREATE A NEW FILE
- ENDIF
- ;; NOW OPEN (IF INPUT), OR MAKE (IF OUTPUT)
- LXI D,FCB&FID
- LOCALT SET NUL NOLOC
- IF NOT FID&PUB OR LOCALT
- PUSH D
- MVI C,@OPN ;;OPEN FILE FUNCTION
- CALL @BDOS ;;OPEN/MAKE OK?
- INR A ;;255 BECOMES 00
- POP D
- JNZ PMSG
- ENDIF ; NUL NOLOC OR NUL PU
- IF FID&PUB AND MD=INFILE
- POPEN NOLOC
- JNZ PMSG
- ENDIF
- IF FMODE=APPEND
- MVI A,EOF ;; PRIME THE BUFFER
- STA FID&BUF
- LXI H,0 ;;SET NEXT TO FILL
- SHLD FID&PTR ;;POINTER INITIALIZED
- LXI D,FCB&FID
- MVI C,@MAK
- CALL @BDOS
- INR A ;;255 BECOMES 00
- JNZ PMSG
- ENDIF
- MVI C,@MSG ;;PRINT MESSAGE FUNCTION
- LXI D,MSG ;;ERROR MESSAGE
- CALL @BDOS ;;PRINTED AT CONSOLE
- JMP FILERR ;;TO RESTART
- MSG EQU $
- DB @CR,@LF
- IF MD=INFILE AND NOT (FMODE=APPEND) ;;INPUT MESSAGE
- DB 'NO &FID FILE'
- ELSE
- DB 'NO DIR SPACE: &FID'
- ENDIF
- DB '$'
-
- IF @SETRC=0
- BACK&FID EQU $
- LXI H,FID&SIZ ;;RESET THE LENGTH, IT MAY BE ZERO
- SHLD FID&LEN ;;IF NO EOF CHARACTER WAS FOUND
- LHLD FID&PTR ;;GET INDEX TO GET/PUT
- MOV A,L ;;IF =0000 NO EOF CHARACTER TO BACK UP OVER
- ORA H
- RZ
- DCX H
- SHLD FID&PTR ;;POINTER UPDATED
- @@&FID EQU $
- LHLD FCB&FID+33 ;;INDEX TO RANDOM RECORD #
- MOV A,L ;;=0000? BE SURE WE DON'T GO BELOW
- ORA H
- RZ
- DCX H
- SHLD FCB&FID+33 ;;POINTER UPDATED
- RET
- ENDIF
- PMSG EQU $
- ENDIF
- IF NOT (@SETRC=0)
- MVI C,@SETRC ; GET RANDOM RECORD #
- LXI D,FCB&FID
- CALL @BDOS
- IF FMODE=APPEND
- CALL @@&FID
- GLOOP EQU $ ; MOVE TO EOF IN LAST RECORD
- CALL GET&FID
- CPI EOF
- JNZ GLOOP
- CALL BACK&FID
- ENDIF ; FMODE=APPEND
- IF FID&PUB
- CALL RESET$SYSTEM
- ENDIF ; FID&PUB
- ENDIF ; @SETRC
- FID&FLG SET 0
- ENDM
- ;
- PUT MACRO DEV
- ;; WRITE CHARACTER FROM ACCUM TO DEVICE
- IF @&DEV <= @LST
- ;; SIMPLE OUTPUT
- PUSH PSW ;;SAVE CHARACTER
- MVI C,@&DEV ;;WRITE CHAR FUNCTION
- MOV E,A ;;READY FOR OUTPUT
- CALL @BDOS ;;WRITE CHARACTER
- POP PSW ;;RESTORE FOR TESTING
- ELSE
- CALL PUT&DEV
- ENDM
- ;
- FINIS MACRO FID
- ;; CLOSE THE FILE(S) GIVEN BY FID
- IRP ?F,<FID>
- ;; SKIP ALL BUT OUTPUT FILES
- IF ?F&TYP=OUTFILE
- LOCAL EOB?,PEOF,MSG,PMSG,SAMEUSR
- ;; WRITE ALL PARTIALLY FILLED BUFFERS
- EOB? EQU $
- ;;ARE WE AT THE END OF A BUFFER?
- LHLD ?F&PTR ;;NEXT TO FILL
- MOV A,L ;;ON BUFFER BOUNDARY?
- ANI (@SECT-1) AND 0FFH
- JNZ PEOF ;;PUT EOF IF NOT 00
- IF @SECT>255
- ;; CHECK HIGH ORDER BYTE ALSO
- MOV A,H
- ANI (@SECT-1) SHR 8
- JNZ PEOF ;;PUT EOF IF NOT 00
- ENDIF
- ;; ARRIVE HERE IF END OF BUFFER, SET LENGTH
- ;; AND WRITE ONE MORE BYTE TO CLEAR BUFFS
- SHLD ?F&LEN ;;SET TO SHORTER LENGTH
- PEOF EQU $
- MVI A,EOF ;;WRITE ANOTHER EOF
- PUSH PSW ;;SAVE ZERO FLAG
- CALL PUT&?F
- POP PSW ;;RECALL ZERO FLAG
- JNZ EOB? ;;NON ZERO IF MORE
- ;; BUFFERS HAVE BEEN WRITTEN, CLOSE FILE
- IF ?F&PUB
- LDA FCB&?F+36 ;; GET USER AREA OF FILE
- CPI 0FFH
- JZ SAMEUSR
- MVI C,32
- MOV E,A
- CALL @BDOS ;; GO TO FILE USER AREA
- SAMEUSR EQU $
- ENDIF
- LXI D,FCB&?F ;;FCB ADDRESS TO DE
- MVI C,@CLS
- CALL @BDOS ;; CLOSE THE FILE
- IF ?F&PUB
- CALL RESET$SYSTEM
- ENDIF
- INR A ;;255 IF ERR BECOMES 00
- JNZ PMSG
- ;; FILE CANNOT BE CLOSED
- MVI C,@MSG
- LXI D,MSG
- CALL @BDOS
- JMP PMSG ;;ERROR MESSAGE PRINTED
- MSG EQU $
- DB @CR,@LF
- DB 'CANNOT CLOSE &?F'
- DB '$'
- PMSG EQU $
- ENDIF
- ENDM ;;OF THE IRP
- ENDM
- ;
- ERASE MACRO FID
- ;; DELETE THE FILE(S) GIVEN BY FID
- IRP ?F,<FID>
- MVI C,@DEL
- LXI D,FCB&?F
- CALL @BDOS
- ENDM ;;OF THE IRP
- ENDM
- ;
- DIRECT MACRO FID
- ;; PERFORM DIRECTORY SEARCH FOR FILE
- ;; SETS ZERO FLAG IF NOT PRESENT
- LXI D,FCB&FID
- MVI C,@DIR
- CALL @BDOS
- INR A ;00 IF NOT PRESENT
- ENDM
- ;
- RENAME MACRO NEW,OLD
- ;; RENAME FILE GIVEN BY "OLD" TO "NEW"
- LOCAL PSUB,REN0
- ;; INCLUDE THE RENAME SUBROUTINE ONCE
- JMP PSUB
- @RENS EQU $
- ;;RENAME SUBROUTINE, HL IS ADDRESS OF
- ;;OLD FCB, DE IS ADDRESS OF NEW FCB
- PUSH H ;;SAVE FOR RENAME
- LXI B,16 ;;B=00,C=16
- DAD B ;;HL = OLD FCB+16
- REN0 EQU $
- LDAX D ;;NEW FCB NAME
- MOV M,A ;;TO OLD FCB+16
- INX D ;;NEXT NEW CHAR
- INX H ;;NEXT FCB CHAR
- DCR C ;;COUNT DOWN FROM 16
- JNZ REN0
- ;; OLD NAME IN FIRST HALF, NEW IN SECOND HALF
- POP D ;;RECALL BASE OF OLD NAME
- MVI C,@REN ;;RENAME FUNCTION
- CALL @BDOS
- RET ;;RENAME COMPLETE
- PSUB EQU $
- RENAME MACRO N,O ;;REDEFINE RENAME
- LXI H,FCB&O ;;OLD FCB ADDRESS
- LXI D,FCB&N ;;NEW FCB ADDRESS
- CALL @RENS ;;RENAME SUBROUTINE
- ENDM
- RENAME NEW,OLD
- ENDM
- ;
- GET MACRO DEV
- ;; READ CHARACTER FROM DEVICE
- IF @&DEV <= @LST
- ;; SIMPLE INPUT
- MVI C,@&DEV
- CALL @BDOS
- ELSE
- CALL GET&DEV
- ENDM
- ;
- POPEN MACRO NOLOC
- ; DE is assumed to point to the file FCB on entry
- OPEN SET 0FH
- LOCAL PSUB,LEAVE
- ;OPEN MAST.CAT
- * OPTION 1: TRY TO OPEN FILE IN CURRENT USER NUMBER ON CURRENT DISK
- JMP PSUB
- @OPEN EQU $
- PUSH D ; save the FCB
- MVI A,0FFH ; DECLARE CURRENT USER AREA ON FILE
- STA FILEUA
- MVI C,12 ; GET VERSION NUMBER
- CALL @BDOS
- MOV A,H ; CP/M 1.X?
- ORA L
- JZ START2$DISK ; CHECK FOR DEFAULT DISK IF SO
-
- * OPTION 2: TRY TO OPEN FILE IN USER 0 ON CURRENT DISK
- MVI E,0FFH ; GET CURRENT USER NUMBER
- MVI C,32 ; GET USER CODE
- CALL @BDOS
- MOV C,A
- LDA DEFAULT$USER ; CHECK IF AT DEFAULT USER
- CMP C
- JZ START2$DISK ; DON'T TRY IF AT DEFAULT USER AREA
- STA FILEUA ; WHERE THE FILE IS IF ANYWHERE
- MOV E,A
- MOV A,C
- STA CUR$USER ; WHERE WE ARE(SAVE FOR LATER)
- MVI C,32 ; SET USER CODE TO DEFAULT$USER
- CALL @BDOS
- IF NUL NOLOC
- POP D ; GET BACK FCB
- PUSH D ; PRESERVE THE STACK
- MVI C,OPEN
- CALL @BDOS ; TRY TO OPEN FILE AGAIN
- CPI 255 ; NOT PRESENT?
- JNZ LEAVE
- ENDIF ; NUL NOLOC
- * OPTION 3: TRY TO OPEN FILE IN USER 0 ON DEFAULT DISK IF NOT CURRENT DISK
- START2$DISK EQU $
- MVI C,25 ; DETERMINE IF CURRENT DISK IS THE DEFAULT
- CALL @BDOS
- MOV C,A
- LDA DEFAULT$DISK ; CHECK IF AT DEFAULT DISK
- CMP C
- IF NUL NOLOC
- JZ LEAVE ;FAILURE TO OPEN SINCE NOTHING LEFT TO TRY
- ENDIF
- POP H ; FCB INTO HL
- PUSH H ; PRESERVE STACK
- IF NUL NOLOC
- ELSE
- JZ START3$DISK
- ENDIF
- INR A ; ADD ONE TO DISK NUMBER
- MOV M,A ; PUT INTO FCB
- START3$DISK EQU $
- XCHG ; FCB INTO DE
- MVI C,15 ; OPEN FILE
- CALL @BDOS
- CPI 255 ; NOT PRESENT?
-
- LEAVE EQU $
- POP D ; GET THE FCB AGAIN(AND CLEAN UP STACK)
- PUSH PSW ; SAVE OPEN STATUS ON FILE
- LXI H,36
- DAD D
- LDA FILEUA ; GET THE USER AREA FOR THE FILE
- MOV M,A ; PUT USER AREA INTO FCB
- POP PSW
- RET
- ;
- RESET$SYSTEM EQU $
- PUSH PSW
- LDA CUR$USER ; CHECK USER
- CPI 0FFH ; 0FFH=NO CHANGE
- JZ RESET$RET
- MOV E,A ; USER IN E
- MVI C,32 ; GET/SET USER CODE
- CALL @BDOS
- RESET$RET EQU $
- POP PSW
- RET
-
- FILEUA EQU $
- DS 1
- PSUB EQU $
- POPEN MACRO
- CALL @OPEN
- ENDM
- POPEN
- ENDM