home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / dpl.zip / _FILEIO.D < prev    next >
Text File  |  1988-07-11  |  24KB  |  1,011 lines

  1. ; Doug's Programming Language  -- DPL, Version 2.22
  2. ; Copyright (c) 1988 Douglas S. Cody, All rights reserved.
  3. ;-----------------------=================================----------------------
  4. ;-----------------------====< _FILEIO.D STARTS HERE >====----------------------
  5. ;-----------------------=================================----------------------
  6. ;
  7. SUBPGM    _FILEIO
  8. ;
  9. ; _FILEIO contains all the routines necessary for reading & writing to
  10. ;      all the different devices in the PC. The following file types
  11. ;      are supported.
  12. ;
  13. ;        Sequential read/write of ASCII variable length records
  14. ;        Sequential read/write of ASCII/BINARY fixed length records
  15. ;        Random read/write of ASCII/BINARY fixed length records
  16. ;
  17. ; This module contains the following routines:
  18. ;
  19. ;    _FREAD  -- READ a device/file
  20. ;    _FWRITE -- WRITE to a device/file
  21. ;    _FNOTE    -- Return the current file pointer
  22. ;    _FPOINT -- Set the file pointer
  23. ;    _FOPEN    -- Open a device/file
  24. ;    _FCLOSE    -- Close a device/file
  25. ;
  26. ;
  27. EXTRN    @CR_LF:BYTE
  28. ;
  29. BEGIN    _FILEIO
  30.     EXTRN    _STREND:NEAR
  31.     RETURN
  32. ;
  33. ;------------------------===============================-----------------------
  34. ;------------------------====< FILE CLOSE ROUTINES >====-----------------------
  35. ;------------------------===============================-----------------------
  36. ;
  37. ; _FCLOSE  -- CLOSE AN OPENED FILE
  38. ;
  39. ; Entry conditions:
  40. ;    SI points to the file
  41. ; Exit conditions:
  42. ;    STATUS holds the return code
  43. ;
  44.     PUBLIC    _FCLOSE
  45. _FCLOSE    PROC    NEAR
  46.     MOV    [STATUS],0
  47.     CMP    BYTE PTR [SI+@FFOPN],01        ; SHOULD WE CLEAR BUFFERS?
  48.     JNZ    FCLO_02                ; NO, CONTINUE ON...
  49.     CALL    @WRT_BUFF_OUT            ; YES, FLUSH IT...
  50. ;
  51. FCLO_02:
  52.     SUB    AX,AX                ; FLUSH THE FILE STATE
  53.     MOV    [SI+@FFSTA],AL            ; CLEAR THE OLD STATUS
  54.     MOV    [SI+@FFSPEN],AL            ; & THE PENDING STATUS
  55.     MOV    [SI+@FFPTRL],AX            ; CLEAR THE FILE POINTERS
  56.     MOV    [SI+@FFPTRH],AX
  57.     NOT    AL
  58.     MOV    [SI+@FFOPN],AL            ; CLEAR THE OPEN STATE
  59.     MOV    BX,[SI+@FFHAN]
  60.     MOV    AH,3EH
  61.     INT    21H
  62.     JNC    FCLO_05
  63.     MOV    [STATUS],AX
  64. ;
  65. FCLO_05:
  66.     RET
  67.  
  68. _FCLOSE    ENDP
  69. ;
  70. ;
  71. ;-------------------------==============================-----------------------
  72. ;-------------------------====< FILE NOTE ROUTINES >====-----------------------
  73. ;-------------------------==============================-----------------------
  74. ;
  75. ; _FNOTE  -- NOTE THE CURRENT POSITION OF THE FILE POINTER
  76. ;
  77. ; Entry conditions:
  78. ;    SI points to the file
  79. ; Exit conditions:
  80. ;    STATUS holds the return code
  81. ;
  82.     PUBLIC    _FNOTE
  83. _FNOTE    PROC    NEAR
  84.     MOV    [STATUS],00
  85.     MOV    BX,[SI+@FFCLA]
  86.     MOV    BX,CS:NOTE_TABLE[BX]
  87.     JMP    BX
  88. ;
  89. NOTE_TABLE    LABEL    WORD
  90.     DW    NOTE_EXIT
  91.     DW    NOTE_IT
  92.     DW    NOTE_IT
  93.     DW    NOTE_EXIT
  94. ;
  95. NOTE_IT:
  96.     CMP    BYTE PTR [SI+@FFOPN],01    ; WRITE STATE?
  97.     JNZ    NTE_05            ; NO, NO NEED TO WORRY
  98.     CALL    @WRT_BUFF_OUT        ; YES, DUMP THE BUFFER FIRST
  99. ;
  100. NTE_05:
  101.     MOV    BX,[SI+@FFPTRL]
  102.     MOV    [DI+0],BX
  103.     MOV    BX,[SI+@FFPTRH]
  104.     MOV    [DI+2],BX
  105. ;
  106. NOTE_EXIT:
  107.     RET
  108.  
  109. _FNOTE    ENDP
  110. ;
  111. ;
  112. ;------------------------==============================------------------------
  113. ;------------------------====< FILE OPEN ROUTINES >====------------------------
  114. ;------------------------==============================------------------------
  115. ;
  116. ; _FOPEN  -- OPEN A DOS FILE
  117. ;
  118. ; Entry conditions:
  119. ;    SI points to the file
  120. ; Exit conditions:
  121. ;    STATUS holds the return code
  122. ;
  123.     PUBLIC    _FOPEN
  124. _FOPEN    PROC    NEAR
  125.     MOV    [STATUS],0
  126.     CMP    BYTE PTR [SI+@FFOPN],0FFH ; ALREADY OPENED?
  127.     JNE    OPENED              ; YES, EXIT IN ERROR
  128. ;
  129. ; PERFORM HOUSEKEEPING ON THE CONTROL BLOCK
  130. ;
  131.     MOV    BX,[SI+@FFCLA]
  132.     MOV    BX,CS:OPEN_TABLE[BX]
  133.     JMP    BX
  134. ;
  135. OPEN_TABLE    LABEL    WORD
  136.     DW    OPEN_CHAR_DEV
  137.     DW    OPEN_SEQ_FILE
  138.     DW    OPEN_SEQ_FILE
  139.     DW    OPEN_RND_FILE
  140. ;
  141. OPENED:
  142.     MOV    [STATUS],5
  143.     RET
  144. ;
  145. ;----------------------------------------
  146. ;
  147. OPEN_CHAR_DEV:
  148.     PUSH    AX            ; SAVE THE OPEN CODE
  149.     MOV    AH,3DH
  150.     LEA    DX,@FFNAM[SI]        ; DX POINTS TO THE FILE NAME
  151.     SUB    CX,CX
  152.     INT    21H            ; OPEN AN EXISTING FILE
  153.     JNC    OPCHR_10        ; CONTINUE ON IF GOOD...
  154.     MOV    [STATUS],AX
  155.     POP    AX            ; FLUSH...
  156.     RET
  157. ;
  158. OPCHR_10:
  159.     MOV    [SI+@FFHAN],AX        ; SAVE THE HANDLE
  160.     POP    AX
  161.     MOV    [SI+@FFOPN],AL        ; SAVE THE OPEN STATE
  162.     RET
  163. ;
  164. ;----------------------------------------
  165. ;
  166. OPEN_SEQ_FILE:
  167.     MOV    BX,[SI+@FFBUF]        ; CALCUATE THE NEW BUFFER POINTER
  168.     MOV    WORD PTR [BX+@RCUR],00    ; CLEAR THE REMAINING COUNT
  169.     ADD    BX,@RDAT
  170.     MOV    [SI+@FFBPTR],BX
  171. ;
  172.     CMP    AL,02            ; ATTEMPTING IO ON A SEQUENTIAL FILE?
  173.     JNZ    OPSQ_05            ; NO, CONTINUE ON...
  174.     MOV    [STATUS],01        ; YES, BOMB OUT
  175.     RET
  176. ;
  177. OPSQ_05:
  178.     PUSH    AX            ; SAVE THE OPEN CODE
  179.     MOV    AH,3DH
  180.     LEA    DX,@FFNAM[SI]        ; DX POINTS TO THE FILE NAME
  181.     SUB    CX,CX
  182.     CMP    AL,01            ; OUTPUT?
  183.     JZ    OPSQ_10            ; YES, CONTINUE ON...
  184.     INT    21H            ; OPEN AN EXISTING FILE
  185.     JNC    OPSQ_15            ; CONTINUE ON IF GOOD...
  186. ;
  187. OPSQ_07:
  188.     MOV    [STATUS],AX
  189.     POP    AX            ; FLUSH...
  190.     RET
  191. ;
  192. OPSQ_10:
  193.     MOV    AH,3CH            ; 'CREATE' a file
  194.     INT    21H
  195.     JC    OPSQ_07            ; EXIT IN ERROR
  196. ;
  197. OPSQ_15:
  198.     MOV    [SI+@FFHAN],AX        ; SAVE THE HANDLE
  199.     POP    AX
  200.     MOV    [SI+@FFOPN],AL        ; SAVE THE OPEN STATE
  201.     RET
  202. ;
  203. ;---------------------------------------
  204. ;
  205. OPEN_RND_FILE:
  206.     PUSH    AX        ; SAVE THE MODE
  207.     MOV    AH,3DH
  208.     LEA    DX,@FFNAM[SI]    ; DX POINTS TO THE FILE NAME
  209.     INT    21H        ; OPEN THE FILE
  210.     JC    OPRN_05        ; EXIT IF IN ERROR
  211. ;
  212. OPRN_00:
  213.     MOV    [SI+@FFHAN],AX    ; SAVE THE HANDLE
  214.     POP    BX        ; GET THE OPEN STATE
  215.     MOV    [SI+@FFOPN],BL
  216.     RET
  217. ;
  218. OPRN_05:
  219.     POP    BX        ; GET THE OPEN MODE
  220.     PUSH    BX        ; & SAVE AGAIN
  221.     CMP    AX,02        ; FILE-NOT-FOUND ERROR?
  222.     JNZ    OPRN_10        ; NO, EXIT DO TO OTHER ERROR
  223.     CMP    BL,0        ; READ ATTEMPT?
  224.     JZ    OPRN_10        ; YES, EXIT BAD
  225.     MOV    AH,3CH        ; TRY TO CREATE A FILE
  226.     SUB    CX,CX        ; MAKE IT A USEFUL FILE
  227.     LEA    DX,@FFNAM[SI]    ; DX POINTS TO THE FILE NAME
  228.     INT    21H
  229.     JNC    OPRN_00        ; EXIT IF GOOD
  230. ;
  231. OPRN_10:
  232.     MOV    [STATUS],AX    ; SAVE THE BAD RETURN CODE
  233.     POP    BX        ; FLUSH...
  234.     RET
  235.  
  236. _FOPEN    ENDP
  237. ;    
  238. ;------------------------===============================-----------------------
  239. ;------------------------====< FILE POINT ROUTINES >====-----------------------
  240. ;------------------------===============================-----------------------
  241. ;
  242. ; _FPOINT  -- MOVE A FILE POINTER
  243. ;
  244. ; Entry conditions:
  245. ;    SI points to the file
  246. ; Exit conditions:
  247. ;    STATUS holds the return code
  248. ;
  249.     PUBLIC    _FPOINT
  250. _FPOINT    PROC    NEAR
  251.     MOV    [STATUS],0
  252.     MOV    BX,[SI+@FFCLA]
  253.     MOV    BX,CS:POINT_TABLE[BX]
  254.     JMP    BX
  255. ;
  256. POINT_TABLE    LABEL    WORD
  257.     DW    POINT_EXIT
  258.     DW    POINT_SEQ
  259.     DW    POINT_SEQ
  260.     DW    POINT_EXIT
  261. ;
  262. POINT_SEQ:
  263.     CMP    BYTE PTR [SI+@FFOPN],01    ; WRITE STATE?
  264.     JNZ    PNT_05            ; NO, NO NEED TO WORRY
  265.     CALL    @WRT_BUFF_OUT        ; YES, DUMP THE BUFFER FIRST
  266. ;
  267. PNT_05:
  268.     MOV    BX,[SI+@FFBUF]        ; FLUSH THE BUFFER
  269.     MOV    WORD PTR [BX+@RCUR],00
  270.     ADD    BX,@RDAT
  271.     MOV    [SI+@FFBPTR],BX
  272.     SUB    BL,BL            ; CLEAR THE EOF FLAGS
  273.     MOV    [SI+@FFSTA],BL
  274.     MOV    [SI+@FFSPEN],BL
  275.     MOV    DX,[DI+0]        ; GET THE LSW
  276.     MOV    CX,[DI+2]        ; GET THE MSW
  277.     CALL    @DO_POINT        ; MOVE THE POINTERS
  278. ;
  279. POINT_EXIT:
  280.     RET
  281.  
  282. _FPOINT    ENDP
  283. ;
  284. ;--------------------------==============================----------------------
  285. ;--------------------------====< FILE READ ROUTINES >====----------------------
  286. ;--------------------------==============================----------------------
  287. ;
  288. ; _FREAD  -- READ DATA FROM A FILE
  289. ;
  290. ; Entry conditions:
  291. ;    SI holds the file handle
  292. ;    DI holds the target string/record
  293. ;    CX holds the length, if the file is an ascii file
  294. ;
  295. ; Exit conditions:
  296. ;    STATUS holds the result of the read
  297. ;
  298.     PUBLIC    _FREAD
  299. _FREAD    PROC    NEAR
  300.     MOV    AL,[SI+@FFSPEN]        ; ANY PENDING STATUS?
  301.     OR    AL,AL            ; (CHECKING...)
  302.     JZ    _FRD_05         ; NO, CONTINUE ON...
  303.     MOV    [SI+@FFSTA],AL        ; YES, SO SET THE BAD STATUS
  304. ;
  305. _FRD_00:
  306.     SUB    AH,AH
  307.     MOV    [STATUS],AX
  308.     MOV    [SI+@FFSPEN],AH        ; CLEAR THE PENDING STATUS
  309.     RET
  310. ;
  311. _FRD_05:
  312.     MOV    AL,[SI+@FFSTA]        ; ANY BAD STATUS?
  313.     OR    AL,AL
  314.     JNZ    _FRD_00            ; YES, EXIT NOW...    
  315.     CMP    BYTE PTR [SI+@FFOPN],01    ; OPENED FOR WRITING?
  316.     JZ    BAD_READ        ; YES, EXIT BAD
  317.     MOV    [STATUS],0
  318.     MOV    BX,[SI+@FFCLA]        ; GET THE FILE CLASS TYPE
  319.     MOV    BX,CS:READ_TBL[BX]    ; & USE AS AN INDEX
  320.     JMP    BX
  321. ;
  322. READ_TBL    LABEL    WORD
  323.     DW    READ_CHAR_DEV
  324.     DW    READ_TXT_SEQ
  325.     DW    READ_BIN_SEQ
  326.     DW    READ_BIN_RND
  327. ;
  328. BAD_READ:
  329.     MOV    [STATUS],05
  330.     RET
  331. ;
  332. ;----------------------------------------
  333. ; READ FROM A CHARACTER DEVICE (CON,AUX,COM1,COM2,ETC.)
  334. ;
  335. READ_CHAR_DEV:
  336.     PUSH    ES
  337.     PUSH    DS
  338.     POP    ES        ; ES = DATA SEGMENT
  339. ;
  340.     JCXZ    RD_CON_10    ; EXIT IF NULL
  341.     MOV    DX,DI        ; DX = TARGET STRING
  342.     MOV    BX,[SI+@FFHAN]    ; GET THE HANDLE 
  343.     MOV    AH,3FH
  344.     INT    21H        ; READ...
  345.     JNC    RD_CON_05    ; CONTINUE IF NOT IN ERROR
  346. ;
  347.     MOV    [STATUS],AX
  348.     POP    ES
  349.     RET
  350. ;
  351. RD_CON_05:
  352.     MOV    CX,AX
  353.     JCXZ    RD_CON_09    ; GO SET THE TERMINATOR
  354.     MOV    AL,0DH
  355.     CLD
  356.     REPNE    SCASB        ; FIND A C/R
  357.     JNE    RD_CON_09    ; NOT FOUND, SAVE ENTIRE STRING
  358.     DEC    DI        ; FLUSH THE C/R
  359. ;
  360. RD_CON_09:
  361.     SUB    AL,AL
  362.     STOSB            ; SET THE TERMINATOR
  363. ;
  364. RD_CON_10:
  365.     POP    ES
  366.     RET
  367. ;
  368. ;  READ FROM AN ASCII FILE
  369. ;
  370. READ_TXT_SEQ:
  371.     PUSH    ES        ; + 14    UNK
  372.     PUSH    DS
  373.     POP    ES
  374.     PUSH    BP        ; + 12    UNDEFINED
  375.     PUSH    DI        ; + 10  TARGET STRING
  376.     PUSH    CX        ; + 8   TARGET STRING LENGTH
  377.     PUSH    SI        ; + 6   FILE ADDRESS
  378.     MOV    DI,[SI+@FFBUF]    ;      GET THE BUFFER ADDRESS
  379.     MOV    AX,[SI+@FFBPTR]    ;      GET THE BUFFER POINTER
  380.     PUSH    AX        ; + 4    BUFFER POINTER
  381.     MOV    DX,[DI+@RLEN]    ;      GET THE RECORD LENGTH
  382.     MOV    CX,[DI+@RCUR]    ;      GET THE RECORD REMAINING COUNT
  383.     PUSH    CX        ; + 2   REMAINING BUFFER COUNT
  384.     SUB    DX,CX        ;      DX = AVAILABLE SPACE IN BUFFER
  385.     PUSH    DI        ; + 0    BUFFER ADDRESS
  386. ;
  387.     MOV    BP,SP        ; FRAME THE STACK
  388. ;
  389. ; MAKE SURE THERE IS DATA IN THE BUFFER
  390. ;
  391.     MOV    AX,[BP+2]    ; GET THE # OF BYTES AVAILABLE
  392.     CMP    AX,[BP+8]    ; HAVE ENOUGH IN THE BUFFER FOR THE WHOLE READ?
  393.     JG    RD_TXT_15    ; YES, SKIP TO THE READ EXTRACTION
  394. ;
  395.     ADD    DI,@RDAT    ; DI POINTS TO THE START OF THE BUFFER DATA
  396.     MOV    SI,[BP+4]    ; GET THE OLD POINTER
  397.     MOV    [BP+4],DI    ; SAVE THE NEW POINTER
  398.     JCXZ    RD_TXT_AA    ; EXIT IF FULL
  399.     CLD
  400.     REP    MOVSB        ; MOVE THE DATA TO THE FRONT OF THE BUFFER
  401. ;
  402. RD_TXT_AA:
  403. ;
  404. ; READ THE FILE FOR MORE DATA
  405. ;
  406.     MOV    CX,DX        ; ALL FULL?
  407.     JCXZ    RD_TXT_09    ; YES, CONTINUE ON...
  408. ;
  409.     MOV    DX,DI        ; GET THE TARGET POINTER
  410.     MOV    SI,[BP+6]    ; GET THE FILE ADDR
  411.     MOV    BX,[SI+@FFHAN]    ; BX = HANDLE
  412.     MOV    AH,3FH        ; FUNCTION...
  413.     INT    21H
  414.     JNC    RD_TXT_10    ; GOOD READ
  415. ;
  416. RD_TXT_05:
  417.     MOV    [STATUS],AX
  418.     MOV    SI,[BP+6]    ; GET THE FILE ADDR
  419.     MOV    [SI+@FFSTA],AL
  420. ;
  421. RD_TXT_07:
  422.     ADD    SP,12        ; DE-FRAME...
  423.     POP    BP
  424.     POP    ES
  425.     RET
  426. ;
  427. RD_TXT_09:
  428.     MOV    AX,CX        ; CLEARS AX
  429. ;
  430. RD_TXT_10:
  431.     ADD    AX,[BP+2]    ; CALC THE FULL DATA SIZE
  432.     JNZ    RD_TXT_15    ; SOME DATA IS PRESENT...
  433.     INC    AX        ; AX = 1
  434.     JMP    SHORT RD_TXT_05 ; EXIT BAD...
  435. ;
  436. ; THERE IS AT LEAST ONE BYTE AVAILABLE TO BE MOVED
  437. ;
  438. RD_TXT_15:
  439.     MOV    DX,AX        ; DX = SOURCE LENGTH
  440.     MOV    SI,[BP+4]    ; GET BUFFER POINTER
  441.     MOV    DI,[BP+10]    ; GET TARGET STRING
  442.     MOV    CX,[BP+8]    ; GET THE TARGET LENGTH
  443.     MOV    BX,0A0DH
  444.     MOV    AH,01AH        ; AH = ^Z
  445. ;
  446.     CMP    [SI],BH        ; LEADING L/F?
  447.     JNZ    RD_TXT_20    ; NO, CONTINUE ON...
  448.     DEC    DX        ; YES, IS THE LAST CHAR A L/F?
  449.     OR    DX,DX        ; (CHECKING...)
  450.     JZ    RD_TXT_30    ; YES, GO LOSE IT...
  451.     INC    SI        ; NO, MOVE PAST IT ANYWAY
  452.     CMP    [SI],AH        ; ^Z?
  453.     JNZ    RD_TXT_20    ; NO, GO MOVE SOME TEXT
  454.     DEC    SI        ; YES, MAKE A FALSE EOF
  455.     JMP    SHORT RD_TXT_30
  456. ;
  457. RD_TXT_20:
  458.     DEC    DX
  459.     JS    RD_TXT_30    ; OUT OF DATA, EXIT NOW
  460.     LODSB            ; FETCH THE CHARACTER
  461.     CMP    AL,AH        ; ^Z
  462.     JZ    RD_TXT_30
  463.     CMP    AL,BL        ; C/R
  464.     JZ    RD_TXT_25
  465.     CMP    AL,BH        ; L/F
  466.     JZ    RD_TXT_25
  467.     STOSB
  468. ;
  469. RD_TXT_21:
  470.     LOOP    RD_TXT_20
  471. ;
  472. RD_TXT_25:
  473.     SUB    AL,AL
  474.     STOSB                ; SET THE TERMINATOR
  475.     MOV    AX,SI            ; SAVE THE END POINTER
  476. ;
  477. RD_TXT_26:
  478.     MOV    SI,[BP+0]        ; GET THE BUFFER
  479.     MOV    [SI+@RCUR],DX        ; SAVE THE NEW REMAINDER
  480.     MOV    SI,[BP+6]        ; GET THE FILE OFFSET
  481.     MOV    [SI+@FFBPTR],AX        ; SET THE NEW BUFFER POINTER
  482.     MOV    BX,[BP+4]        ; GET THE ORIGINAL POINTER
  483.     SUB    AX,BX            ; AX HOLDS THE # OF BYTES EXTRACTED
  484.     ADD    [SI+@FFPTRL],AX        ; ADD TO THE FILE POINTER
  485.     ADC    WORD PTR [SI+@FFPTRH],0
  486.     JMP    RD_TXT_07        ; & EXIT HOME
  487. ;
  488. RD_TXT_30:
  489.     SUB    AL,AL
  490.     STOSB                ; SET THE TERMINATOR
  491.     MOV    AX,[BP+4]        ; GET THE BUFFER POINTER
  492.     CMP    AX,SI            ; ANY DATA READ?
  493.     MOV    AX,[BP+6]        ; (GET THE FILE ADDR FIRST...)
  494.     XCHG    AX,SI            ; AX = BUF PTR, SI = FILE PTR
  495.     JZ    RD_TXT_35        ; NO, CONTINUE ON...
  496.     MOV    BYTE PTR [SI+@FFSPEN],01; EOF PENDING ON NEXT READ
  497.     JMP    SHORT RD_TXT_26
  498. ;
  499. RD_TXT_35:
  500.     MOV    BYTE PTR [SI+@FFSTA],01; EOF PENDING RIGHT NOW
  501.     MOV    [STATUS],01
  502.     JMP    SHORT RD_TXT_26
  503. ;
  504. ;---------------------------------------
  505. ; READ_BIN_SEQ  -- READ A BINARY SEQUENTIAL FILE USING
  506. ;           FIXED RECORD LENGTH ACCESS
  507. ;
  508. READ_BIN_SEQ:
  509.     PUSH    ES        ; + 14    UNK
  510.     PUSH    DS
  511.     POP    ES
  512.     PUSH    BP        ; + 12    UNDEFINED
  513.     PUSH    DI        ; + 10  TARGET RECORD ADDRESS
  514.     MOV    CX,[DI+@RLEN]    ;       GET THE TARGET RECORD LENGTH & SAVE
  515.     PUSH    CX        ; + 8   TARGET STRING LENGTH
  516.     PUSH    SI        ; + 6   FILE ADDRESS
  517.     MOV    DI,[SI+@FFBUF]    ;      GET THE BUFFER ADDRESS
  518.     MOV    AX,[SI+@FFBPTR]    ;      GET THE BUFFER POINTER
  519.     PUSH    AX        ; + 4    BUFFER POINTER
  520.     MOV    DX,[DI+@RLEN]    ;      GET THE RECORD LENGTH
  521.     MOV    CX,[DI+@RCUR]    ;      GET THE RECORD REMAINING COUNT
  522.     PUSH    CX        ; + 2   REMAINING BUFFER COUNT
  523.     SUB    DX,CX        ;      DX = AVAILABLE SPACE IN BUFFER
  524.     PUSH    DI        ; + 0    BUFFER ADDRESS
  525. ;
  526.     MOV    BP,SP        ; FRAME THE STACK
  527. ;
  528. ; MAKE SURE THERE IS DATA IN THE BUFFER
  529. ;
  530.     MOV    AX,[BP+2]    ; GET THE # OF BYTES AVAILABLE
  531.     CMP    AX,[BP+8]    ; HAVE ENOUGH IN THE BUFFER FOR THE WHOLE READ?
  532.     JG    RD_BSEQ_15    ; YES, SKIP TO THE READ EXTRACTION
  533. ;
  534.     ADD    DI,@RDAT    ; DI POINTS TO THE START OF THE BUFFER DATA
  535.     MOV    SI,[BP+4]    ; GET THE OLD POINTER
  536.     MOV    [BP+4],DI    ; SAVE THE NEW POINTER
  537.     JCXZ    RD_BSEQ_00    ; EXIT IF FULL
  538.     CLD
  539.     REP    MOVSB        ; MOVE THE DATA TO THE FRONT OF THE BUFFER
  540. ;
  541. RD_BSEQ_00:
  542. ;
  543. ; READ THE FILE FOR MORE DATA
  544. ;
  545.     MOV    CX,DX        ; ALL FULL?
  546.     JCXZ    RD_BSEQ_09    ; YES, CONTINUE ON...
  547. ;
  548.     MOV    DX,DI        ; GET THE TARGET POINTER
  549.     MOV    SI,[BP+6]    ; GET THE FILE ADDR
  550.     MOV    BX,[SI+@FFHAN]    ; BX = HANDLE
  551.     MOV    AH,3FH        ; FUNCTION...
  552.     INT    21H
  553.     JNC    RD_BSEQ_10    ; GOOD READ
  554. ;
  555. RD_BSEQ_05:
  556.     MOV    [STATUS],AX
  557.     MOV    SI,[BP+6]    ; GET THE FILE ADDR
  558.     MOV    [SI+@FFSTA],AL
  559. ;
  560. RD_BSEQ_07:
  561.     ADD    SP,12        ; DE-FRAME...
  562.     POP    BP
  563.     POP    ES
  564.     RET
  565. ;
  566. RD_BSEQ_09:
  567.     MOV    AX,CX        ; CLEARS AX
  568. ;
  569. RD_BSEQ_10:
  570.     ADD    AX,[BP+2]    ; CALC THE FULL DATA SIZE
  571.     JNZ    RD_BSEQ_15    ; SOME DATA IS PRESENT...
  572.     INC    AX        ; AX = 1
  573.     JMP    SHORT RD_BSEQ_05 ; EXIT BAD...
  574. ;
  575. ; THERE IS AT LEAST ONE BYTE AVAILABLE TO BE MOVED
  576. ;
  577. RD_BSEQ_15:
  578.     MOV    DX,AX            ; DX = SOURCE LENGTH
  579.     MOV    CX,[BP+8]        ; GET THE TARGET LENGTH
  580.     CMP    CX,DX            ; IS TARGET GT THE REST OF THE FILE?
  581.     JLE    RD_BSEQ_20        ; NO, MOVE THE DATA
  582.     MOV    CX,DX            ; YES, SO MOVE IT & SET AN EOF
  583.     MOV    SI,[BP+6]        ; GET THE FILE
  584.     MOV    BYTE PTR [SI+@FFSTA],01    ; SET THE EOF
  585.     MOV    [STATUS],01        ; SET IMMEDIATE STATUS TOO
  586. ;
  587. RD_BSEQ_20:
  588.     SUB    DX,CX            ; DX HOLDS THE AMOUNT TO BE EXTRACTED
  589.     MOV    SI,[BP+4]        ; GET BUFFER POINTER
  590.     MOV    DI,[BP+10]        ; GET TARGET RECORD
  591.     MOV    [DI+@RCUR],CX        ; SAVE THE AMOUNT MOVED
  592.     ADD    DI,@RDAT        ; MOVE TO THE START OF THE DATA PORTION
  593.     REP    MOVSB            ; MOVE THE ENTIRE RECORD
  594. ;
  595.     MOV    AX,SI            ; SAVE THE END POINTER
  596.     MOV    SI,[BP+0]        ; GET THE BUFFER
  597.     MOV    [SI+@RCUR],DX        ; SAVE THE NEW REMAINDER
  598.     MOV    SI,[BP+6]        ; GET THE FILE OFFSET
  599.     MOV    [SI+@FFBPTR],AX        ; SET THE NEW BUFFER POINTER
  600.     MOV    BX,[BP+4]        ; GET THE ORIGINAL POINTER
  601.     SUB    AX,BX            ; AX HOLDS THE # OF BYTES EXTRACTED
  602.     ADD    [SI+@FFPTRL],AX        ; ADD TO THE FILE POINTER
  603.     ADC    WORD PTR [SI+@FFPTRH],0
  604.     JMP    RD_BSEQ_07        ; & EXIT HOME
  605. ;
  606. ;---------------------------------------
  607. ; READ_BIN_RND  -- READ A BINARY RANDOM FILE USING
  608. ;           FIXED RECORD LENGTH ACCESS
  609. ;
  610. READ_BIN_RND:
  611.     CALL    @RND_POINT        ; SET THE RANDOM FILE POINTER
  612.     JC    RDBR_05            ; EXIT IF BAD
  613.     CALL    @READ_IT        ; PERFORM THE DOS I/O
  614.     MOV    BYTE PTR [SI+@FFSTA],00    ; KILL ANY PERMENANT EOF
  615. ;
  616. RDBR_05:
  617.     RETURN
  618.  
  619. _FREAD    ENDP
  620. ;
  621. ;-------------------------===============================----------------------
  622. ;-------------------------====< FILE WRITE ROUTINES >====----------------------
  623. ;-------------------------===============================----------------------
  624. ;
  625. ; _FWRT  -- WRITE DATA TO AN OPENED FILE
  626. ;
  627. ; Entry conditions:
  628. ;    SI points to the data/record
  629. ;    DI points to the file
  630. ;    CX holds the count, if the write is to an ascii file
  631. ; Exit conditions:
  632. ;    STATUS holds the return code
  633. ;
  634.     PUBLIC    _FWRT
  635. _FWRT    PROC    NEAR
  636.     MOV    [STATUS],00
  637.     CMP    BYTE PTR [DI+@FFOPN],00 ; OPENED FOR READING ONLY?
  638.     JZ    BAD_WRITE        ; YES, SKIP OUT
  639.     MOV    BX,[DI+@FFCLA]        ; USE THE CLASS FOR AN INDEX
  640.     MOV    BX,CS:WRT_TABLE[BX]
  641.     JMP    BX
  642. ;
  643. WRT_TABLE    LABEL    WORD
  644.     DW    _WRT_UNBUF_SEQ
  645.     DW    _WRT_ASC_SEQ
  646.     DW    _WRT_BIN_SEQ
  647.     DW    _WRT_BIN_RND
  648. ;
  649. BAD_WRITE:
  650.     MOV    [STATUS],5        ; DENIED ACCESS
  651.     RET
  652. ;
  653. ;
  654. ;---------------------------------------
  655. ; _WRT_ASC_SEQ    -- WRITE ASCII TEXT TO THE DEVICE
  656. ;
  657. ; Entry conditions:
  658. ;    AX holds the CR/LF flag
  659. ;    SI points to the text
  660. ;    DI points to the file
  661. ;
  662. ; Exit conditions:
  663. ;    STATUS holds the return code
  664. ;
  665. _WRT_ASC_SEQ:
  666.     PUSH    AX        ; SAVE THE CR/LF FOR LATER
  667.     OR    SI,SI        ; ANY TEXT?
  668.     JZ    WRTAS_05    ; NO, CONTINUE ON...
  669.     MOV    DX,SI        ; DX POINTS TO THE TEXT
  670.     CALL    _STREND        ; CX HOLDS THE LENGTH
  671.     CALL    @WRT_TO_BUFF    ; WRITE IT TO THE FILE
  672.     JNC    WRTAS_05
  673.     POP    AX        ; FLUSH THE STACK
  674. ;
  675. WRTAS_EXIT:
  676.     RET
  677. ;
  678. WRTAS_05:
  679.     POP    AX
  680.     OR    AL,AL        ; DO A CR/LF?
  681.     JZ    WRTAS_EXIT    ; NO, CONTINUE ON...
  682.     MOV    CX,2
  683.     MOV    DX,OFFSET @CR_LF
  684.     CALL    @WRT_TO_BUFF    ; YES, DO IT NOW...
  685.     JMP    SHORT WRTAS_EXIT
  686. ;
  687. ;
  688. ;---------------------------------------
  689. ; _WRT_UNBUF_SEQ -- WRITE ASCII TEXT TO UNBUFFERED OUTPUT
  690. ;
  691. ; Entry conditions:
  692. ;    AX holds the CR/LF flag
  693. ;    SI points to the text
  694. ;    DI points to the file
  695. ;
  696. ; Exit conditions:
  697. ;    STATUS holds the return code
  698. ;
  699. _WRT_UNBUF_SEQ:
  700.     PUSH    AX        ; SAVE THE CR/LF FOR LATER
  701.     OR    SI,SI        ; ANY TEXT?
  702.     JZ    WRTUN_05    ; NO, CONTINUE ON...
  703.     MOV    DX,SI        ; DX POINTS TO THE TEXT
  704.     CALL    _STREND        ; CX HOLDS THE LENGTH
  705.     CALL    @WRT_IT        ; WRITE IT TO THE FILE
  706.     JNC    WRTUN_05
  707.     POP    AX        ; FLUSH THE STACK
  708. ;
  709. WRTUN_EXIT:
  710.     RET
  711. ;
  712. WRTUN_05:
  713.     POP    AX
  714.     OR    AL,AL        ; DO A CR/LF?
  715.     JZ    WRTUN_EXIT    ; NO, CONTINUE ON...
  716.     MOV    CX,2
  717.     MOV    DX,OFFSET @CR_LF
  718.     CALL    @WRT_IT        ; YES, DO IT NOW...
  719.     JMP    SHORT WRTUN_EXIT
  720. ;
  721. ;
  722. ;---------------------------------------
  723. ; _WRT_BIN_RND    -- WRITE BINARY RECORD TO THE DEVICE
  724. ;
  725. ; Entry conditions:
  726. ;    AX holds the CR/LF flag
  727. ;    SI points to the record
  728. ;    DI points to the file
  729. ;
  730. ; Exit conditions:
  731. ;    STATUS holds the return code
  732. ;
  733. _WRT_BIN_RND:
  734.     XCHG    SI,DI        ; SETUP FOR THE NEXT CALL
  735.     CALL    @RND_POINT
  736.     JC    WRBIRN_05
  737.     XCHG    SI,DI
  738.     LEA    DX,@RDAT[SI]    ; DX POINTS TO THE TEXT
  739.     MOV    CX,[SI+@RLEN]    ; CX HOLDS THE WHOLE LENGTH
  740.     CALL    @WRT_IT        ; WRITE IT TO THE FILE
  741. ;
  742. WRBIRN_05:
  743.     RET
  744. ;
  745. ;
  746. ;---------------------------------------
  747. ; _WRT_BIN_SEQ    -- WRITE BINARY RECORD TO THE DEVICE
  748. ;
  749. ; Entry conditions:
  750. ;    AX holds the CR/LF flag
  751. ;    SI points to the record
  752. ;    DI points to the file
  753. ;
  754. ; Exit conditions:
  755. ;    STATUS holds the return code
  756. ;
  757. _WRT_BIN_SEQ:
  758.     LEA    DX,@RDAT[SI]    ; DX POINTS TO THE TEXT
  759.     MOV    CX,[SI+@RLEN]    ; CX HOLDS THE CURRENT LENGTH
  760.     CALL    @WRT_TO_BUFF    ; WRITE IT TO THE FILE
  761.     RET
  762.  
  763. _FWRT    ENDP
  764. ;
  765. ;
  766. ;=====================
  767. ;   ROUTINE SECTION
  768. ;    LEVEL 1
  769. ;=====================
  770. ;
  771. ;
  772. ;---------------------------------------
  773. ; @READ_IT  -- READ THE BINARY FILE AT THE CURRENT POSITION.
  774. ;        RECORD THE NEW FILE POSITION
  775. ;
  776. ; Entry conditions:
  777. ;    SI points to the file
  778. ;    DI points to the record
  779. ; Exit conditions:
  780. ;    CARRY set = error
  781. @READ_IT PROC    NEAR
  782.     MOV    BX,[SI+@FFHAN]    ; BX = FILE HANDLE
  783.     MOV    CX,[DI+@RLEN]    ; CX = BLOCK LENGTH
  784.     LEA    DX,@RDAT[DI]    ; DX POINTS TO THE TARGET DATA AREA
  785.     MOV    AX,3F00H
  786.     INT    21H
  787.     JC    @RDIT_05    ; EXIT IF IN ERROR
  788.     MOV    [DI+@RCUR],AX    ; SAVE THE NEW RECORD LENGTH
  789.     CMP    AX,[DI+@RLEN]    ; DID WE GET THE WHOLE RECORD?
  790.     JZ    @RDIT_10    ; YES, EXIT GOOD
  791.     MOV    AX,01        ; NO, SO SET AN EOF
  792. ;
  793. @RDIT_05:
  794.     MOV    [STATUS],AX
  795.     MOV    [SI+@FFSTA],AL    ; SAVE IN THE FILE TOO...
  796. ;
  797. @RDIT_10:
  798.     RET
  799.  
  800. @READ_IT ENDP
  801. ;
  802. ;
  803. ;----------------------------------------
  804. ; @RND_POINT  -- SET THE NEW FILE POINTER BASED
  805. ;         UPON THE KEY * FILE RECORD LENGTH
  806. ;
  807. ; Entry conditions:
  808. ;    SI points to the opened file
  809. ;    DI points to the record
  810. ; Exit conditions:
  811. ;    CARRY set = error
  812. ;    CX,DX,AX modified
  813. ;
  814. @RND_POINT    PROC    NEAR
  815.     MOV    AX,[DI+@RLEN]        ; GET THE LENGTH FROM THE RECORD
  816.     MOV    BX,[SI+@FFKYW]        ; GET THE KEY OFFSET
  817.     MOV    BX,[BX]
  818.     MUL    BX            ; DX:AX HOLDS THE FILE POINTER
  819.     MOV    CX,DX
  820.     MOV    DX,AX            ; CX:DX MUST FOR DOS
  821.     CALL    @DO_POINT
  822.     RET
  823.  
  824. @RND_POINT    ENDP
  825. ;
  826. ;
  827. ;----------------------------------------
  828. ; @WRT_BUFF_OUT -- WRITE THE BUFFER TO THE DISK FILE
  829. ;
  830. ; Entry conditions:
  831. ;    SI points to the opened file
  832. ; Exit conditions:
  833. ;    CARRY set = error
  834. ;    CX,DX,AX,BX modified
  835. ;
  836. @WRT_BUFF_OUT    PROC    NEAR
  837.     MOV    CX,[SI+@FFBPTR]        ; GET THE CURRENT BUFFER POINTER
  838.     MOV    DX,[SI+@FFBUF]        ; & RESET IT
  839.     OR    DX,DX            ; ANY BUFFER USED?
  840.     JZ    WRTBFO_05        ; NO, EXIT HOME
  841.     ADD    DX,@RDAT        ; YES, CALC THE DATA ADDRESS
  842.     SUB    CX,DX            ; CX HOLDS THE LENGTH
  843.     JCXZ    WRTBFO_05        ; CONTINUE ON IF NULL
  844.     XCHG    SI,DI
  845.     CALL    @WRT_IT
  846.     XCHG    SI,DI
  847. ;
  848. WRTBFO_05:
  849.     RET
  850.  
  851. @WRT_BUFF_OUT    ENDP
  852. ;
  853. ;
  854. ;----------------------------------------
  855. ; @WRT_IT -- WRITE DATA TO THE DEVICE/FILE
  856. ;
  857. ; Entry conditions:
  858. ;    DI points to the opened file
  859. ;    DX points to the data
  860. ;    CX holds the length
  861. ; Exit conditions:
  862. ;    CARRY set = error
  863. ;    CX,DX,AX,BX modified
  864. ;
  865. @WRT_IT    PROC    NEAR
  866.     CALL    @WRT_DATA
  867.     JC    WRTIT_BAD
  868.     ADD    [DI+@FFPTRL],AX        ; CALC THE NEW POINTER
  869.     ADC    WORD PTR [DI+@FFPTRH],0
  870.     CLC
  871. ;
  872. WRTIT_BAD:
  873.     RET
  874.  
  875. @WRT_IT    ENDP
  876. ;
  877. ;
  878. ;----------------------------------------
  879. ; @WRT_TO_BUFF -- WRITE DATA TO THE BUFFER THEN TO DEVICE/FILE
  880. ;
  881. ; Entry conditions:
  882. ;    DI points to the opened file
  883. ;    DX points to the data
  884. ;    CX holds the length
  885. ; Exit conditions:
  886. ;    CARRY set = error
  887. ;    CX,DX,AX,BX modified
  888. ;
  889. @WRT_TO_BUFF    PROC    NEAR
  890.     MOV    AX,[DI+@FFBPTR]        ; GET THE CURRENT BUFFER POINTER
  891.     MOV    BX,[DI+@FFBUF]        ; AND THE START OF THE BUFFER
  892.     SUB    AX,BX            ; AX = LENGTH USED + 4
  893.     SUB    AX,@RDAT
  894.     MOV    BX,[BX]            ; GET THE FULL BUFFER LENGTH
  895.     SUB    BX,AX            ; BX HOLDS THE USEABLE SPACE...
  896.     CMP    BX,CX            ; ANY ROOM LEFT?
  897.     JGE    @WRTBF_05        ; YES, GO FILL IT...
  898. ;
  899.     PUSH    CX            ; SAVE THE COUNT
  900.     PUSH    DX            ; SAVE THE DATA PTR
  901.     MOV    CX,AX            ; CX = LENGTH TO WRITE
  902.     MOV    DX,[DI+@FFBUF]        ;
  903.     ADD    DX,@RDAT        ; DX = BUFFER
  904.     CALL    @WRT_DATA        ; GO WRITE THE BUFFER TO DISK
  905.     POP    DX            ; GET THE ORIGINAL DATA POINTER
  906.     POP    CX            ; AND LENGTH
  907.     JC    WRTBF_BAD        ; EXIT IF BAD
  908.     ADD    [DI+@FFPTRL],AX        ; CALC THE NEW POINTER
  909.     ADC    WORD PTR [DI+@FFPTRH],0
  910. ;
  911. @WRTBF_05:
  912.     PUSH    SI            ; SAVE WHATEVER...
  913.     PUSH    DI            ; SAVE THE FILE
  914.     MOV    DI,[DI+@FFBPTR]        ; GET THE BUFFER POINTER
  915.     MOV    SI,DX            ; SI POINTS TO THE SOURCE
  916.     PUSH    ES
  917.     PUSH    DS
  918.     POP    ES
  919.     CLD
  920.     REP    MOVSB            ; MOVE ALL THE BYTES INTO THE BUFFER
  921.     POP    ES
  922.     POP    SI            ; GET THE FILE
  923.     MOV    [SI+@FFBPTR],DI        ; SAVE THE NEW POINTER
  924.     MOV    DI,SI
  925.     POP    SI
  926.     CLC
  927.     RET
  928. ;
  929. WRTBF_BAD:
  930.     RET
  931.     RET
  932.  
  933. @WRT_TO_BUFF    ENDP
  934. ;
  935. ;
  936. ;=====================
  937. ;   ROUTINE SECTION
  938. ;    LEVEL 2
  939. ;=====================
  940. ;
  941. ;
  942. ;---------------------------------------
  943. ; @DO_POINT  -- POINT TO THE NEW FILE LOCATION
  944. ;
  945. ; Entry conditions:
  946. ;    SI points to the file
  947. ;    CX:DX holds the new pointer
  948. ; Exit conditions:
  949. ;    CARRY set = error
  950. ;
  951. @DO_POINT    PROC    NEAR
  952.     MOV    AX,4200H
  953.     MOV    BX,[SI+@FFHAN]
  954.     INT    21H
  955.     JNC    @DOPT_05
  956.     MOV    [STATUS],AX
  957.     RET
  958. ;
  959. @DOPT_05:
  960.     MOV    [SI+@FFPTRL],AX        ; SET THE CURRENT POSITION
  961.     MOV    [SI+@FFPTRH],DX
  962.     RET
  963.  
  964. @DO_POINT    ENDP
  965. ;
  966. ;
  967. ;----------------------------------------
  968. ; @WRT_DATA -- WRITE DATA TO THE DEVICE/FILE
  969. ;
  970. ; Entry conditions:
  971. ;    DI points to the opened file
  972. ;    DX points to the data
  973. ;    CX holds the length
  974. ; Exit conditions:
  975. ;    CARRY set = error
  976. ;    CX,DX,AX,BX modified
  977. ;    IF GOOD, AX HOLDS THE BYTES WRITTEN
  978. ;
  979. @WRT_DATA PROC    NEAR
  980.     CLC
  981.     JCXZ    WRTDT_EXIT        ; EXIT IF NO DATA
  982.     MOV    BX,[DI+@FFBUF]        ; RESET THE BUFFER POINTER
  983.     OR    BX,BX            ; ANY BUFFER USED?
  984.     JZ    WRTDT_02        ; NO, CONTINUE ON...
  985.     ADD    BX,@RDAT
  986.     MOV    [DI+@FFBPTR],BX
  987. ;
  988. WRTDT_02:
  989.     MOV    BX,[DI+@FFHAN]        ; GET THE HANDLE
  990.     MOV    AH,40H
  991.     INT    21H
  992.     JNC    WRTDT_05        ; CONTINUE IF NOT IN ERROR
  993.     MOV    [STATUS],AX
  994.     RET
  995. ;
  996. WRTDT_05:
  997.     CMP    AX,CX            ; ALL WRITTEN?
  998.     JZ    WRTDT_EXIT        ; YES, CONTINUE GOOD
  999.     MOV    BYTE PTR [DI+@FFSTA],01    ; NO, SET AN EOF STATUS
  1000.     MOV    [STATUS],01
  1001.     STC
  1002. ;
  1003. WRTDT_EXIT:
  1004.     RET
  1005.  
  1006. @WRT_DATA    ENDP
  1007. ;
  1008. ENDPGM    _FILEIO
  1009. ;
  1010.