home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol097 / cct.asm < prev    next >
Encoding:
Assembly Source File  |  1984-04-29  |  24.8 KB  |  1,177 lines

  1.     title    'CCT.ASM    05/29/82'
  2.  
  3. ;Used to combine multiple small files into one large file.
  4.  
  5. ;command format:
  6.  
  7. ;    CCT output [string] ]string[ = input1 , input2....
  8.  
  9. ;;    blanks may be used before and after (but not
  10. ;;    within) the filenames for readability. The
  11. ;;    commas are also optional, except there must be
  12. ;;    something separating the filenames.
  13.  
  14. ;;The input and output files may have the standard form
  15. ;;        drive:filename.ext
  16. ;;    where the drive may be A: to N: and is optional,
  17. ;;    and ext is the optional file extension.
  18.  
  19. ;;If the output filename is * (not *.*), the program will
  20. ;;    create the file $$$.SUB on drive A in correct SUBMIT
  21. ;;    format. That is, CCT can be used as a replacement
  22. ;;    for SUBMIT, except for parameter substitution. The
  23. ;;    program will automatically stop at 128 lines of input,
  24. ;;    since that is what most CP/M systems allow.
  25.  
  26. ;;The [string] is the optional prefix string, which will be
  27. ;;    put at the beginning of every line of the output file.
  28. ;;    The [ and ] are required punctuation, and the ] cannot
  29. ;;    be within the string, tho almost anything else can be.
  30. ;;    The surrounding brackets will not be included in the
  31. ;;    string. When present, the prefix string will always be
  32. ;;    the first characters of the output file, unless the
  33. ;;    output is completely empty.
  34.  
  35. ;;The ]string[ is the optional suffix string, which will be
  36. ;;    put at the end of every line on the output file. The
  37. ;;    ] and [ are required punctuation, and the [ cannot be
  38. ;;    within the string. The suffix string may be specified
  39. ;;    in the command line in front of the prefix string, as
  40. ;;    long as both are after the output filename and before
  41. ;;    the equal sign (=)
  42.  
  43. ;;An input filename %N will give a CRLF (hex 0D 0A)
  44. ;;An input filename %F will give a Formfeed (hex 0C)
  45. ;;An input filename %T will give a Tab (^I, hex 09)
  46.  
  47. ;;An input file name of n (a number from 1 to 65535) will cause
  48. ;;    an automatic CRLF after "n" characters on one line. The
  49. ;;    CR and LF are not counted in the number of characters
  50. ;;    per line, and this option will hold for all successive
  51. ;;    files until changed. Any characters being inserted
  52. ;;    by prefix or suffix strings are not counted. To turn
  53. ;;    off this option after using it on an earlier input file,
  54. ;;    use option 65535
  55.  
  56. ;;An input file name of +n (a number from 1 to 65565) will cause
  57. ;;    the program to skip the first "n" lines of each following
  58. ;;    input file, until changed. To turn this option back off,
  59. ;;    specify option +0
  60.  
  61. ;;An input file name of -n (a number from 1 to 65535) will cause
  62. ;;    the program to stop after the "n"th line is read from
  63. ;;    each file, until changed. To turn this option back off,
  64. ;;    specify an option of -65535
  65.  
  66. ;;The "n" "+n" and "-n" options are absolutely independent of each
  67. ;;    other, and may appear many times in the command, each or
  68. ;;    together.
  69.  
  70. ;;An * as an input  filename, such as A=* or A=B,*,C will
  71. ;;    switch to the console for input. All the standard
  72. ;;    line-editing functions are available, such as
  73. ;;    backspacing. Up to 254 characters may be input,
  74. ;;    and the input terminates with a null line or a
  75. ;;    EOF (Control-Z, hex 1A)
  76.  
  77. ;;If the output file is omitted (no =), the console will
  78. ;;    be the destination
  79.  
  80. ;; For example :
  81.  
  82. ;;    CCT -60 CCT.ASM        Types the first 60 lines of CCT.ASM
  83.  
  84. ;;    CCT A = B FOO.ASM    Concatenates B and FOO.ASM giving A
  85.  
  86. ;;    CCT A,C:B,C        Concatenates A, B (from the C drive),
  87. ;;                 and C with output to the console
  88.  
  89. ;;    CCT A=*            Create file A from your console input
  90.  
  91. ;;    CCT A = *, +5 X.ASM    Accepts whatever you type in, followed
  92. ;;                by all but the first 5 lines of X.ASM
  93.  
  94. ;;            Note: CCT works under XSUB and will accept
  95. ;;            the input from the "console" that XSUB
  96. ;;            fakes out. Use the ^z to terminate input.
  97.  
  98. ;;    CCT NEW.ASM=OLD.ASM    Copies OLD.ASM to NEW.ASM
  99. ;;                NOTE:  only for ASCII files
  100.  
  101. ;;    CCT X.ASM = Y %N Z    Concatenates Y, adds a CRLF, then Z
  102. ;;                 output going to X.ASM
  103.  
  104. ;;    CCT %N %N %N %N        Sends four CRLFs to the console
  105.  
  106. ;;    CCT COMMENT.ASM [; ] = COMMENT.DOC  Puts a ; and a blank at
  107. ;;                the beginning of every line in the
  108. ;;                .DOC file and puts the results in
  109. ;;                the COMMENT.ASM file
  110.  
  111. ;;    CCT * = *        Accepts a series of commands from
  112. ;;                the console, and creates a submit
  113. ;;                file that will automatically start
  114. ;;                executing when CCT is done.
  115.  
  116. ;;    CCT * [PIP C:=B:] = NAMES.SUB  Puts "PIP C:=B:" in front of
  117. ;;                every line from NAMES.SUB and will
  118. ;;                submit the results to CP/M. This may
  119. ;;                be useful if NAMES.SUB is a list of
  120. ;;                files on drive B:
  121.  
  122. ;;            Note: Ward Christensen's FMAP utility
  123. ;;            can create a file containing a list
  124. ;;            of filenames. This is very handy.
  125.  
  126. ;;    CCT -5 A B        Will type the first 5 lines of file A
  127. ;;                followed by the first 5 lines of file B.
  128.  
  129. ;;    CCT B = +6 A        Will copy file A to file B, skipping
  130. ;;                the first 6 lines of A.
  131.  
  132. ;;    CCT -7 A +5 B        Will copy the first 7 lines of file A
  133. ;;                followed by lines 6 and 7 of file B.
  134.  
  135. ;;    CCT 80 C        Will type file C, putting an automatic
  136. ;;                CR-LF every 80 bytes on every line that
  137. ;;                is over 80 bytes long. Lines under 80
  138. ;;                bytes long will be unchanged.
  139.  
  140. ;;    CCT D = -7 E -9 F    Will type the first 7 lines of E followed
  141. ;;                by the first 9 lines of F.
  142.  
  143.  
  144. ;;Bugs or restrictions
  145.  
  146. ;;    If BLKSIZE is 16, as supplied, the program will require a
  147. ;;        a minimum 24K CP/M system, and will allow a maximum
  148. ;;        of 128 (16K/128) lines of Submit output. The BLKSIZE
  149. ;;        does not affect other types of files except for per-
  150. ;;        formance.
  151.  
  152. ;;    Ambiguous filenames are not allowed (no ? in filename)
  153. ;;        The files might not be concatenated in the order
  154. ;;        you wanted anyway.
  155.  
  156. ;;    As the exception to the above statement, an output filename
  157. ;;        beginning with ? will be treated as *, because it was
  158. ;;        not deemed worth the effort to put in any extra code.
  159.  
  160. ;;    If the output file exists, it will be erased and replaced,
  161. ;;        so CCT A = A,B  will not do what you want
  162.  
  163. ;;    A filename with nothing but an extension ( .ASM) is con-
  164. ;;        sidered an error
  165.  
  166. ;;    It is possible to use a file called %N, %F, %T, +n, -n, or n
  167. ;;        - just put a period after it, e.g. %N. or +5. or 988.
  168.  
  169. ;;    Multiple commas get swallowed - A,,,B is wierd but OK.
  170. ;;        This might be useful in a submit file if a parameter
  171. ;;        is missing, such as   CCT $1=$2,$3,$4
  172.  
  173. ;;    The program will stop when it hits a Control-Z (hex 1A), so
  174. ;;        using it to copy .COM files is not recommended.
  175.  
  176. ;;    There will be only one Control-Z at the end, but there will
  177. ;;        always be one there, even if the input files do not
  178. ;;        have one, & that will be the only one in the file.
  179.  
  180. ;;    When creating a file from console input, it is possible to
  181. ;;        choose whether there will be a CR-LF (hex 0D 0A) at
  182. ;;        the end. If you want it, stop with a null line. If
  183. ;;        you don't, stop by typing a Control-Z before hitting
  184. ;;        Return on the last line.
  185.  
  186. ;;    Entering an ASCII NUL (hex 00, Control-@) can cause wierd
  187. ;;        problems anywhere in CP/M, and should be avoided.
  188.  
  189. ;;    Entering CCT * will echo console input back to the console,
  190. ;;        but most systems will not see anything, because the
  191. ;;        output line will exactly overlay the input line.
  192. ;;        This command might be useful for Microshell, tho.
  193.  
  194. ;;    The brackets [ and ] must be paired right, and may not appear
  195. ;;        in the output or any input filename.
  196.  
  197. ;;    The %N is not changed into a CRLF within the prefix and suffix
  198. ;;        strings. In fact, I haven't found a way of getting
  199. ;;        a CRLF into the strings yet.
  200.  
  201. ;;    If you want prefix or suffix strings on console output, you
  202. ;;        must put an = after the strings. Under any other con-
  203. ;;        dition, you cannot use an = if you want console out.
  204. ;;        E.g. CCT [<<<]=A and CCT A are legal, CCT =A is not
  205.  
  206. ;;    It is adviseable to put spaces in between the output filename
  207. ;;        and the [ or ] if a prefix or suffix string is desired.
  208. ;;        In some versions of CP/M, if you are putting "funny"
  209. ;;        characters in the strings, it may be necessary to put a 
  210. ;;        . (period) before the strings start (and after the output
  211. ;;        filename) e.g.   CCT A . [^I.A::^I::??] = B
  212.  
  213. ;;    If * is the output filename, the file $$$.SUB will be erased
  214. ;;        on the A: drive and a new file will be created. This
  215. ;;        may be desireable or not, but it will happen. It is
  216. ;;        possible to use CCT to chain to another file at the
  217. ;;        end of a submit file if the CCT *=filename is the
  218. ;;        last command in the first Submit file. CCT will acc-
  219. ;;        null lines from the input file, unlike Submit.
  220.  
  221. ;;    The algorithm used for the prefix and suffix strings will in-
  222. ;;        tentionally not put the strings on the last line of
  223. ;;        the output file, if that line is empty. That is, if
  224. ;;        the end of the last file is CR LF EOF, the output file
  225. ;;        will also be that way.
  226.  
  227. ;;    The algorithm used for line determination also treats the CR and
  228. ;;        LF as equivalent, and basically nul - that is, it doesn't
  229. ;;        care whether there is a CR, a CR-LF, an LF, or maybe CR-
  230. ;;        LF-CR-LF-LF, they're all the same. This most seriously
  231. ;;        affects the +n and -n options if there are nul lines.
  232.  
  233. ;;    If both are used, the + number must be less than the - number, or
  234. ;;        there will be no output from that file. The file(s) will
  235. ;;        be opened, though, so that might be a way of testing for
  236. ;;        files. For example,  CCT -0 +1 A B  just sees if files
  237. ;;        A and B are present.
  238.  
  239. ;;    The character-per-line counter (used by the "n" option) does not
  240. ;;        treat tabs specially - that is, tabs are not expanded when
  241. ;;        computing the number of characters on the line.
  242.  
  243. ;adapted from    'COMBINE.ASM'
  244. ;12/10/78 BY Ward Christensen
  245.  
  246. ;Modified by Bob Van Valzah & Steve Ness on 1/9/79 to allow
  247. ;source files on any drive and remove comments preceded by blanks.
  248.  
  249. ;Modified by Steve Ness on 12/20/79 to allow filetypes on source files.
  250.  
  251. ;; 05/16/82 by Chuck Weingart, take out comment killer (above),
  252. ;;    add the %n inserter, rename to CCT to make a UNIX-like
  253. ;;    filter (the name CAT was already taken), add more error
  254. ;;    checks, allow console input, add prefix and suffix strings,
  255. ;;    and ignore blanks on command line.
  256.  
  257. ;; 05/29/82 by Chuck Weingart, Add the %F and %T inserter from an
  258. ;;    idea of Jim Mills. Add GETNUM and the line and character
  259. ;;    counters etc. code to restrict the output. Includes code
  260. ;;    from /.ASM by John M. Kodis, CP/M U.G. contribution Novem-
  261. ;;    ber 1980, on CPMUG 78. (Based on "/.COM", CPMUG 40.1,
  262. ;;    originally written by Ward Christensen)
  263.  
  264. TEST    EQU    0
  265. ;;        The BLKSIZE parameter determines the maximum
  266. ;;        number of lines allowed in a $$$.SUB file, and
  267. ;;        is used otherwise for efficiency.
  268. K    EQU    1024    ;1K
  269. BLKSIZE    EQU    16*K    ;OUTPUT FILE BLOCKSIZE
  270. ;;
  271. tpa    equ    100h    ;transient program area
  272. ;;
  273. EOF    EQU    1AH    ;;Control-Z
  274. CR    EQU    0DH    ;;Carriage Return
  275. LF    EQU    0AH    ;;Line Feed
  276. ;
  277. ;(FROM EQU7.LIB...)
  278. MF    SET    0    ;SHOW MOVE NOT REQUESTED
  279. CF    SET    0    ;SHOW COMP NOT REQUESTED
  280.  
  281. ;
  282. ;DEFINE SOME MACROS TO MAKE THINGS EASIER
  283. ;
  284. ;DEFINE DATA MOVE MACRO
  285. ;
  286. MOVE    MACRO    ?F,?T,?L,?I
  287.     IF    NOT NUL ?F
  288.     LXI    H,?F
  289.     ENDIF
  290.     IF    NOT NUL ?T
  291.     LXI    D,?T
  292.     ENDIF
  293.     IF    NOT NUL ?L
  294.     LXI    B,?L
  295.     ENDIF
  296.     IF    NOT NUL ?I
  297.     LOCAL    ?B,?Z
  298.     CALL    ?Z
  299. ?B    DB    ?I
  300. ?Z    POP    H    ;GET TO
  301.     LXI    B,?Z-?B
  302.     ENDIF
  303.     CALL    MOVER
  304. MF    SET    -1    ;;SHOW EXPANSION
  305.     ENDM
  306. ;COMPARE MACRO
  307. COMP    MACRO    ?F,?T,?L,?I
  308.     IF    NOT NUL ?F
  309.     LXI    H,?F
  310.     ENDIF
  311.     IF    NOT NUL ?T
  312.     LXI    D,?T
  313.     ENDIF
  314.     IF    NOT NUL ?L
  315.     LXI    B,?L
  316.     ENDIF
  317.     IF    NOT NUL ?I
  318.     LOCAL    ?B,?Z
  319.     CALL    ?Z
  320. ?B    DB    ?I
  321. ?Z    POP    D    ;GET TO
  322.     LXI    B,?Z-?B
  323.     ENDIF
  324.     CALL    COMPR
  325. CF    SET    -1    ;;SHOW EXPANSION
  326.     ENDM
  327. ;
  328. ;DEFINE CP/M MACRO - CPM FNC,PARM
  329. ;
  330. CPM    MACRO    ?F,?P
  331.     PUSH    B
  332.     PUSH    D
  333.     PUSH    H
  334.     IF    NOT NUL ?F
  335.     MVI    C,?F
  336.     ENDIF
  337.     IF    NOT NUL ?P
  338.     LXI    D,?P
  339.     ENDIF
  340.     CALL    BDOS
  341.     POP    H
  342.     POP    D
  343.     POP    B
  344.     ENDM
  345. ;
  346.     ORG    tpa
  347. ;INIT LOCAL STACK
  348. ;
  349.     LXI    H,0
  350.     DAD    SP
  351.     SHLD    STACK
  352.     LXI    SP,STACK
  353.     lxi    h,cibuf
  354.     mov    a,l    ;;from /.asm
  355.     add    m
  356.     inr    a
  357.     mov    l,a
  358.     mvi    m,0    ;zero the byte after the end of the command line.
  359. ;
  360. ;
  361. ;START OF PROGRAM EXECUTION
  362. ;
  363. ;MOVE THE COMMAND BUFFER
  364.     MOVE    cibuf,HOLD,128 ;FROM,TO,LENGTH
  365.     COMP    FCB,,,<0,'?'>
  366.     JNZ    POSITION ;;check for *, or a close resemblance
  367.     COMP    FCB+9,,,'   '
  368.     JNZ    POSITION
  369.     MVI    A,0C3H    ;;now flag the *
  370.     STA    STRFLAG
  371. POSITION    ; TO FIRST NAME TO COPY (FOLLOWS =)
  372.     LXI    H,HOLD
  373.     SHLD    NAMEADD    ;;save in case of no file
  374. SKIPEQ    INX    H
  375.     MOV    A,M
  376.     ORA    A    ;;check if end of line
  377.     JZ    CONSOL
  378.     CPI    '['    ;;look for boxes
  379.     JZ    SKIPBRK
  380.     CPI    ']'
  381.     JZ    S2IPBRK
  382.     CPI    '='
  383.     JNZ    SKIPEQ
  384.     SHLD    NAMEADD    ;SAVE POINTER
  385.     LDA    STRFLAG
  386.     ORA    A    ;;see if got the *
  387.     JZ    QMTEST
  388.     MOVE    XFCB,FCB,24
  389.     lxi    h,subbuf+1;hl is the destination pointer.
  390.     SHLD    SUBOUT
  391.     LXI    H,BLKSIZE/128    ;;maximum number of lines
  392.     SHLD    MINSNUM
  393.     JMP    EQDONE
  394. QMTEST
  395.     LXI    H,FCB+1    ;;now set up to scan FCB
  396.     MOV    A,M
  397.     MVI    B,11
  398. QMLOOP
  399.     CPI    '='    ;;see if got equal in filename
  400.     JZ    EQLOOP
  401.     CPI    '>'
  402.     JZ    EQLOOP
  403.     CPI    '?'    ;;see if ambiguous
  404.     JZ    QMFILE
  405.     CPI    '['    ;;kill the boxes, too
  406.     JZ    EQLOOP
  407.     CPI    ']'
  408.     JZ    EQLOOP
  409.     INX    H    ;;check next character
  410.     MOV    A,M
  411.     DCR    B    ;;see if done
  412.     JNZ    QMLOOP
  413. ;ERASE THE OUTPUT FILE
  414. EQDONE
  415.     LDA    FCB+1    ;;see if error
  416.     CPI    ' '
  417.     JZ    NOFILE2
  418.     IF    NOT TEST
  419.     CPM    delete,FCB
  420.     CPM    makef,FCB
  421.     INR    A
  422.     JZ    NOROOM
  423.     ENDIF
  424.     CALL    NEXTFL    ;PRIME THINGS
  425.     JC    NOFILE
  426. LOOP    CALL    WRBYTE
  427.     CALL    RDBYTE
  428.     JNC    LOOP
  429. ;DONE -
  430. NOFILE0
  431.     MVI    A,EOF    ;;gotta end the file
  432.     CALL    WRBYTE
  433.     LDA    STRFLAG    ;;buffers for $$$.sub already flushed
  434.     ORA    A
  435.     JNZ    DONEIT
  436.     LHLD    WRCOUNT
  437.     LXI    D,128
  438.     DAD    D    ;FORCE LAST SECTOR
  439.     SHLD    WRCOUNT    ;..WRITE
  440.     CALL    WRBUFS    ;WRITE THE BUFFER
  441. DONEIT
  442.     CPM    closef,FCB
  443.     INR    A
  444.     JNZ    EXIT
  445.     CALL    ERXIT
  446.     DB    '++CLOSE ERROR++$'
  447. ;
  448. EQLOOP
  449.     MVI    M,' '    ;;gonna blank out rest of FCB
  450.     INX    H
  451.     DCR    B    ;;see if done
  452.     JNZ    EQLOOP
  453.     JMP    EQDONE
  454. ;;
  455. SKIPBRK
  456.     SHLD    BRAKAD    ;;save address
  457. SKIPLUP
  458.     INX    H    ;;bump to next
  459.     MOV    A,M
  460.     ORA    A    ;;check if end of line
  461.     JZ    BADNAME
  462.     SBI    ']'    ;;stop at bracket
  463.     JNZ    SKIPLUP
  464.     MOV    M,A    ;;note for later use
  465.     JMP    SKIPEQ
  466. ;;
  467. S2IPBRK
  468.     SHLD    B2AKAD    ;;save address
  469. S2IPLUP
  470.     INX    H    ;;bump to next
  471.     MOV    A,M
  472.     ORA    A    ;;check if end of line
  473.     JZ    BADNAME
  474.     SBI    '['    ;;stop at bracket
  475.     JNZ    S2IPLUP
  476.     MOV    M,A    ;;note for later use
  477.     JMP    SKIPEQ
  478. ;;
  479. QMFILE
  480.     CALL    ERXIT    ;;
  481.     DB    '++AMBIGUOUS FILE++$'
  482. ;
  483. NOFILE
  484.     LDA    PCTFLAG    ;;see if just percents
  485.     ORA    A
  486.     JZ    NOFILE1
  487.     LDA    CNFLAG    ;;see if submit file out
  488.     ORA    A
  489.     JZ    NOFILE0
  490.     JMP    EXIT    ;;if console out, nothing to close
  491. NOFILE1
  492.     CALL    ERXIT    ;;nothing at all
  493.     DB    '++MISSING FILE++$'
  494. ;;
  495. ;;
  496. NOFILE2
  497.     LHLD    BRAKAD    ;;see if prefix or suffix strings
  498.     MOV    A,H
  499.     ORA    L
  500.     LHLD    B2AKAD
  501.     ORA    H
  502.     ORA    L
  503.     JZ    NOFILE1    ;; = is OK if had strings
  504. ;;
  505. CONSOL
  506.     MVI    A,0C3H
  507.     STA    CNFLAG
  508.     CALL    NEXTFL    ;;set up loop
  509.     JC    NOFILE
  510. LOOPC    CALL    WRBYTE    ;;now copy to console
  511.     CALL    RDBYTE
  512.     JNC    LOOPC    ;;see if all done
  513.     JMP    EXIT
  514. ;
  515. ;WRITE BYTE TO OUTPUT FILE
  516. ;
  517. WRBYTE
  518.     MOV    B,A    ;;save the character
  519.     CPI    EOF    ;;see if end
  520.     JZ    WRCRLF
  521.     CPI    CR    ;;look for CR or LF
  522.     JZ    WRCRLF
  523.     CPI    LF
  524.     JZ    WRCRLF
  525. ;;    Just got a character not CR, LF, or EOF
  526.     LHLD    WIDTH    ;;bump up char. #
  527.     INX    H
  528.     SHLD    WIDTH
  529.     XCHG
  530.     LHLD    WIDNUM    ;;load max width
  531.     MOV    A,L
  532.     SUB    E
  533.     MOV    A,H    ;;compare width to max
  534.     SBB    D
  535.     JNC    WRBY2
  536.     PUSH    B    ;;save the character
  537.     MVI    A,CR
  538.     CALL    WRBYTE    ;;recursive call to end line
  539.     MVI    B,LF
  540.     CALL    WRBYT
  541.     POP    B    ;;now r    la;OZ0'mYacter on new line
  542. WRBY2
  543.     LDA    CRFLAG    ;;now check if just had CR or LF
  544.     ORA    A
  545.     JZ    WRBYT
  546.     LHLD    LINE    ;;bump up line counter
  547.     INX    H
  548.     SHLD    LINE
  549.     XRA    A    ;;now turn off CRLF
  550.     STA    CRFLAG
  551.     LHLD    BRAKAD    ;;at beginning of line, put out prefix
  552.     MOV    A,L
  553.     ORA    H    ;;see if prefix
  554.     JZ    WRBYT
  555. PREFLUP
  556.     INX    H
  557.     MOV    A,M    ;;get a character
  558.     ORA    A
  559.     JZ    WRBYT    ;;jump if end of prefix string
  560.     PUSH    H
  561.     PUSH    B
  562.     MOV    B,A
  563.     CALL    WRBYT    ;;pump out character
  564.     POP    B
  565.     POP    H
  566.     JMP    PREFLUP
  567. ;;
  568. ;;    Just found a CR or LF
  569. WRCRLF
  570.     LXI    H,0    ;;zero out line width
  571.     SHLD    WIDTH
  572.     LDA    CRFLAG    ;;now check if just had CR or LF
  573.     ORA    A
  574.     JNZ    WRBYT
  575.     CMA        ;;now indicate CRLF
  576.     STA    CRFLAG
  577.     LHLD    B2AKAD    ;;at end of line, put out suffix
  578.     MOV    A,L
  579.     ORA    H    ;;see if suffix
  580.     JZ    WRBYT
  581. SUFFLUP
  582.     INX    H
  583.     MOV    A,M    ;;get a character
  584.     ORA    A
  585.     JZ    WRBYT    ;;jump if end of prefix string
  586.     PUSH    H
  587.     PUSH    B
  588.     MOV    B,A
  589.     CALL    WRBYT    ;;pump out character
  590.     POP    B
  591.     POP    H
  592.     JMP    SUFFLUP
  593. ;;
  594. ;;    Now put out character wherever it goes
  595. WRBYT
  596.     LHLD    LINE    ;;get line #
  597.     MOV    A,L
  598.     ORA    H    ;;if very first line, accept CR and LF
  599.     JZ    WRBY3
  600.     XCHG
  601.     LHLD    PLUSNUM    ;;get starting #
  602.     MOV    A,L
  603.     SUB    E
  604.     MOV    A,H    ;;compare line # vs start
  605.     SBB    D
  606.     RNC
  607.     LHLD    MINSNUM    ;;get ending line #
  608.     DCX    D
  609.     MOV    A,E
  610.     SUB    L
  611.     MOV    A,D    ;;compare line # vs end
  612.     SBB    H
  613.     JNC    FAKEOF    ;;tell RDBYTE to get next file
  614. WRBY3
  615.     LDA    CNFLAG
  616.     ORA    A    ;;if console output, go do it
  617.     MOV    A,B
  618.     JNZ    TYPE
  619.     LDA    STRFLAG
  620.     ORA    A    ;;if submit output, go do it
  621.     JNZ    SUBCMD
  622.     LHLD    WRBUFAD    ;;disk i/o is buffered
  623.     MOV    M,B
  624.     INX    H    ;;bump up to next character
  625.     SHLD    WRBUFAD
  626. ;BUMP COUNT
  627.     LHLD    WRCOUNT
  628.     INX    H
  629.     SHLD    WRCOUNT
  630. ;SEE IF TIME TO WRITE BUFFER
  631.     DAD    H    ;H=# SECTORS
  632.     MOV    A,H
  633.     CPI    BLKSIZE/128
  634.     RNZ
  635. ;TIME TO WRITE THE OUTPUT BUFFER
  636. ;
  637. WRBUFS    LXI    H,WRBUFF
  638.     SHLD    WRBUFAD
  639.     XCHG
  640.     LHLD    WRCOUNT
  641.     DAD    H    ;H=# SECTORS
  642.     MOV    B,H    ;SAVE SECTOR COUNT
  643.     MOV    A,B
  644.     ORA    A    ;0 SECTORS? (POSS AT EOF)
  645.     JNZ    WRBFLP
  646.     INR    B    ;FUDGE IN PARTIAL SECTOR
  647. WRBFLP    CPM    dmaf
  648.     CPM    writef,FCB
  649.     ORA    A
  650.     JNZ    WRERR
  651.     LXI    H,128
  652.     DAD    D
  653.     XCHG
  654.     DCR    B
  655.     JNZ    WRBFLP
  656.     LXI    H,0
  657.     SHLD    WRCOUNT
  658.     RET
  659. ;
  660. ;    all this from /.asm , with thanks
  661. ;
  662. SUBCMD
  663.     MOV    A,B
  664.     CPI    LF    ;;skip linefeeds
  665.     RZ
  666.     LHLD    SUBOUT
  667.     CPI    CR    ;;see if end of line
  668.     jz    cmdend
  669.     CPI    EOF    ;;end of file ?
  670.     jz    cmdend
  671.     mov    m,a    ;if neither, xfer it to the output buffer,
  672.     inx    h    ;bump pointer
  673.     SHLD    SUBOUT
  674.     RET        ;and try again.
  675. ;
  676. cmdend:    mvi    m,0    ;zero the byte after the end of the line.
  677.     mov    a,l
  678.     dcr    a
  679.     ani    7fh    ;accumulator has character count.
  680.     mov    c,a    ;save it.
  681.     mov    a,l
  682.     ani    80h
  683.     mov    l,a    ;hl points to the character count byte.
  684.     mov    m,c
  685. ;
  686.     MOV    A,B
  687.     CPI    EOF    ;if we've reached the end of the input line...
  688.     jz    fileit    ;let's "file it".
  689.     lxi    b,129
  690.     dad    b
  691.     SHLD    SUBOUT
  692.     RET        ;back for the next command.
  693. ;
  694. fileit:        
  695. ;
  696. wrloop:    push    h    ;save address of last zone
  697.     xchg
  698.     mvi    c,dmaf
  699.     call    bdos
  700. ;
  701.     lxi    d,fcb
  702.     mvi    c,writef
  703.     call    bdos    ;write the new commands, one command per
  704.             ;disk sector, writing the last command first.
  705.     ORA    A
  706.     JNZ    WRERR
  707. ;
  708.     pop    h    ;get current dma address
  709.     lxi    d,-128
  710.     dad    d
  711.     lxi    d,subbuf
  712.     mov    a,l
  713.     sub    e
  714.     mov    a,h
  715.     sbb    d
  716.     jnc    wrloop
  717.     RET
  718. ;
  719. WRERR    CALL    ERXIT
  720.     DB    '++WRITE ERROR++$'
  721. ;;
  722. FAKEOF
  723.     LXI    H,RDBUFF ;;create EOF so RDBYTE will
  724.     SHLD    RDBUFAD     ;;get next file
  725.     MVI    A,EOF
  726.     MOV    M,A
  727.     STA    RDCOUNT
  728.     RET
  729. ;
  730. ;READ BYTE FROM INPUT FILE
  731. ;
  732. RDBYTE    LHLD    RDBUFAD
  733.     LDA    RDCOUNT    ;GET CHAR COUNT
  734.     ORA    A    ;TIME TO READ?
  735.     JP    NOREAD
  736. ;HAVE TO READ
  737.     CPM    dmaf,RDBUFF
  738.     CPM    readf,RDFCB
  739.     ORA    A
  740.     JNZ    NEXTFL    ;;if disk EOF, go get next file
  741.     CPM    dmaf,cibuf
  742.     LXI    H,RDBUFF
  743.     MVI    A,0
  744. NOREAD    INR    A
  745.     STA    RDCOUNT    ;SAVE CHAR COUNT
  746.     MOV    A,M    ;GET CHAR
  747.     INX    H
  748.     SHLD    RDBUFAD
  749.     CPI    EOF    ;EOF?
  750.     JZ    NEXTFL
  751.     ORA    A    ;CARRY OFF SHOWN NOT EOF
  752.     RET
  753. ;
  754. ;GOT EOF - GET NEXT FILE
  755. NEXTFL
  756.     LXI    H,0
  757.     SHLD    WIDTH    ;;zero out counters for new file
  758.     SHLD    LINE
  759.     LHLD    NAMEADD    ;GET NAME POINTER
  760.     MOV    A,M    ;GET DELIMITER
  761.     ORA    A
  762.     STC
  763.     RZ        ;RET IF ALL DONE
  764. MOVEX
  765.     INX    H    ;SKIP DELIMITER
  766.     MOV    A,M
  767.     CPI    ' '    ;;gonna skip by blanks
  768.     JZ    MOVEX
  769.     CPI    ','    ;;   and commas
  770.     JZ    MOVEX
  771.     ORA    A
  772.     STC        ;;return if nothing but blanks
  773.     RZ
  774.     LXI    D,RDFCB ;POINT TO NAME
  775.     xra    a    ;prepare to use default drive
  776.     stax    d
  777.     STA    PRFLAG    ;;zero out period flag
  778.     inx    d
  779.     PUSH    D
  780. ;BLANK THE FCB
  781.     MVI    A,' '
  782.     MVI    B,11
  783. BLANK    STAX    D
  784.     INX    D
  785.     DCR    B
  786.     JNZ    BLANK
  787.     POP    D
  788. ;
  789.     inx    h    ;look ahead for colon, indicating drive
  790.     mov    a,m
  791.     dcx    h    ;backup j.i.c. not there
  792.     cpi    ':'    ;was a drive specified?
  793.     jnz    moven    ;nope - just scan off file name
  794.     mov    a,m    ;yup - insert drive name into fcb
  795.     sui    'A'-1
  796.     JC    MOVEN    ;;skip bad drive name
  797.     CPI    16    ;;and make sure valid
  798.     JNC    BADNAME
  799.     sta    rdfcb
  800.     inx    h    ;move source pointer over drive spec.
  801.     inx    h
  802. MOVEN    MOV    A,M
  803.     CPI    ':'    ;;see if extraneous colon
  804.     JZ    BADNAME
  805.     CPI    '>'
  806.     JZ    BADNAME
  807.     CPI    '?'    ;;dont allow ambiguity
  808.     JZ    QMFILE
  809.     CPI    ','
  810.     JZ    MOVED
  811.     CPI    ' '    ;;stop at comma or blank
  812.     JZ    MOVED
  813.     cpi    '.'
  814.     jz    movft
  815.     ORA    A    ;ZERO @ END?
  816.     JZ    MOVEZ
  817.     CPI    '['    ;;no bad filenames
  818.     JZ    BADNAME
  819.     CPI    ']'
  820.     JZ    BADNAME
  821.     STAX    D
  822.     MVI    A,FCBEXT ;;is it past FCB ?
  823.     CP    E
  824.     JNC    BADNAME
  825.     INX    H
  826.     INX    D
  827.     JMP    MOVEN
  828. movft
  829.     LDA    PRFLAG    ;;check if already got period
  830.     ORA    A
  831.     JNZ    BADNAME
  832.     CMA
  833.     STA    PRFLAG    ;;indicate found period
  834.     inx    h
  835.     lxi    d,rdfcb+9    ;address filetype of read block
  836.     jmp    moven
  837. ;
  838. MOVEZ
  839.     SHLD    NAMEADD    ;SAVE NAME LIST ADDR
  840.     LDA    RDFCB+1
  841.     CPI    ' '    ;;look at file name
  842.     STC
  843.     RZ
  844. ;ALL DONE MOVING
  845. MOVED    SHLD    NAMEADD    ;SAVE NAME LIST ADDR
  846.     LDA    RDFCB+1    ;;see if no file
  847.     CPI    ' '
  848.     JZ    NOFILE
  849.     LDA    PRFLAG
  850.     ORA    A    ;;if got a period, not special name
  851.     JNZ    NOCENT
  852.     CALL    GETNUM    ;;see if have valid number
  853.     JNC    GOTNUM
  854. ;;    check for special filenames
  855.     COMP    RDFCB,,,<0,'*   '>
  856.     JZ    GOTBLNK
  857.     COMP    RDFCB,,,<0,'%F  '>
  858.     JZ    FORMFEED
  859.     COMP    RDFCB,,,<0,'%T  '>
  860.     JZ    TABCHAR
  861.     COMP    RDFCB,,,<0,'%N  '>
  862.     JNZ    NOCENT
  863.     MVI    A,CR    ;; CR
  864.     STA    PCTFLAG
  865.     CALL    WRBYTE
  866.     MVI    A,LF    ;; LF
  867.     CALL    WRBYTE
  868.     JMP    NEXTFL    ;;now go skip by filename
  869. FORMFEED
  870.     MVI    A,0CH    ;; FF
  871.     STA    PCTFLAG
  872.     CALL    WRBYTE    ;; put it out
  873.     JMP    NEXTFL
  874. TABCHAR
  875.     MVI    A,09H    ;; Tab
  876.     STA    PCTFLAG
  877.     CALL    WRBYTE    ;; put it out
  878.     JMP    NEXTFL
  879. NOCENT
  880.     XRA    A
  881.     STA    RDEXT    ;ZERO EXTENT
  882.     STA    RDRNO    ;ZERO RECORD #
  883.     CPM    dmaf,RDBUFF
  884.     CPM    openf,RDFCB
  885.     INR    A
  886.     JZ    OPENERR
  887.     MVI    A,128    ;SHOW TIME TO READ
  888.     STA    RDCOUNT
  889.     CPM    dmaf,cibuf
  890.     JMP    RDBYTE
  891. ;;
  892. ;;    Do console input here
  893. GOTBLNK
  894.     LDA    PRFLAG
  895.     ORA    A    ;;see if bad news
  896.     JNZ    BADNAME
  897.     CMA
  898.     STA    PCTFLAG    ;;deactivate error message
  899. GOTLIN
  900.     CPM    CONIN,INAREA
  901.     LXI    H,INAREA+1 ;;get character count
  902.     MOV    A,M
  903.     ORA    A    ;;see if no line
  904.     JZ    NEXTFL
  905.     MOV    B,A    ;;initialize loop
  906.     INR    B
  907. GOTLUP
  908.     DCR    B    ;;see if end of line
  909.     JZ    GOTEND
  910.     INX    H    ;;get next character
  911.     MOV    A,M
  912.     ORA    A    ;;stop if NUL
  913.     JZ    NEXTFL
  914.     CPI    EOF    ;;see of EOF
  915.     JZ    NEXTFL
  916.     PUSH    B
  917.     PUSH    H
  918.     CALL    WRBYTE    ;;pop out character
  919.     POP    H
  920.     POP    B
  921.     JMP    GOTLUP    ;;no go get another
  922. GOTEND
  923.     MVI    A,CR    ;;put out CR
  924.     CALL    WRBYTE
  925.     MVI    A,LF    ;;put out LF
  926.     CALL    WRBYTE
  927.     LDA    CNFLAG    ;;see if console in, file out
  928.     ORA    A
  929.     JNZ    GOTLIN
  930.     MVI    A,LF    ;;LF after CR if console in
  931.     CALL    TYPE
  932.     JMP    GOTLIN    ;;go get another line
  933. ;;
  934. ;;    Now process the three numeric options
  935. GOTNUM
  936.     XCHG        ;;put number in HL
  937.     LDA    SGNFLAG
  938.     ORA    A    ;;check sign
  939.     JNZ    GOTNUM2
  940.     SHLD    WIDNUM    ;;no sign
  941.     JMP    NEXTFL
  942. GOTNUM2
  943.     CPI    '-'
  944.     JNZ    GOTPLS
  945.     SHLD    MINSNUM    ;;minus sign
  946.     JMP    NEXTFL
  947. GOTPLS
  948.     SHLD    PLUSNUM    ;;plus sign
  949.     JMP    NEXTFL
  950. ;;
  951. ;;
  952. OPENERR    LXI    H,RDFCB+1
  953.     MVI    B,11
  954. NAMELP    MOV    A,M
  955.     CALL    TYPE
  956.     INX    H
  957.     DCR    B
  958.     JNZ    NAMELP
  959.     CALL    ERXIT
  960.     DB    ': ++OPEN FAILED++$'
  961. ;;
  962. ;;
  963. BADNAME
  964.     LXI    H,RDFCB+1
  965.     MVI    B,11
  966. NAMEZZ    MOV    A,M
  967.     CALL    TYPE
  968.     INX    H
  969.     DCR    B
  970.     JNZ    NAMEZZ
  971.     CALL    ERXIT
  972.     DB    '++INVALID FILENAME++$'
  973. ;
  974. ;
  975. NOROOM    CALL    ERXIT
  976.     DB    '++NO ROOM ON OUTPUT DISK$'
  977. ;
  978. TYPE    MOV    E,A
  979.     CPM    WRCON
  980.     RET
  981. ;;
  982. ;;    This code scans RDFCB for a decimal number and converts
  983. ;;    it into a 16-bit number in DE. Leading plus and minus
  984. ;;    signs are accepted and indicated in SGNFLAG. If there
  985. ;;    are any problems (bad digits or overflows), the carry
  986. ;;    flag is set and the routine stops.
  987. ;;
  988. GETNUM
  989.     LXI    H,RDFCB+1    ;; initialize first
  990.     MVI    B,8
  991.     XRA    A
  992.     MOV    E,A
  993.     MOV    D,A
  994.     STA    SGNFLAG
  995.     MOV    A,M
  996.     CPI    '+'        ;; now check for leading +
  997.     JZ    GOTSIGN
  998.     CPI    '-'        ;; or -
  999.     JNZ    GETDIG
  1000. GOTSIGN
  1001.     STA    SGNFLAG        ;; indicate the sign
  1002. GITLUP
  1003.     INX    H        ;; bump up to next char
  1004.     DCR    B
  1005.     RZ            ;; return if done
  1006.     MOV    A,M
  1007.     CPI    ' '
  1008.     RZ
  1009. GETDIG
  1010.     CPI    '9'+1        ;; now check for valid numeric
  1011.     CMC
  1012.     RC
  1013.     SBI    '0'        ;; test and subtract combined
  1014.     RC
  1015.     MOV    C,A        ;; now have 0-9 in C
  1016.     PUSH    H
  1017.     MOV    H,D
  1018.     MOV    L,E        ;; DE - HL
  1019.     DAD    H
  1020.     RC            ;; * 2
  1021.     MOV    D,H
  1022.     MOV    E,L
  1023.     DAD    H        ;; * 4
  1024.     RC
  1025.     DAD    H        ;; * 8
  1026.     RC
  1027.     DAD    D        ;; * 10 = * ( 8+2 )
  1028.     RC
  1029.     XRA    A
  1030.     MOV    D,A        ;; now add in digit
  1031.     MOV    E,C
  1032.     DAD    D
  1033.     RC
  1034.     XCHG            ;; result back in DE
  1035.     POP    H
  1036.     JMP    GITLUP
  1037. ;
  1038. ;FOLLOWING FROM 'EQU7.LIB'---->
  1039. ;
  1040. ;MOVE SUBROUTINE
  1041. ;
  1042.     IF    MF    ;MACRO EXPANSION FLAG SET?
  1043. MOVER    MOV    A,M
  1044.     STAX    D
  1045.     INX    H
  1046.     INX    D
  1047.     DCX    B
  1048.     MOV    A,B
  1049.     ORA    C
  1050.     JNZ    MOVER
  1051.     RET
  1052.     ENDIF
  1053. ;
  1054.     IF    CF    ;MACRO EXPANSION FLAG SET?
  1055. COMPR    LDAX    D
  1056.     CMP    M
  1057.     RNZ
  1058.     INX    D
  1059.     INX    H
  1060.     DCX    B
  1061.     MOV    A,B
  1062.     ORA    C
  1063.     JNZ    COMPR
  1064.     RET
  1065.     ENDIF
  1066. ;
  1067. ;
  1068. ;EXIT WITH ERROR MESSAGE
  1069. MSGEXIT    EQU    $    ;EXIT W/"INFORMATIONAL" MSG
  1070. ERXIT    POP    D    ;GET MSG
  1071.     MVI    C,PRINT
  1072.     CALL    BDOS
  1073. ;EXIT, RESTORING STACK AND RETURN
  1074. EXIT    LHLD    STACK
  1075.     SPHL
  1076. ;
  1077.     rst    boot    ;back to cp/m via a warm start.
  1078.             ;changing this to a "ret" will return
  1079.             ;to CP/M without the warm start, and so
  1080.             ;the command file will not be executed
  1081.             ;until the next boot from this disk.
  1082. ;;
  1083. ;;
  1084. BRAKAD
  1085.     DW    0    ;;start of prefix string
  1086. B2AKAD
  1087.     DW    0    ;;start of suffix string
  1088. PCTFLAG
  1089.     DB    0    ;;flag to indicate percent
  1090. PRFLAG
  1091.     DB    0    ;;flag to indicate period
  1092. CNFLAG
  1093.     DB    0    ;;flag indicating console
  1094. CRFLAG
  1095.     DB    1    ;;flag indicating CR or LF
  1096. STRFLAG
  1097.     DB    0    ;;flag indicating doing $$$.sub
  1098. WIDNUM
  1099.     DW    65535    ;;maximum line width
  1100. MINSNUM
  1101.     DW    65535    ;;maximum line number
  1102. PLUSNUM
  1103.     DW    0    ;;beginning line number
  1104. WIDTH
  1105.     DW    0    ;;current line width
  1106. LINE
  1107.     DW    0    ;;current line number
  1108. ;;
  1109. WRBUFAD    DW    WRBUFF    ;OUTPUT BUFFER ADDR
  1110. WRCOUNT    DW    0    ;BYTE COUNTER
  1111. RDBUFAD    DW    RDBUFF
  1112. RDDRV    DB    0    ;DRIVE NAME TO READ FROM
  1113. RDFCB    DB    0,'filenameext'
  1114. RDEXT    DB    0
  1115.     DS    19
  1116. RDRNO    DB    0
  1117. RDCOUNT    DB    128    ;CHARACTER COUNT IN BUFF
  1118. ;
  1119. xfcb:    db    1, '$$$     SUB'    ;;note file on A: drive
  1120.     dw    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  1121. ;;
  1122. ;;CONSOLE INPUT LINE BUFFER
  1123. INAREA    DB    254
  1124.     DS    255
  1125. ;;
  1126. ;;    Only unitialized RAM after this 
  1127. ;;
  1128.     DS    40H    ;STACK AREA
  1129. STACK    DS    2
  1130. ;;
  1131. ;POINTER TO LIST OF FILENAMES
  1132. NAMEADD    DS    2
  1133. ;;
  1134. SUBOUT
  1135.     DS    2    ;;pointer to submit output buffer
  1136. ;;
  1137. SGNFLAG
  1138.     DS    1    ;;indicates if a sign was found in GETNUM
  1139. ;;
  1140. ;COPY OF INPUT COMMAND BUFFER (FROM 80H)
  1141. HOLD    DS    128
  1142. ;;
  1143. ;OUTPUT DISK BUFFER
  1144.     ORG    ($+255) AND 0FF00H ;TO PAGE
  1145. RDBUFF    DS    128
  1146. subbuf:
  1147. WRBUFF    DS    BLKSIZE
  1148. ;;
  1149. ;;    The end of the buffer must not overlay the BIOS
  1150. ENDBUF
  1151. ;;
  1152. ;BDOS/CBIOS EQUATES (VERSION 7)    
  1153. RDCON    EQU    1
  1154. WRCON    EQU    2
  1155. PRINT    EQU    9
  1156. CONIN    EQU    10
  1157. CONST    EQU    11
  1158. openf    equ    15
  1159. closef    equ    16
  1160. SRCHF    EQU    17
  1161. SRCHN    EQU    18
  1162. delete    equ    19
  1163. readf    EQU    20
  1164. writef    equ    21
  1165. makef    equ    22
  1166. REN    EQU    23
  1167. dmaf    equ    26
  1168. ;
  1169. boot    equ      0    ;for a warm start
  1170. bdos    equ      5    ;cp/m entry point
  1171. FCB    EQU    5CH 
  1172. FCB2    EQU    6CH
  1173. FCBEXT    EQU    FCB+12
  1174. FCBRNO    EQU    FCB+32
  1175. cibuf    equ    080h    ;console input buffer
  1176.     END
  1177.