home *** CD-ROM | disk | FTP | other *** search
- ; SEQUENTIAL FILE I/O LIBRARY
- ;
- FILERR SET 0000H ;REBOOT AFTER ERROR
- @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
- @FRD EQU 20 ;FILE READ OPERATION
- @FWR EQU 21 ;FILE WRITE OPERATION
- @MAK EQU 22 ;FILE MAKE
- @REN EQU 23 ;FILE RENAME
- @DMA EQU 26 ;SET DMA ADDRESS
- ;
- @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
- INFILE EQU 1 ;INPUT FILE
- OUTFILE EQU 2 ;OUTPUTFILE
- SETFILE EQU 3 ;SETUP NAME ONLY
- ;
- ; 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:
- 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 FID,DN,FN,FT,BS,BA
- ;; FILL THE FILE CONTROL BLOCK WITH DISK NAME
- ;; 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
- ;;
- ;; 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
- 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 20 ;;X,X,RC,DM0...DM15,CR FIELDS
- ;;
- 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:
- DW FID&BUF
- ;;
- FID&SIZ EQU @BS ;;LITERAL SIZE
- FID&LEN:
- DW @BS ;;BUFFER SIZE
- FID&PTR:
- 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: ENDM
- ;
- FILE MACRO MD,FID,DN,FN,FT,BS,BA
- ;; CREATE FILE USING MODE MD:
- ;; INFILE = 1 INPUT FILE
- ;; OUTFILE = 2 OUTPUT FILE
- ;; SETFILE = 3 SETUP FCB
- ;; (SEE FILLFCB FOR REMAINING PARAMETERS)
- LOCAL PSUB,MSG,PMSG
- LOCAL PND,EOD,EOB,PNC
- ;; CONSTRUCT THE FILE CONTROL BLOCK
- ;;
- FID&TYP EQU MD ;;SET MODE FOR LATER REF'S
- FILLFCB FID,DN,FN,FT,BS,BA
- IF MD=3 ;;SETUP FCB ONLY, SO EXIT
- EXITM
- ENDIF
- ;; FILE CONTROL BLOCK AND RELATED PARAMETERS
- ;; ARE CREATED INLINE, NOW CREATE IO FUNCTION
- JMP PSUB ;;PAST INLINE SUBROUTINE
- IF MD=1 ;;INPUT FILE
- GET&FID:
- ELSE
- PUT&FID:
- PUSH PSW ;;SAVE OUTPUT CHARACTER
- 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
- LXI H,0
- SHLD FID&PTR ;;CLEAR NEXT TO GET/PUT
- PND:
- ;; 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
- LXI D,FCB&FID ;;FCB ADDRESS TO DE
- IF MD=1 ;;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
- ORA A ;;CHECK RETURN CODE
- JNZ EOD ;;END OF FILE/DISK?
- ;; NOT END OF FILE/DISK, INCREMENT LENGTH
- 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:
- ;; END OF FILE/DISK ENCOUNTERED
- IF MD=1 ;;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: DB CR,LF
- DB 'DISK FULL: &FID'
- DB '$'
- ENDIF
- ;;
- EOB:
- ;; 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:
- ;; 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=1 ;;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
- RET
- ;;
- PSUB: ;;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=1 ;;INPUT FILE
- SHLD FID&PTR ;;CAUSE IMMEDIATE READ
- MVI C,@OPN ;;OPEN FILE FUNCTION
- 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
- CALL @BDOS ;;OPEN/MAKE OK?
- INR A ;;255 BECOMES 00
- JNZ PMSG
- MVI C,@MSG ;;PRINT MESSAGE FUNCTION
- LXI D,MSG ;;ERROR MESSAGE
- CALL @BDOS ;;PRINTED AT CONSOLE
- JMP FILERR ;;TO RESTART
- MSG: DB CR,LF
- IF MD=1 ;;INPUT MESSAGE
- DB 'NO &FID FILE'
- ELSE
- DB 'NO DIR SPACE: &FID'
- ENDIF
- DB '$'
- PMSG:
- 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=2
- LOCAL EOB?,PEOF,MSG,PMSG
- ;; WRITE ALL PARTIALLY FILLED BUFFERS
- EOB?: ;;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: 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
- MVI C,@CLS
- LXI D,FCB&?F ;;READY FOR CALL
- CALL @BDOS
- 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: DB CR,LF
- DB 'CANNOT CLOSE &?F'
- DB '$'
- PMSG:
- 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: ;;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: 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:
- 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
- ;
-