home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / MACLIB / SEQIO.LIB < prev    next >
Text File  |  2000-06-30  |  10KB  |  439 lines

  1. ;    SEQUENTIAL FILE I/O LIBRARY
  2. ;
  3. FILERR    SET    0000H    ;REBOOT AFTER ERROR
  4. @BDOS    EQU    0005H    ;BDOS ENTRY POINT
  5. @TFCB    EQU    005CH    ;DEFAULT FILE CONTROL BLOCK
  6. @TBUF    EQU    0080H    ;DEFAULT BUFFER ADDRESS
  7. ;
  8. ;    BDOS FUNCTIONS
  9. @MSG    EQU    9    ;SEND MESSAGE
  10. @OPN    EQU    15    ;FILE OPEN
  11. @CLS    EQU    16    ;FILE CLOSE
  12. @DIR    EQU    17    ;DIRECTORY SEARCH
  13. @DEL    EQU    19    ;FILE DELETE
  14. @FRD    EQU    20    ;FILE READ OPERATION
  15. @FWR    EQU    21    ;FILE WRITE OPERATION
  16. @MAK    EQU    22    ;FILE MAKE
  17. @REN    EQU    23    ;FILE RENAME
  18. @DMA    EQU    26    ;SET DMA ADDRESS
  19. ;
  20. @SECT    EQU    128    ;SECTOR SIZE
  21. EOF    EQU    1AH    ;END OF FILE
  22. CR    EQU    0DH    ;CARRIAGE RETURN
  23. LF    EQU    0AH    ;LINE FEED
  24. TAB    EQU    09H    ;HORIZONTAL TAB
  25. ;
  26. @KEY    EQU    1    ;KEYBOARD
  27. @CON    EQU    2    ;CONSOLE DISPLAY
  28. @RDR    EQU    3    ;READER
  29. @PUN    EQU    4    ;PUNCH
  30. @LST    EQU    5    ;LIST DEVICE
  31. ;
  32. ;    KEYWORDS FOR "FILE" MACRO
  33. INFILE    EQU    1    ;INPUT FILE
  34. OUTFILE    EQU    2    ;OUTPUTFILE
  35. SETFILE    EQU    3    ;SETUP NAME ONLY
  36. ;
  37. ;    THE FOLLOWING MACROS DEFINE SIMPLE SEQUENTIAL
  38. ;    FILE OPERATIONS:
  39. ;
  40. FILLNAM    MACRO    FC,C
  41. ;;    FILL THE FILE NAME/TYPE GIVEN BY FC FOR C CHARACTERS
  42. @CNT    SET    C    ;;MAX LENGTH
  43.     IRPC    ?FC,FC    ;;FILL EACH CHARACTER
  44. ;;    MAY BE END OF COUNT OR NUL NAME
  45.     IF    @CNT=0 OR NUL ?FC
  46.     EXITM
  47.     ENDIF
  48.     DB    '&?FC'    ;;FILL ONE MORE
  49. @CNT    SET    @CNT-1    ;;DECREMENT MAX LENGTH
  50.     ENDM        ;;OF IRPC ?FC
  51. ;;
  52. ;;    PAD REMAINDER
  53.     REPT    @CNT    ;;@CNT IS REMAINDER
  54.     DB    ' '    ;;PAD ONE MORE BLANK
  55.     ENDM        ;;OF REPT
  56.     ENDM
  57. ;
  58. FILLDEF    MACRO    FCB,?FL,?LN
  59. ;;    FILL THE FILE NAME FROM THE DEFAULT FCB
  60. ;;    FOR LENGTH ?LN (9 OR 12)
  61.     LOCAL    PSUB
  62.     JMP    PSUB    ;;JUMP PAST THE SUBROUTINE
  63. @DEF:    ;;THIS SUBROUTINE FILLS FROM THE TFCB (+16)
  64.     MOV    A,M    ;;GET NEXT CHARACTER TO A
  65.     STAX    D    ;;STORE TO FCB AREA
  66.     INX    H
  67.     INX    D
  68.     DCR    C    ;;COUNT LENGTH DOWN TO 0
  69.     JNZ    @DEF
  70.     RET
  71. ;;    END OF FILL SUBROUTINE
  72. PSUB:
  73. FILLDEF    MACRO    ?FCB,?F,?L
  74.     LXI    H,@TFCB+?F    ;;EITHER @TFCB OR @TFCB+16
  75.     LXI    D,?FCB
  76.     MVI    C,?L        ;;LENGTH = 9,12
  77.     CALL    @DEF
  78.     ENDM
  79.     FILLDEF    FCB,?FL,?LN
  80.     ENDM
  81. ;
  82. FILLNXT    MACRO
  83. ;;    INITIALIZE BUFFER AND DEVICE NUMBERS
  84. @NXTB    SET    0    ;;NEXT BUFFER LOCATION
  85. @NXTD    SET    @LST+1    ;;NEXT DEVICE NUMBER
  86. FILLNXT    MACRO
  87.     ENDM
  88.     ENDM
  89. ;
  90. FILLFCB    MACRO    FID,DN,FN,FT,BS,BA
  91. ;;    FILL THE FILE CONTROL BLOCK WITH DISK NAME
  92. ;;    FID IS AN INTERNAL NAME FOR THE FILE,
  93. ;;    DN IS THE DRIVE NAME (A,B..), OR BLANK
  94. ;;    FN IS THE FILE NAME, OR BLANK
  95. ;;    FT IS THE FILE TYPE 
  96. ;;    BS IS THE BUFFER SIZE
  97. ;;    BA IS THE BUFFER ADDRESS
  98.     LOCAL    PFCB
  99. ;;
  100. ;;    SET UP THE FILE CONTROL BLOCK FOR THE FILE
  101. ;;    LOOK FOR FILE NAME = 1 OR 2
  102. @C    SET    1    ;;ASSUME TRUE TO BEGIN WITH
  103.     IRPC    ?C,FN    ;;LOOK THROUGH CHARACTERS OF NAME
  104.     IF    NOT ('&?C' = '1' OR '&?C' = '2')
  105. @C    SET    0    ;;CLEAR IF NOT 1 OR 2
  106.     ENDM
  107. ;;    @C IS TRUE IF FN = 1 OR 2 AT THIS POINT
  108.     IF    @C    ;;THEN FN = 1 OR 2
  109. ;;    FILL FROM DEFAULT AREA
  110.     IF    NUL FT    ;;TYPE SPECIFIED?
  111. @C    SET    12    ;;BOTH NAME AND TYPE
  112.     ELSE
  113. @C    SET    9    ;;NAME ONLY
  114.     ENDIF
  115.     FILLDEF    FCB&FID,(FN-1)*16,@C    ;;TO SELECT THE FCB
  116.     JMP    PFCB    ;;PAST FCB DEFINITION
  117.     DS    @C    ;;SPACE FOR DRIVE/FILENAME/TYPE
  118.     FILLNAM    FT,12-@C    ;;SERIES OF DB'S
  119.     ELSE
  120.     JMP    PFCB    ;;PAST INITIALIZED FCB
  121.     IF    NUL DN
  122.     DB    0    ;;USE DEFAULT DRIVE IF NAME IS ZERO
  123.     ELSE
  124.     DB    '&DN'-'A'+1    ;;USE SPECIFIED DRIVE
  125.     ENDIF
  126.     FILLNAM    FN,8    ;;FILL FILE NAME
  127. ;;    NOW GENERATE THE FILE TYPE WITH PADDED BLANKS
  128.     FILLNAM    FT,3    ;;AND THREE CHARACTER TYPE
  129.     ENDIF
  130. FCB&FID    EQU    $-12    ;;BEGINNING OF THE FCB
  131.     DB    0    ;;EXTENT FIELD 00 FOR SETFILE
  132. ;;    NOW DEFINE THE 3 BYTE FIELD, AND DISK MAP
  133.     DS    20    ;;X,X,RC,DM0...DM15,CR FIELDS
  134. ;;
  135.     IF    FID&TYP<=2    ;;IN/OUTFILE
  136. ;;    GENERATE CONSTANTS FOR INFILE/OUTFILE
  137.     FILLNXT        ;;@NXTB=0 ON FIRST CALL
  138.     IF    BS+0<@SECT
  139. ;;    BS NOT SUPPLIED, OR TOO SMALL
  140. @BS    SET    @SECT    ;;DEFAULT TO ONE SECTOR
  141.     ELSE
  142. ;;    COMPUTE EVEN BUFFER ADDRESS
  143. @BS    SET    (BS/@SECT)*@SECT
  144.     ENDIF
  145. ;;
  146. ;;    NOW DEFINE BUFFER BASE ADDRESS
  147.     IF    NUL BA
  148. ;;    USE NEXT ADDRESS AFTER @NXTB
  149. FID&BUF    SET    BUFFERS+@NXTB
  150. ;;    COUNT PAST THIS BUFFER
  151. @NXTB    SET    @NXTB+@BS
  152.     ELSE
  153. FID&BUF    SET    BA
  154.     ENDIF
  155. ;;    FID&BUF IS BUFFER ADDRESS
  156. FID&ADR:
  157.     DW    FID&BUF
  158. ;;
  159. FID&SIZ    EQU    @BS    ;;LITERAL SIZE
  160. FID&LEN:
  161.     DW    @BS    ;;BUFFER SIZE
  162. FID&PTR:
  163.     DS    2    ;;SET IN INFILE/OUTFILE
  164. ;;    SET DEVICE NUMBER
  165. @&FID    SET    @NXTD    ;;NEXT DEVICE
  166. @NXTD    SET    @NXTD+1
  167.     ENDIF    ;;OF FID&TYP<=2 TEST
  168. PFCB:    ENDM
  169. ;
  170. FILE    MACRO    MD,FID,DN,FN,FT,BS,BA
  171. ;;    CREATE FILE USING MODE MD:
  172. ;;        INFILE = 1    INPUT FILE
  173. ;;        OUTFILE = 2    OUTPUT FILE
  174. ;;        SETFILE = 3    SETUP FCB
  175. ;;    (SEE FILLFCB FOR REMAINING PARAMETERS)
  176.     LOCAL    PSUB,MSG,PMSG
  177.     LOCAL    PND,EOD,EOB,PNC
  178. ;;    CONSTRUCT THE FILE CONTROL BLOCK
  179. ;;
  180. FID&TYP    EQU    MD    ;;SET MODE FOR LATER REF'S
  181.     FILLFCB    FID,DN,FN,FT,BS,BA
  182.     IF    MD=3    ;;SETUP FCB ONLY, SO EXIT
  183.     EXITM
  184.     ENDIF
  185. ;;    FILE CONTROL BLOCK AND RELATED PARAMETERS
  186. ;;    ARE CREATED INLINE, NOW CREATE IO FUNCTION
  187.     JMP    PSUB    ;;PAST INLINE SUBROUTINE
  188.     IF    MD=1    ;;INPUT FILE
  189. GET&FID:
  190.     ELSE
  191. PUT&FID:
  192.     PUSH    PSW    ;;SAVE OUTPUT CHARACTER
  193.     ENDIF
  194.     LHLD    FID&LEN    ;;LOAD CURRENT BUFFER LENGTH
  195.     XCHG        ;;DE IS LENGTH
  196.     LHLD    FID&PTR    ;;LOAD NEXT TO GET/PUT TO HL
  197.     MOV    A,L    ;;COMPUTE CUR-LEN
  198.     SUB    E
  199.     MOV    A,H
  200.     SBB    D    ;;CARRY IF NEXT<LENGTH
  201.     JC    PNC    ;;CARRY IF LEN GTR CURRENT
  202. ;;    END OF BUFFER, FILL/EMPTY BUFFERS
  203.     LXI    H,0
  204.     SHLD    FID&PTR    ;;CLEAR NEXT TO GET/PUT
  205. PND:
  206. ;;    PROCESS NEXT DISK SECTOR:
  207.     XCHG        ;;FID&PTR TO DE
  208.     LHLD    FID&LEN    ;;DO NOT EXCEED LENGTH
  209. ;;    DE IS NEXT TO FILL/EMPTY, HL IS MAX LEN
  210.     MOV    A,E    ;;COMPUTE NEXT-LEN
  211.     SUB    L    ;;TO GET CARRY IF MORE
  212.     MOV    A,D
  213.     SBB    H    ;;TO FILL
  214.     JNC    EOB
  215. ;;    CARRY GEN'ED, HENCE MORE TO FILL/EMPTY
  216.     LHLD    FID&ADR    ;;BASE OF BUFFERS
  217.     DAD    D    ;;HL IS NEXT BUFFER ADDR
  218.     XCHG
  219.     MVI    C,@DMA    ;;SET DMA ADDRESS
  220.     CALL    @BDOS    ;;DMA ADDRESS IS SET
  221.     LXI    D,FCB&FID    ;;FCB ADDRESS TO DE
  222.     IF    MD=1    ;;READ BUFFER FUNCTION
  223.     MVI    C,@FRD    ;;FILE READ FUNCTION
  224.     ELSE
  225.     MVI    C,@FWR    ;;FILE WRITE FUNCTION
  226.     ENDIF
  227.     CALL    @BDOS    ;;RD/WR TO/FROM DMA ADDRESS
  228.     ORA    A    ;;CHECK RETURN CODE
  229.     JNZ    EOD    ;;END OF FILE/DISK?
  230. ;;    NOT END OF FILE/DISK, INCREMENT LENGTH
  231.     LXI    D,@SECT    ;;SECTOR SIZE
  232.     LHLD    FID&PTR    ;;NEXT TO FILL
  233.     DAD    D
  234.     SHLD    FID&PTR    ;;BACK TO MEMORY
  235.     JMP    PND    ;;PROCESS ANOTHER SECTOR
  236. ;;
  237. EOD:
  238. ;;    END OF FILE/DISK ENCOUNTERED
  239.     IF    MD=1    ;;INPUT FILE
  240.     LHLD    FID&PTR    ;;LENGTH OF BUFFER
  241.     SHLD    FID&LEN    ;;RESET LENGTH
  242.     ELSE
  243. ;;    FATAL ERROR, END OF DISK
  244.     LOCAL    EMSG
  245.     MVI    C,@MSG    ;;WRITE THE ERROR
  246.     LXI    D,EMSG
  247.     CALL    @BDOS    ;;ERROR TO CONSOLE
  248.     POP    PSW    ;;REMOVE STACKED CHARACTER
  249.     JMP    FILERR    ;;USUALLY REBOOTS
  250. EMSG:    DB    CR,LF
  251.     DB    'DISK FULL: &FID'
  252.     DB    '$'
  253.     ENDIF
  254. ;;
  255. EOB:
  256. ;;    END OF BUFFER, RESET DMA AND POINTER
  257.     LXI    D,@TBUF
  258.     MVI    C,@DMA
  259.     CALL    @BDOS
  260.     LXI    H,0
  261.     SHLD    FID&PTR    ;;NEXT TO GET
  262. ;;
  263. PNC:
  264. ;;    PROCESS THE NEXT CHARACTER
  265.     XCHG        ;;INDEX TO GET/PUT IN DE
  266.     LHLD    FID&ADR    ;;BASE OF BUFFER
  267.     DAD    D    ;;ADDRESS OF CHAR IN HL
  268.     XCHG        ;;ADDRESS OF CHAR IN DE
  269.     IF    MD=1    ;;INPUT PROCESSING DIFFERS
  270.     LHLD    FID&LEN    ;;FOR EOF CHECK
  271.     MOV    A,L    ;;0000?
  272.     ORA    H
  273.     MVI    A,EOF    ;;END OF FILE?
  274.     RZ        ;;ZERO FLAG IF SO
  275.     LDAX    D    ;;NEXT CHAR IN ACCUM
  276.     ELSE
  277. ;;    STORE NEXT CHARACTER FROM ACCUMULATOR
  278.     POP    PSW    ;;RECALL SAVED CHAR
  279.     STAX    D    ;;CHARACTER IN BUFFER
  280.     ENDIF
  281.     LHLD    FID&PTR    ;;INDEX TO GET/PUT
  282.     INX    H
  283.     SHLD    FID&PTR    ;;POINTER UPDATED
  284. ;;    RETURN WITH NON ZERO FLAG IF GET
  285.     RET
  286. ;;
  287. PSUB:    ;;PAST INLINE SUBROUTINE
  288.     XRA    A        ;;ZERO TO ACC
  289.     STA    FCB&FID+12    ;;CLEAR EXTENT
  290.     STA    FCB&FID+32    ;;CLEAR CUR REC
  291.     LXI    H,FID&SIZ    ;;BUFFER SIZE
  292.     SHLD    FID&LEN        ;;SET BUFF LEN
  293.     IF    MD=1    ;;INPUT FILE
  294.     SHLD    FID&PTR    ;;CAUSE IMMEDIATE READ
  295.     MVI    C,@OPN    ;;OPEN FILE FUNCTION
  296.     ELSE        ;;OUTPUT FILE
  297.     LXI    H,0    ;;SET NEXT TO FILL
  298.     SHLD    FID&PTR    ;;POINTER INITIALIZED
  299.     MVI    C,@DEL
  300.     LXI    D,FCB&FID    ;;DELETE FILE
  301.     CALL    @BDOS    ;;TO CLEAR EXISTING FILE
  302.     MVI    C,@MAK    ;;CREATE A NEW FILE
  303.     ENDIF
  304. ;;    NOW OPEN (IF INPUT), OR MAKE (IF OUTPUT)
  305.     LXI    D,FCB&FID
  306.     CALL    @BDOS    ;;OPEN/MAKE OK?
  307.     INR    A    ;;255 BECOMES 00
  308.     JNZ    PMSG
  309.     MVI    C,@MSG    ;;PRINT MESSAGE FUNCTION
  310.     LXI    D,MSG    ;;ERROR MESSAGE
  311.     CALL    @BDOS    ;;PRINTED AT CONSOLE
  312.     JMP    FILERR    ;;TO RESTART
  313. MSG:    DB    CR,LF
  314.     IF    MD=1    ;;INPUT MESSAGE
  315.     DB    'NO &FID FILE'
  316.     ELSE
  317.     DB    'NO DIR SPACE: &FID'
  318.     ENDIF
  319.     DB    '$'
  320. PMSG:
  321.     ENDM
  322. ;
  323. PUT    MACRO    DEV
  324. ;;    WRITE CHARACTER FROM ACCUM TO DEVICE
  325.     IF    @&DEV <= @LST
  326. ;;    SIMPLE OUTPUT
  327.     PUSH    PSW    ;;SAVE CHARACTER
  328.     MVI    C,@&DEV    ;;WRITE CHAR FUNCTION
  329.     MOV    E,A    ;;READY FOR OUTPUT
  330.     CALL    @BDOS    ;;WRITE CHARACTER
  331.     POP    PSW    ;;RESTORE FOR TESTING
  332.     ELSE
  333.     CALL    PUT&DEV
  334.     ENDM
  335. ;
  336. FINIS    MACRO    FID
  337. ;;    CLOSE THE FILE(S) GIVEN BY FID
  338.     IRP    ?F,<FID>
  339. ;;    SKIP ALL BUT OUTPUT FILES
  340.     IF    ?F&TYP=2
  341.     LOCAL    EOB?,PEOF,MSG,PMSG
  342. ;;    WRITE ALL PARTIALLY FILLED BUFFERS
  343. EOB?:    ;;ARE WE AT THE END OF A BUFFER?
  344.     LHLD    ?F&PTR    ;;NEXT TO FILL
  345.     MOV    A,L    ;;ON BUFFER BOUNDARY?
  346.     ANI    (@SECT-1) AND 0FFH
  347.     JNZ    PEOF    ;;PUT EOF IF NOT 00
  348.     IF    @SECT>255
  349. ;;    CHECK HIGH ORDER BYTE ALSO
  350.     MOV    A,H
  351.     ANI    (@SECT-1) SHR 8
  352.     JNZ    PEOF    ;;PUT EOF IF NOT 00
  353.     ENDIF
  354. ;;    ARRIVE HERE IF END OF BUFFER, SET LENGTH
  355. ;;    AND WRITE ONE MORE BYTE TO CLEAR BUFFS
  356.     SHLD    ?F&LEN    ;;SET TO SHORTER LENGTH
  357. PEOF:    MVI    A,EOF    ;;WRITE ANOTHER EOF
  358.     PUSH    PSW    ;;SAVE ZERO FLAG
  359.     CALL    PUT&?F
  360.     POP    PSW    ;;RECALL ZERO FLAG
  361.     JNZ    EOB?    ;;NON ZERO IF MORE
  362. ;;    BUFFERS HAVE BEEN WRITTEN, CLOSE FILE
  363.     MVI    C,@CLS
  364.     LXI    D,FCB&?F    ;;READY FOR CALL
  365.     CALL    @BDOS
  366.     INR    A    ;;255 IF ERR BECOMES 00
  367.     JNZ    PMSG
  368. ;;    FILE CANNOT BE CLOSED
  369.     MVI    C,@MSG
  370.     LXI    D,MSG
  371.     CALL    @BDOS
  372.     JMP    PMSG    ;;ERROR MESSAGE PRINTED
  373. MSG:    DB    CR,LF
  374.     DB    'CANNOT CLOSE &?F'
  375.     DB    '$'
  376. PMSG:
  377.     ENDIF
  378.     ENDM    ;;OF THE IRP
  379.     ENDM
  380. ;
  381. ERASE    MACRO    FID
  382. ;;    DELETE THE FILE(S) GIVEN BY FID
  383.     IRP    ?F,<FID>
  384.     MVI    C,@DEL
  385.     LXI    D,FCB&?F
  386.     CALL    @BDOS
  387.     ENDM    ;;OF THE IRP
  388.     ENDM
  389. ;
  390. DIRECT    MACRO    FID
  391. ;;    PERFORM DIRECTORY SEARCH FOR FILE
  392. ;;    SETS ZERO FLAG IF NOT PRESENT
  393.     LXI    D,FCB&FID
  394.     MVI    C,@DIR
  395.     CALL    @BDOS
  396.     INR    A    ;00 IF NOT PRESENT
  397.     ENDM
  398. ;
  399. RENAME    MACRO    NEW,OLD
  400. ;;    RENAME FILE GIVEN BY "OLD" TO "NEW"
  401.     LOCAL    PSUB,REN0
  402. ;;    INCLUDE THE RENAME SUBROUTINE ONCE
  403.     JMP    PSUB
  404. @RENS:    ;;RENAME SUBROUTINE, HL IS ADDRESS OF
  405.     ;;OLD FCB, DE IS ADDRESS OF NEW FCB
  406.     PUSH    H    ;;SAVE FOR RENAME
  407.     LXI    B,16    ;;B=00,C=16
  408.     DAD    B    ;;HL = OLD FCB+16
  409. REN0:    LDAX    D    ;;NEW FCB NAME
  410.     MOV    M,A    ;;TO OLD FCB+16
  411.     INX    D    ;;NEXT NEW CHAR
  412.     INX    H    ;;NEXT FCB CHAR
  413.     DCR    C    ;;COUNT DOWN FROM 16
  414.     JNZ    REN0
  415. ;;    OLD NAME IN FIRST HALF, NEW IN SECOND HALF
  416.     POP    D    ;;RECALL BASE OF OLD NAME
  417.     MVI    C,@REN    ;;RENAME FUNCTION
  418.     CALL    @BDOS
  419.     RET        ;;RENAME COMPLETE
  420. PSUB:
  421. RENAME    MACRO    N,O    ;;REDEFINE RENAME
  422.     LXI    H,FCB&O    ;;OLD FCB ADDRESS
  423.     LXI    D,FCB&N    ;;NEW FCB ADDRESS
  424.     CALL    @RENS    ;;RENAME SUBROUTINE
  425.     ENDM
  426.     RENAME    NEW,OLD
  427.     ENDM
  428. ;
  429. GET    MACRO    DEV
  430. ;;    READ CHARACTER FROM DEVICE
  431.     IF    @&DEV <= @LST
  432. ;;    SIMPLE INPUT
  433.     MVI    C,@&DEV
  434.     CALL    @BDOS
  435.     ELSE
  436.     CALL    GET&DEV
  437.     ENDM
  438. ;
  439.