home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols000 / vol017 / sortv-12.asm < prev    next >
Assembly Source File  |  1984-04-29  |  13KB  |  767 lines

  1. ;         SORTV.ASM ver 1.2
  2. ;        by Ward Christensen
  3. ;         (revised 1/3/81)
  4. ;
  5. ;SIMPLE SORT PROGRAM FOR SORTING LISTS OF NAMES,
  6. ;OR ANY OTHER VARIABLE LENGTH FILE, WITH CR/LF
  7. ;DELIMITED RECORDS.
  8. ;
  9. ;THIS IS A "SIMPLE" PROGRAM: FILE MUST FIT IN MEMORY.
  10. ;
  11. ;--->NEEDS MAC TO ASSEMBLE<---
  12. ;
  13. ;01/03/81 Change stack init.  By Keith Petersen, W8SDZ
  14. ;
  15. ;11/15/80 Add @ command (WLC)
  16. ;
  17. ;10/24/80 Originally written by Ward Christensen
  18. ;
  19. ;FORMAT:
  20. ;    SORTV INPUT-NAME OUTPUT-NAME
  21. ; or    SORTV NAME
  22. ;
  23. ;if the second format is used, the file is read into
  24. ;memory, sorted, erased, created, and written back.
  25. ;
  26. ;    THE SORT WILL BE BASED ON THE FIRST CHARACTERS
  27. ;    IN THE FILE, UNLESS THE COMMAND IS FOLLOWED BY
  28. ;    AN "@" SIGN, THEN A STRING (1 OR MORE CHARACTERS)
  29. ;    TO SKIP.
  30. ;
  31. ;EX:    SORTV NAMES.SUB @.
  32. ;
  33. ;WILL SORT NAMES.SUB BY FILETYPE, SINCE IT SKIPS PAST
  34. ;THE "." BEFORE DOING THE COMPARE.
  35. ;
  36. EOF    EQU    1AH
  37. CR    EQU    0DH
  38. LF    EQU    0AH
  39. ;
  40. ;(FROM EQU10.LIB...)
  41. ;
  42. MF    SET    0    ;SHOW MOVE NOT REQUESTED
  43. CF    SET    0    ;SHOW COMP NOT REQUESTED
  44. ;
  45. ;DEFINE SOME MACROS TO MAKE THINGS EASIER
  46. ;
  47. ;DEFINE DATA MOVE MACRO: MOVE from,to,length
  48. ;    from may be addr, or quoted string
  49. ;
  50. MOVE    MACRO    ?F,?T,?L
  51.     MCSUB    ?F,?T,?L ;;HANDLE ARGS
  52.     CALL    MOVER
  53. MF    SET    -1    ;;SHOW EXPANSION
  54.     ENDM
  55. ;
  56. ;COMPARE MACRO
  57. COMP    MACRO    ?F,?T,?L
  58.     MCSUB    ?F,?T,?L ;;HANDLE ARGS
  59.     CALL    COMPR
  60. CF    SET    -1    ;;SHOW EXPANSION
  61.     ENDM
  62. ;
  63. ;MCSUB - HANDLES MOVE, COMPARE ARGUMENTS
  64. MCSUB    MACRO    ?F,?T,?L
  65.     IF    NOT NUL ?F
  66.     IRPC    ?C,?F
  67. ?Q    SET    '&?C&?C' ;;TEST FOR QUOTE
  68.     EXITM
  69.     ENDM
  70.     IF    ?Q EQ ''''
  71.     LOCAL    ?B,?Z
  72.     CALL    ?Z
  73. ?B    DB    ?F
  74. ?Z    POP    H    ;GET FROM
  75.     LXI    B,?Z-?B    ;GET LEN
  76.     ELSE
  77.     LXI    H,?F
  78.     ENDIF
  79.     ENDIF
  80.     IF    NOT NUL ?T
  81.     LXI    D,?T
  82.     ENDIF
  83.     IF    NOT NUL ?L
  84.     LXI    B,?L
  85.     ENDIF
  86.     ENDM
  87. ;
  88. ;DEFINE CP/M MACRO - CPM FNC,PARM [,NOSAVE]
  89. ;
  90. CPM    MACRO    ?F,?P,?N
  91.     IF    NUL ?N
  92.     PUSH    B
  93.     PUSH    D
  94.     PUSH    H
  95.     ENDIF
  96.     IF    NOT NUL ?F
  97.     MVI    C,?F
  98.     ENDIF
  99.     IF    NOT NUL ?P
  100.     LXI    D,?P
  101.     ENDIF
  102.     CALL    BDOS
  103.     IF    NUL ?N
  104.     POP    H
  105.     POP    D
  106.     POP    B
  107.     ENDIF
  108.     ENDM
  109. ;
  110. RDB    MACRO    ?F
  111.     PUSH    D
  112.     PUSH    H
  113.     LXI    H,?F
  114.     CALL    RDBYTE
  115.     POP    H
  116.     POP    D
  117.     ENDM
  118. ;
  119. WRB    MACRO    ?F
  120.     PUSH    H
  121.     LXI    H,?F
  122.     CALL    WRBYTE
  123.     POP    H
  124.     ENDM
  125. ;
  126. EFCB    MACRO    ?B,?P,?F
  127.     DW    ?B
  128.     DW    0
  129.     DB    ?P
  130.     DW    ?F
  131.     ENDM
  132. ;
  133.     ORG    100H
  134. ;
  135. ;INIT LOCAL STACK
  136. ;
  137.     LXI    SP,STACK
  138. ;
  139.     CALL    START
  140.     DB    'SORTV rev 1.2'
  141.     DB    CR,LF,'$'
  142. ;
  143. START    POP    D    ;GET ID
  144.     MVI    C,PRINT
  145.     CALL    BDOS    ;PRINT ID
  146. ;
  147. ;START OF PROGRAM EXECUTION
  148. ;
  149.     CALL    SVSKIP    ;SAVE SKIP INFO
  150.     CALL    CKNAMES    ;SEE THAT 2 NAMES ARE THERE
  151.     CALL    OPENIN    ;OPEN INPUT FILE
  152.     CALL    READN    ;READ THE NAMES
  153.     CALL    SORTN    ;SORT THE NAMES
  154.     CALL    WRITEN    ;WRITE THE NAMES
  155.     CALL    ERXIT
  156.     DB    '++DONE++$'
  157. ;
  158. ;====>    SUBROUTINES
  159. ;    ----------------
  160. ;
  161. ;====>    SAVE "SKIP TO" INFORMATION
  162. ;
  163. SVSKIP    LXI    H,81H
  164. ;
  165. SVSKL    MOV    A,M
  166.     ORA    A
  167.     RZ        ;NO 'SKIP TO'
  168.     CPI    '@'    ;SKIP DELIMITER?
  169.     INX    H
  170.     JNZ    SVSKL
  171.     LXI    D,SKIPC    ;CHARS TO SKIP
  172. ;
  173. SVSKL2    MOV    A,M
  174.     STAX    D
  175.     INX    H
  176.     INX    D
  177.     ORA    A
  178.     JNZ    SVSKL2
  179.     RET
  180. ;
  181. ;====>    CHECK THAT 2 NAMES WERE SUPPLIED
  182. ;
  183. CKNAMES    LDA    FCB+1
  184.     CPI    ' '
  185.     JZ    NONAME
  186.     LDA    FCB2+1
  187.     CPI    ' '
  188.     JZ    SAMENAM
  189.     CPI    '@'    ;SKIP PARM?
  190.     JZ    SAMENAM
  191.     MOVE    FCB2,OUTNAME,12
  192.     RET
  193. ;
  194. ;OUTPUT NAME = INPUT NAME
  195. ;
  196. SAMENAM    MOVE    FCB,OUTNAME,12
  197.     RET
  198. ;
  199. NONAME    CALL    ERXIT
  200.     DB    '++Error - ',CR,LF
  201.     DB    'Command format requires an '
  202.     DB    'input name, and an output name.$'
  203. ;
  204. ;====>    OPEN THE INPUT FILE
  205. ;
  206. OPENIN    CPM    OPEN,FCB
  207.     INR    A
  208.     RNZ        ;SUCCESSFUL?  RETURN
  209.     CALL    ERXIT
  210.     DB    '++Input file not found$'
  211. ;
  212. ;====>    READ IN THE NAMES
  213. ;
  214. READN    LXI    H,BUFF    ;TO FIRST NAME
  215. ;
  216. READNL    CALL    READL    ;READ ONE LINE
  217.     RC        ;GOT EOF, RETURN
  218.     CALL    CHAIN    ;CHAIN THINGS TOGETHER
  219.     JMP    READNL
  220. ;
  221. ;====>    READ ONE LINE
  222. ;
  223. READL    SHLD    CURR    ;SAVE CURR LINE PTR
  224.     XRA    A    ;GET 0
  225.     MOV    M,A    ;INIT FORWARD
  226.     INX    H    ;    POINTER
  227.     MOV    M,A    ;    TO
  228.     INX    H    ;    0
  229.     LXI    D,SKIPC    ;TO CK SKIP CHARS PRESENT
  230. ;
  231. READLLP    LDA    BDOS+2    ;ARE WE
  232.     DCR    A    ;    OVER-
  233.     CMP    H    ;    FLOW-
  234.     JZ    OFLO    ;    ING?
  235.     RDB    EXTFCB    ;READ A BYTE
  236.     CPI    EOF    ;SET CARRY
  237.     STC        ;    AND RETURN
  238.     RZ        ;    IF EOF
  239.     MOV    M,A    ;STORE CHAR
  240. ;TEST FOR SKIP CHAR FOUND
  241.     MOV    B,A    ;SAVE FOR COMPARE
  242.     LDAX    D
  243.     ORA    A    ;NO MORE SKIP CHARS?
  244.     JZ    READLNS    ;NO MORE
  245.     CMP    B    ;A SKIP CHAR?
  246.     JNZ    READLNS    ;NO, KEEP TRYIN.
  247.     INX    D    ;TO NEXT SKIP CHAR
  248. ;
  249. READLNS    INX    H    ;POINT TO NEXT
  250.     MOV    A,B    ;GET CHAR
  251.     CPI    CR    ;END OF LINE?
  252.     JNZ    READLLP    ;    NO, LOOP.
  253.     RDB    EXTFCB    ;GOBBLE UP LF
  254.     LDAX    D    ;GET SKIP CHAR END
  255.     ORA    A    ;TEST IT AND SET "NO EOF"
  256.     RZ
  257. ;ERROR - NO SKIP CHAR
  258.     LHLD    CURR
  259.     INX    H    ;SKIP
  260.     INX    H    ;    POINTER
  261. ;
  262. ERPLP    MOV    E,M
  263.     CPM    WRCON
  264.     MOV    A,M
  265.     INX    H
  266.     CPI    CR
  267.     JNZ    ERPLP
  268.     CALL    ERXIT
  269.     DB    LF,'++NO SKIP CHAR FOUND++$'
  270. ;
  271. OFLO    CALL    ERXIT
  272.     DB    '++File won''t fit in memory$'
  273. ;
  274. ;====>    CHAIN RECORDS TOGETHER
  275. ;
  276. CHAIN    PUSH    H    ;SAVE POINTER
  277.     LHLD    CURR    ;GET CURRENT
  278.     XCHG        ;    TO DE
  279.     LHLD    PREV    ;PREV TO HL
  280.     MOV    M,E    ;MOVE CURR
  281.     INX    H    ;    TO
  282.     MOV    M,D    ;    PREV
  283.     XCHG        ;THEN MOVE
  284.     SHLD    PREV    ;    PREV TO CURR
  285.     POP    H
  286.     RET
  287. ;
  288. ;====>    SORT THE NAMES
  289. ;
  290. SORTN    XRA    A    ;SHOW NO
  291.     STA    SWAPS    ;    SWAPS
  292.     LXI    H,PTR    ;POINT PREV
  293.     SHLD    PREV    ;    TO PTR
  294.     LHLD    PTR    ;POINT TO FIRST
  295. ;
  296. ;HANDLE WIERD CASE OF ONLY ONE NAME
  297. ;
  298.     MOV    A,M    ;GET POINTER
  299.     INX    H    ;POINT TO NEXT
  300.     ORA    M    ;OR TOGETHER
  301.     DCX    H    ;BACK UP
  302.     RZ        ;RETURN IF ONLY ONE
  303. ;
  304. SORTL    CALL    CMPR    ;COMPARE ENTRIES
  305.     CC    SWAP    ;SWAP IF WRONG ORDER
  306.     CALL    NEXT    ;POINT TO NEXT
  307.     JNC    SORTL    ;LOOP IF MORE
  308.     LDA    SWAPS    ;ANY
  309.     ORA    A    ;    SWAPS?
  310.     JNZ    SORTN    ;YES, LOOP
  311.     RET        ;NO, RETURN
  312. ;
  313. ;---->    COMPARE TWO NAMES
  314. ;
  315. CMPR    PUSH    H    ;SAVE POINTER
  316.     MOV    E,M    ;GET NEXT
  317.     INX    H    ;    POINTER
  318.     MOV    D,M    ;    TO DE
  319.     INX    D    ;ALIGN POINTERS
  320. ;
  321. ;SKIP IF NECESS
  322. ;
  323.     LXI    B,SKIPC
  324. ;
  325. TSTSKIP    LDAX    B
  326.     ORA    A
  327.     JZ    COMPL    ;NO SKIP
  328.     INX    B
  329. ;
  330. SKIP1    INX    H
  331.     CMP    M
  332.     JNZ    SKIP1
  333.     XCHG        ;SWAP
  334. ;
  335. SKIP2    INX    H
  336.     CMP    M
  337.     JNZ    SKIP2
  338.     XCHG        ;PUT THINGS BACK
  339.     JMP    TSTSKIP
  340. ;
  341. COMPL    INX    D    ;TO NEXT
  342.     INX    H    ;TO NEXT
  343.     LDAX    D    ;GET ONE
  344.     CMP    M    ;COMPARE
  345.     JNZ    COMPNE    ;NO COMPARE
  346.     CPI    CR    ;END?
  347.     JNZ    COMPL    ;    NO, LOOP
  348. ;
  349. COMPH    POP    H    ;RESTORE POINTER
  350.     RET        ;THEY ARE EQUAL
  351. ;
  352. ;COMPARE NOT EQUAL - SEE IF END OF ELEMENT,
  353. ;AND IF SO, CALL THEM EQUAL
  354. ;
  355. COMPNE    MOV    A,M
  356.     CPI    CR
  357.     JZ    COMPH
  358.     LDAX    D
  359.     CMP    M
  360.     JMP    COMPH    ;CARRY SET AS APPROP
  361. ;
  362. ;---->    SWAP ENTRIES
  363. ;
  364. ;LOGIC:    PTR points to some entry, which points
  365. ;to another entry.  They are not in order.  Thus:
  366. ;point PTR to the second, point the second to
  367. ;the first, and point the first to what the
  368. ;second USED to point to.
  369. ;
  370. SWAP    MVI    A,1
  371.     STA    SWAPS    ;SHOW WE SWAPPED
  372. ;BC=NEXT
  373.     MOV    C,M
  374.     INX    H
  375.     MOV    B,M
  376.     DCX    H
  377. ;CHAIN CURRENT TO NEXT ONES CHAIN
  378.     LDAX    B
  379.     MOV    M,A
  380.     INX    B
  381.     INX    H
  382.     LDAX    B
  383.     MOV    M,A
  384.     DCX    B
  385.     DCX    H
  386. ;SAVE CURRENT POINTER IN DE
  387.     XCHG
  388. ;GET POINTER TO PREV
  389.     LHLD    PREV
  390. ;POINT PREV TO NEXT
  391.     MOV    M,C
  392.     INX    H
  393.     MOV    M,B
  394. ;STORE CURR IN NEXT
  395.     MOV    A,E
  396.     STAX    B
  397.     INX    B
  398.     MOV    A,D
  399.     STAX    B
  400.     DCX    B
  401. ;RESTORE CURRENT POINTER
  402.     XCHG
  403.     RET        ;CURRENT POINTER IN DE
  404. ;
  405. ;---->    GET NEXT ENTRY, CARRY IF NOT 2 MORE
  406. ;
  407. NEXT    SHLD    PREV    ;SAVE POINTER
  408.     MOV    E,M
  409.     INX    H
  410.     MOV    D,M
  411.     XCHG        ;HL= NEXT
  412.     MOV    A,H    ;CARRY ON
  413.     ORA    L    ;    IF HL
  414.     STC        ;    =
  415.     RZ        ;    0
  416.     MOV    A,M    ;GET
  417.     INX    H    ;SEE IF THERE
  418.     ORA    M    ;    IS
  419.     DCX    H    ;    ANOTHER
  420.     RNZ        ;THERE IS ANOTHER
  421.     STC        ;SHOW NOT 2 TO SWAP
  422.     RET
  423. ;
  424. ;====>    WRITE THE NAMES
  425. ;
  426. WRITEN    LXI    H,0    ;INIT
  427.     SHLD    EXTFCB+2 ;    EFCB
  428.     XRA    A    ;INIT
  429.     STA    FCBEXT    ;    THE
  430.     STA    FCBRNO    ;    FCB
  431.     MOVE    OUTNAME,FCB,12 ;RESTORE NAME
  432.     CPM    ERASE,FCB
  433.     CPM    MAKE,FCB
  434.     INR    A    ;MAKE OK?
  435.     JZ    BADOUT    ;    NO, ERROR
  436.     LHLD    PTR    ;GET FIRST
  437. ;
  438. WNLP    CALL    WRITEL        ;WRITE ONE LINE
  439.     JNC    WNLP        ;LOOP IF MORE
  440.     MVI    A,EOF        ;WRITE EOF
  441.     WRB    EXTFCB        ;    CHAR
  442.     LXI    H,EXTFCB    ;FLUSH
  443.     CALL    FLUSH        ;    BUFFERS
  444.     CPM    STDMA,80H    ;RESET DMA
  445.     CPM    CLOSE,FCB    ;CLOSE,
  446.     CALL    ERXIT         ;    AND EXIT
  447.     DB    '++DONE++$'
  448. ;
  449. WRITEL    PUSH    H    ;SAVE POINTER
  450.     INX    H
  451. ;
  452. WRLP    INX    H    ;TO NEXT CHAR
  453.     MOV    A,M    ;GET CHAR
  454.     WRB    EXTFCB    ;WRITE IT
  455.     MOV    A,M    ;SEE IF END
  456.     CPI    CR    ;    OF LINE
  457.     JNZ    WRLP    ;NO, LOOP
  458.     MVI    A,LF    ;OTHERWISE
  459.     WRB    EXTFCB    ;    WRITE LF
  460.     POP    H    ;GET POINTER
  461.     MOV    E,M    ;GET 
  462.     INX    H    ;    FORWARD
  463.     MOV    D,M    ;    POINTER
  464.     XCHG        ;PUT IT IN HL
  465.     MOV    A,H    ;IS POINTER
  466.     ORA    L    ;    ZERO?
  467.     RNZ        ;NO, RETURN
  468.     STC        ;CARRY SHOWS END
  469.     RET
  470. ;
  471. BADOUT    CALL    ERXIT
  472.     DB    '++Can''t make output file$'
  473. ;
  474. ;FOLLOWING FROM 'EQU10.LIB'---->
  475. ;
  476. ;MOVE, COMPARE SUBROUTINES
  477. ;
  478.     IF    MF    ;MACRO EXPANSION FLAG SET?
  479. MOVER    MOV    A,M
  480.     STAX    D
  481.     INX    H
  482.     INX    D
  483.     DCX    B
  484.     MOV    A,B
  485.     ORA    C
  486.     JNZ    MOVER
  487.     RET
  488.     ENDIF
  489. ;
  490.     IF    CF    ;MACRO EXPANSION FLAG SET?
  491. COMPR    LDAX    D
  492.     CMP    M
  493.     RNZ
  494.     INX    D
  495.     INX    H
  496.     DCX    B
  497.     MOV    A,B
  498.     ORA    C
  499.     JNZ    COMPR
  500.     RET
  501.     ENDIF
  502. ;
  503. ;    FROM EQU10.LIB: AS OF 07/19/80
  504. ;
  505. ;RDBYTE, HL POINTS TO EXTENDED FCB:
  506. ;
  507. ;    2 BYTE BUFFER ADDR
  508. ;    2 BYTE "BYTES LEFT" (INIT TO 0)
  509. ;    1 BYTE BUFFER SIZE (IN PAGES)
  510. ;    2 BYTE FCB ADDRESS
  511. ;
  512. RDBYTE    MOV    E,M
  513.     INX    H
  514.     MOV    D,M    ;GET BUFFER ADDR
  515.     INX    H
  516.     MOV    C,M
  517.     INX    H
  518.     MOV    B,M    ;BC = BYTES LEFT
  519.     MOV    A,B    ;GET COUNT
  520.     ORA    C
  521.     JNZ    RDBNORD    ;NO READ
  522. ;
  523.     INX    H    ;TO BUFFER SIZE
  524.     MOV    A,M    ;GET COUNT
  525.     ADD    A    ;MULTIPLY BY 2
  526.     MOV    B,A    ;SECTOR COUNT IN B
  527.     INX    H    ;TO FCB
  528.     PUSH    H    ;SAVE FCB POINTER
  529.     MOV    A,M    ;GET..
  530.     INX    H    ;..FCB..
  531.     MOV    H,M    ;..ADDR..
  532.     MOV    L,A    ;..TO HL
  533. ;
  534. RDBLP    MVI    A,1AH    ;GET EOF CHAR
  535.     STAX    D    ;SAVE IN CASE EOF
  536.     PUSH    D    ;SAVE DMA ADDR
  537.     PUSH    H    ;SAVE FCB ADDR
  538.     CPM    STDMA    ;SET DMA ADDR
  539.     POP    D    ;GET FCB
  540.     CPM    READ
  541.     ORA    A
  542.     POP    H    ;HL=DMA, DE=FCB
  543.     JNZ    RDBRET    ;GOT EOF
  544.     MOV    A,L
  545.     ADI    80H    ;TO NEXT BUFF
  546.     MOV    L,A
  547.     MOV    A,H
  548.     ACI    0
  549.     MOV    H,A
  550.     XCHG        ;DMA TO DE, FCB TO HL
  551.     DCR    B    ;MORE SECTORS?
  552.     JNZ    RDBLP    ;YES, MORE
  553. ;
  554. RDBRET    POP    H    ;GET FCB POINTER
  555.     DCX    H    ;TO LENGTH
  556.     MOV    A,M    ;GET LENGTH
  557.     DCX    H    ;TO COUNT
  558.     MOV    M,A    ;SET PAGE COUNT
  559.     DCX    H    ;TO LO COUNT
  560.     DCX    H    ;TO HI FCB
  561.     DCX    H    ;TO EFCB START
  562.     JMP    RDBYTE    ;LOOP THRU AGAIN
  563. ;
  564. RDBNORD    INX    H    ;TO LENGTH
  565.     MOV    A,M    ;GET LENGTH (PAGES)
  566.     XCHG        ;BUFF TO HL
  567.     ADD    H
  568.     MOV    H,A    ;HL = END OF BUFF
  569.     MOV    A,L
  570.     SUB    C
  571.     MOV    L,A
  572.     MOV    A,H
  573.     SBB    B
  574.     MOV    H,A    ;HL = DATA POINTER
  575.     MOV    A,M    ;GET BYTE
  576.     XCHG        ;EFCB BACK TO HL
  577.     CPI    1AH    ;EOF?
  578.     RZ        ;YES, LEAVE POINTERS
  579.     DCX    B    ;DECR COUNT
  580.     DCX    H    ;BACK TO "BYTES LEFT"
  581.     MOV    M,B
  582.     DCX    H
  583.     MOV    M,C    ;STORE BACK COUNT
  584.     RET
  585. ;
  586. ;SAMPLE EFCB:
  587. ;
  588. ;EFCB    DW    BUFF    ;BUFFER ADDR
  589. ;    DW    0    ;BYTES LEFT (OR TO WRITE)
  590. ;    DB    20    ;BUFFER SIZE (IN PAGES)
  591. ;    DW    FCB    ;FCB ADDRESS
  592. ;
  593. ;
  594. ;WRBYTE, HL POINTS TO EXTENDED FCB:
  595. ;
  596. ;    2 BYTE BUFFER ADDR
  597. ;    2 BYTE "BYTES LEFT" (INIT TO 0)
  598. ;    1 BYTE BUFFER SIZE (IN PAGES)
  599. ;    2 BYTE FCB ADDRESS
  600. ;
  601. WRBYTE    MOV    E,M
  602.     INX    H
  603.     MOV    D,M    ;DE=BUF ADDR
  604.     INX    H
  605.     MOV    C,M
  606.     INX    H
  607.     MOV    B,M    ;BC=BYTES IN BUFF
  608.     PUSH    D    ;SAVE FCB
  609.     XCHG
  610.     DAD    B    ;TO NEXT BYTE
  611.     MOV    M,A    ;STORE IT
  612.     INX    B    ;ONE MORE
  613.     XCHG
  614.     POP    D
  615. ;
  616. ;SEE IF BUFFER IS FULL
  617. ;
  618.     INX    H    ;GET
  619.     MOV    A,M    ;    SIZE
  620.     CMP    B    ;FULL?
  621.     JNZ    WRBNOWR    ;NO WRITE
  622. ;
  623.     ADD    A    ;MULTIPLY BY 2
  624.     MOV    B,A    ;SECTOR COUNT IN B
  625.     INX    H    ;TO FCB
  626.     PUSH    H    ;SAVE FCB POINTER
  627.     MOV    A,M    ;GET..
  628.     INX    H    ;..FCB..
  629.     MOV    H,M    ;..ADDR..
  630.     MOV    L,A    ;..TO HL
  631. ;
  632. WRBLP    PUSH    D    ;SAVE DMA ADDR
  633.     PUSH    H    ;SAVE FCB ADDR
  634.     CPM    STDMA    ;SET DMA ADDR
  635.     POP    D    ;GET FCB
  636.     CPM    WRITE
  637.     ORA    A
  638.     POP    H    ;HL=DMA, DE=FCB
  639.     JNZ    WRBERR    ;GOT ERR
  640.     MOV    A,L
  641.     ADI    80H    ;TO NEXT BUFF
  642.     MOV    L,A
  643.     MOV    A,H
  644.     ACI    0
  645.     MOV    H,A
  646.     XCHG        ;DMA TO DE, FCB TO HL
  647.     DCR    B    ;MORE SECTORS?
  648.     JNZ    WRBLP    ;YES, MORE
  649. ;
  650. WRBRET    POP    H    ;GET FCB POINTER
  651.     DCX    H    ;TO LENGTH
  652.     DCX    H    ;TO COUNT
  653.     MVI    M,0    ;SET 0 TO WRITE
  654.     DCX    H    ;TO LO COUNT
  655.     MVI    M,0
  656.     CPM    STDMA,80H
  657.     RET
  658. ;
  659. WRBNOWR    DCX    H    ;TO LENGTH
  660.     MOV    M,B    ;SET NEW LENGTH
  661.     DCX    H
  662.     MOV    M,C
  663.     RET
  664. ;
  665. ;FLUSH THE EFCB BUFFERS
  666. ;
  667. FLUSH    MOV    E,M
  668.     INX    H
  669.     MOV    D,M    ;DE=BUF ADDR
  670.     INX    H
  671.     MOV    C,M
  672.     INX    H
  673.     MOV    B,M    ;BC=BYTES IN BUFF
  674.     INX    H    ;TO COUNT
  675.     MOV    A,B
  676.     ORA    C
  677.     RZ        ;NOTHING TO WRITE
  678.     MOV    A,C    ;GET LOW COUNT
  679.     ADD    A    ;SHIFT HIGH TO CARRY
  680.     MOV    A,B    ;GET LOW COUNTAL
  681.     RAL        ;MULT BY 2, + CARRY
  682.     INR    A    ;FUDGE FOR PARTIAL SECT
  683.     MOV    B,A    ;SAVE SECTOR COUNT
  684.     INX    H    ;TO FCB
  685.     MOV    A,M
  686.     INX    H
  687.     MOV    H,M
  688.     MOV    L,A    ;HL=FCB
  689. ;
  690. FLUSHL    CPM    STDMA
  691.     XCHG
  692.     CPM    WRITE
  693.     XCHG
  694.     ORA    A
  695.     JNZ    WRBERR
  696.     PUSH    H
  697.     LXI    H,80H
  698.     DAD    D
  699.     XCHG
  700.     POP    H
  701.     DCR    B
  702.     JNZ    FLUSHL
  703.     XCHG
  704.     CPM    CLOSE
  705.     INR    A
  706.     RNZ
  707.     CALL    ERXIT
  708.     DB    '++OUTPUT FILE CLOSE ERROR ++$'
  709. ;
  710. WRBERR    CALL    ERXIT
  711.     DB    '++OUTPUT FILE WRITE ERROR++$'
  712. ;
  713. ;EXIT WITH ERROR MESSAGE
  714. ;
  715. MSGEXIT    EQU    $    ;EXIT W/"INFORMATIONAL" MSG
  716. ;
  717. ERXIT    POP    D    ;GET MSG
  718.     MVI    C,PRINT
  719.     CALL    BDOS
  720. ;
  721. ;EXIT, RESTORING STACK AND RETURN
  722. ;
  723. EXIT    JMP    0
  724. ;
  725. ;====>    START OF WORK AREA
  726. ;
  727. EXTFCB    EFCB    DKBUF,4,FCB
  728. PREV    DW    PTR    ;POINTER TO PREV POINTER
  729. SKIPC    DB    0    ;SKIP CHARS END
  730.     DS    8    ;VARIABLE SKIP CHARS
  731. ;
  732.     DS    100    ;STACK AREA
  733. STACK    EQU    $
  734. ;
  735. OUTNAME    DS    12    ;OUTPUT FILENAME
  736. SWAPS    DS    1
  737. CURR    DS    2
  738. PTR    DS    2    ;POINTER TO FIRST NAME
  739.     ORG    ($+255) AND 0FF00H    ;TO PAGE
  740. DKBUF    DS    256*4    ;4 PAGES OF BUFFER
  741. BUFF    EQU    $    ;NAMES READ IN HERE
  742. ;
  743. ;BDOS/CBIOS EQUATES (VERSION 10)
  744. ;
  745. RDCON    EQU    1
  746. WRCON    EQU    2
  747. PRINT    EQU    9
  748. RDCONBF    EQU    10
  749. CONST    EQU    11
  750. OPEN    EQU    15
  751. CLOSE    EQU    16
  752. SRCHF    EQU    17
  753. SRCHN    EQU    18
  754. ERASE    EQU    19
  755. READ    EQU    20
  756. WRITE    EQU    21
  757. MAKE    EQU    22
  758. REN    EQU    23
  759. STDMA    EQU    26
  760. BDOS    EQU    5
  761. FCB    EQU    5CH 
  762. FCB2    EQU    6CH
  763. FCBEXT    EQU    FCB+12
  764. FCBRNO    EQU    FCB+32
  765. ;
  766.     END
  767.