home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / utils / squsq / fcrnch11.lbr / FCRUNCH.MZC / FCRUNCH.MAC
Text File  |  1986-12-24  |  20KB  |  878 lines

  1. title    'FCRUNCH multi-file cruncher'
  2. ;
  3. ver        equ    11
  4. ;
  5. ; Crunch file 1 to file 2.  By C.B. Falconer.
  6. ;
  7. ;   d>FCRUNCH [-[c][k][p][q]] [d[u]:]afnin.aft [d[u]:][afnout.aft]
  8. ;        crunches afnin.aft to afnout.aft
  9. ;        (with full du addressing, across users, drives)
  10. ; the (optional) -c causes confirmation per file crunched
  11. ;         -k causes no existing files to be erased
  12. ;         -p causes existing output file erasure
  13. ;         -q suppresses running messages
  14. ; Default output name is input with a middle Z in filetype.
  15. ;
  16. ; 1.1    (86/12/20) Only version # changed, relinked to CRN v25, which
  17. ;    allows for trapping of particular output sequences.  This now
  18. ;    traps the sequence <0dh>,<040h> (with possible high bits set)
  19. ;    and injects a nulcode to output.  This avoids problems with
  20. ;    Telenet/PcPursuit (or so I am told).  CRN can be configured
  21. ;    to trap any 2 byte sequence, by reassembly.    - cbf
  22. ;
  23. ; Created as a modification of FCOPY 1.1.  Needs BUFFLIB v1.4 up
  24. ;
  25. ; ASSEMBLY    (rmac is not usable without changes)
  26. ;    A>m80 fcrunch,=fcrunch
  27. ; or
  28. ;    A>slrmac fcrunch/r        (much faster)
  29. ;
  30. ;    CAUTION - nnnn/mmmm numbers below are examples, can change
  31. ;
  32. ; LINKING with L80  (slowest by far)
  33. ;
  34. ;    A>l80 /p:100,/d:4000,fcrunch,crn,bufflib/s,/u,/r
  35. ;
  36. ;    Link-80  3.44   . . . . 
  37. ;    Data    4000    405A    <   90>
  38. ;    Program 0100    0ADD    < dddd>
  39. ;
  40. ;    */p:100,/d:nnnn,fcrunch,crn,bufflib/s,fcrunch/n,/e
  41. ;            ^ using nnnn = 0ADD from above line (example)
  42. ;
  43. ; LINKING with SLRNK
  44. ;
  45. ;    A>slrnk /p:100,/d:4000,fcrunch,crn,bufflib/s,/u,/r
  46. ;
  47. ;    Superlinker . . . .
  48. ;    0100-0ADC  (09DD)       973E left
  49. ;    Superlinker . . . .
  50. ;
  51. ;    %/p:100,/d:mmmm,fcrunch,crn,bufflib/s,fcrunch/n,/e
  52. ;            ^ using mmmm = 0ADD, i.e. 0ADC + 1 (example)
  53. ;
  54. ; LINKING with SLRNK+  (fastest and easiest, no copying numbers)
  55. ;
  56. ;    A>slrnk+ /a:100,/j,fcrunch,crn,bufflib/s,fcrunch/n,/e
  57. ;                        (does it all)
  58. ; Externals in BUFFLIB.    See BUFFERS.DOC
  59.     extrn    .getusr,  .xltusr, .setusr;    user parsing
  60.     extrn    .wildx,      .wldck,  .pfnmdu;    file parsing
  61.     extrn    .options, .skipblks;        command parsing
  62.     extrn    .fncpy,      .nxtout, .nxtfn;    fname operations
  63.     extrn    .dos;                bdos(a), save regs
  64.     extrn    .idiv,      .imul,   .dcmp
  65.     extrn    .tdzs,      .tfnam,  .crlf;    utility
  66.     extrn    .couta,      .tdzsf,  .blk
  67.     extrn    .initfcb, .drvlock
  68.     extrn    .bfwopen, .bfclose;        write opens/close
  69.     extrn    .bfropen;            read opens
  70.     extrn    .bfgetc,  .bfputc;        buffered file i/o
  71.     extrn    b.ohead;            ext. constants
  72.     extrn    .bver;                library version
  73.     extrn    .endata;            Available memory area
  74. ;
  75.     extrn    crn;                crunch package
  76.     extrn    incnt, outcnt, nxtcod, ttotal;    display vars
  77.     entry    getchr, outbyt;            crn i/o
  78. ;
  79. buflibver    equ    14;        minimum to link
  80. stkmargin    equ    5*1400h + 256;    bytes for crn & stack
  81. ;
  82. boot    equ    0
  83. bdos    equ    boot+5
  84. tfcb    equ    boot+05ch;    used to hold outname template
  85. defdma    equ    boot+080h
  86. ;
  87. cr    equ    0dh
  88. lf    equ    0ah
  89. t    equ    09h
  90. crnchid    equ    076feh;        Standard header
  91. stpmax    equ    40;        max size (+1) of any stamp
  92. ;
  93. ; errors
  94. xhelp    equ    0;        no error, give help
  95. xempty    equ    1;        file empty
  96. xcrn    equ    2;        file already crunched/squeezed
  97. xstkovf    equ    3;        memory overflow
  98. xwild    equ    4;        incompatible wildcards
  99. xtoself    equ    5;        copying into self
  100. xnodir    equ    6;        fcreate failure
  101. xwrterr    equ    7;        write error
  102. xusrabt    equ    8;        user abort
  103. xbadlib    equ    9;        linked to wrong library
  104. xsaved    equ    10;        Old file not eraseable
  105. xbadnam    equ    11;        Unable to create new name
  106. xnofile    equ    12;        input file not found
  107. xok    equ    13;        done, without errors
  108. ;
  109. ; Dos function calls
  110. cin    equ    1
  111. pstrg    equ    9
  112. csta    equ    11
  113. @fopen    equ    15
  114. @purge    equ    19
  115. ;
  116. ; Initialize
  117. begin:    jmp    bgn
  118. ;
  119. ; Option image.  Zero locations to pre-set.
  120. ; Make letters lower case to forbid setting.
  121. optimg:    db    '-',optlgh
  122.     db    'C';        Confirm "crunch this file" option
  123.     db    'K';        Keep pre-existing output files
  124.     db    'P';        purge pre-existing output files
  125.     db    'Q';        Quiet option.
  126. optlgh    equ    $-optimg-2
  127. ;
  128. ; Start up here
  129. bgn:    lhld    bdos+1
  130.     mvi    l,0;        set stack at top of memory
  131.     sphl
  132.     call    .getusr
  133.     sta    entryusr
  134.     call    .bver;        This also ensures the lib version
  135.     cpi    buflibver;    module is linked and identified
  136.     mvi    a,xbadlib
  137.     jc    exeunt;        linked to wrong library
  138.     lxi    h,0
  139.     shld    filesdone;    zero count of files processed
  140.     shld    stamp;        default empty stamp
  141.     lxi    d,defdma
  142.     call    markeol;    of input command line
  143.     inx    d
  144.     lxi    b,optimg
  145.     lxi    h,options
  146.     call    .options;    from de^
  147. ;    "    "
  148. ; parse in/out file names
  149.     lxi    h,fcbout
  150.     call    .initfcb
  151.     lxi    h,fcbin
  152.     call    .initfcb;    init in and out fcbs
  153.     call    .pfnmdu
  154.     mov    a,b;        is 0 for default, else usr+1
  155.     call    usrlok;        now 1..max
  156.     sta    inuser
  157.     lxi    h,tfcb
  158.     call    .initfcb
  159.     mvi    b,0;        in case no 2nd file parsed
  160.     call    .skipblks
  161.     cpi    '['
  162.     cnz    .pfnmdu;    no 2nd spec, reached the stamp
  163.     push    d;        save input parse pointer
  164.     mov    a,b
  165.     call    usrlok;        now 1..max, no defaults left
  166.     sta    outuser
  167.     lxi    d,fcbin;    ensure locked to drive for compare
  168.     call    .drvlock;     else default and specific drives
  169.     lxi    d,tfcb;         may erroneously appear different
  170.     call    .drvlock
  171.     ldax    d
  172.     sta    fcbout;        set output drive id
  173.     lda    fcbin+1
  174.     pop    d;        get input parse pointer back
  175.     sui    ' '
  176.     jz    exeunt;        a=0, help message
  177. ;    "    "
  178. ; Parse the remaining tail into the stamp buffer
  179.     call    rstamp;        from de^
  180. ;    "    "
  181. ; Set default output names, check compatible wild cards
  182.     lxi    h,fcbin
  183.     lxi    d,tfcb
  184.     call    sdefault;    if no output, make same as input
  185.     call    .wldck;        Check wild cards compatible
  186.     mvi    a,xwild
  187.     jc    exeunt;        Incompatible wildcards
  188. ;    "    "
  189. ; Expand any wild cards
  190.     lxi    h,.endata
  191.     shld    fnptr
  192.     lda    inuser
  193.     dcr    a
  194.     call    .setusr
  195.     lxi    d,fcbin
  196.     call    .wildx;        expand fcbin into wild list
  197.     mvi    a,xstkovf
  198.     jc    exeunt;        Ran out of memory
  199.     shld    @outbuff;    mark available memory
  200.     xchg;            de := @outbuff
  201.     mov    l,c
  202.     mov    h,b
  203.     shld    fncount;    number of files matched
  204. ;    "    "
  205. ; Calculate space available for buffers and allocate them
  206.     lxi    h,b.ohead+b.ohead
  207.     dad    d
  208.     xchg;            adjust base of storage
  209.     lxi    h,-stkmargin
  210.     dad    sp
  211.     mvi    a,0;        round down to page boundary
  212.     sub    e
  213.     mov    e,a
  214.     mov    a,h
  215.     sbb    d
  216.     mov    d,a;        form buffer size available
  217.     xchg
  218.     lxi    d,0;        0 extend
  219.     lxi    b,3
  220.     call    .idiv;        one third for outbuffer
  221.     xchg
  222.     mov    a,l
  223.     ani    080h;        round down to multiple of 128
  224.     mov    l,a
  225.     shld    bufsize
  226.     ora    h
  227.     mvi    a,xstkovf
  228.     jz    exeunt;        0 size buffers just wont do
  229.     lxi    d,b.ohead
  230.     dad    d;        space needed for complete buffer
  231.     xchg
  232.     lhld    @outbuff
  233.     dad    d
  234.     shld    @inbuff;    locate past output buffer
  235.     lxi    d,b.ohead
  236.     dad    d
  237.     xchg
  238.     lhld    bufsize
  239.     dad    h;        double, two thirds for input buffer
  240.     dad    d
  241.     shld    @freemem;    and locate available memory
  242. ;    "    "
  243. ; Now tfcb holds output file pattern, fnptr points to next input file
  244. ; name, and fncount holds file count to process.  @outbuff points just
  245. ; above the file list and is allocated, @inbuff is allocated, memory
  246. ; from @freemem up, less an allowance for stack use, is available.
  247. copy:    lhld    fncount
  248.     mov    a,h
  249.     ora    l
  250.     dcx    h
  251.     shld    fncount
  252.     jz    done;        no more files
  253.     call    setfiles;    setup input/output file names
  254.     mvi    a,xbadnam
  255.     push    psw
  256.     call    showf;        file names set up
  257.     pop    psw
  258.     jc    exeunt;        Can't setup this name
  259.     lda    confirm
  260.     ora    a
  261.     cz    askcfm
  262.     jz    copy;        ignore, try next
  263.     lhld    outuser;    to l
  264.     lda    inuser
  265.     cmp    l
  266.     lxi    h,fcbout
  267.     lxi    d,fcbin
  268.     cz    cmpfns;        users same, compare file names/drv
  269.     mvi    a,xtoself
  270.     jz    exeunt;        can't copy to self
  271.     lhld    bufsize
  272.     dad    h;        * 2 for input
  273.     mov    c,l
  274.     mov    b,h
  275.     lhld    @inbuff
  276.     lxi    d,fcbin
  277.     lda    inuser
  278.     call    .bfropen;    open buffered input system
  279.     mvi    a,xnofile
  280.     jc    exeunt;        input file not found
  281.     lxi    d,fcbout
  282.     lda    purge
  283.     ora    a
  284.     lda    outuser
  285.     cnz    chkpurge;    Check for erasure of old file
  286.     mvi    a,xsaved
  287.     jnz    copy2;        and treat NO as an error
  288.     call    .crlf
  289.     lda    outuser
  290.     lhld    bufsize
  291.     mov    c,l
  292.     mov    b,h
  293.     lhld    @outbuff
  294.     call    .bfwopen;    open buffered output file
  295.     mvi    a,xnodir
  296.     jc    exeunt;        fopen error
  297.     call    crnch
  298.     jc    copy1
  299.     lhld    filesdone
  300.     inx    h
  301.     shld    filesdone
  302.     jmp    copy;        no error
  303. ;
  304. ; error (a).  If non-terminal delete output file and continue, 
  305. ; otherwise abort everything.
  306. copy1:    call    delout
  307. copy2:    cpi    xstkovf
  308.     jz    exeunt;        abort everything
  309.     call    msgptr
  310.     call    tstr
  311.     jmp    copy
  312. ;
  313. ; purge output file
  314. delout:    push    psw
  315.     push    d
  316.     lda    outuser
  317.     dcr    a
  318.     call    .setusr
  319.     lxi    d,fcbout
  320.     mvi    a,@purge
  321.     call    .dos;        remove the partial file
  322.     pop    d
  323.     pop    psw
  324.     ret
  325. ;
  326. done:    lhld    filesdone
  327.     mov    a,h
  328.     ora    l
  329.     mvi    a,xnofile
  330.     jz    exeunt;        no files found
  331.     call    .crlf
  332.     call    .tdzs
  333.     mvi    a,xok
  334. ;    "    "
  335. ; output message index (a) and exit
  336. exeunt:    call    msgptr
  337.     call    tstr
  338.     lda    entryusr;    restore user at entry
  339.     call    .setusr
  340.     jmp    boot
  341. ;
  342. ; convert error index (a) into pointer (de) to error message
  343. ; a,f,d,e,h,l
  344. msgptr:    lxi    h,errtbl
  345.     add    a
  346.     add    l
  347.     mov    l,a;        point to msgtable entry (a)
  348.     adc    h
  349.     sub    l
  350.     mov    h,a
  351.     mov    e,m;        get pointer to message
  352.     inx    h
  353.     mov    d,m
  354.     ret
  355. ;
  356. ; messages for error codes 0 up
  357. ;        ERROR MESSAGES        ERROR CODES (0 up)
  358. errtbl:    dw    helpmsg,   emptymsg;    xhelp,     xempty
  359.     dw    xcrnmsg,   nomemsg;    xcrn,     xstkovf
  360.     dw    wildmsg,   selfmsg;    xwild,     xtoself
  361.     dw    nodirmsg,  wrterrmsg;    xnodir,     xwrterr
  362.     dw    abtmsg,    badlibmsg;    xusrabt, xbadlib
  363.     dw    ignoremsg, badnamsg;    xsaved,     xbadnam
  364.     dw    nofind,    filesmsg;    xnofile, xok
  365. ;
  366. helpmsg:
  367. db 'FCRUNCH v', ver/10 + '0', '.', ver MOD 10 + '0'
  368. db    ' by C.B. Falconer',cr,lf,lf
  369. ;   1234567-1234567-1234567-1234567-1234567-1234567-1234567-
  370. db '      keep old   quiet  input file',t, 'output file',cr,lf
  371. db t,      '     \     \',t, t,    ' \',t,  t,     '\',cr,lf
  372. db 'FCRUNCH {-{c}{k}{p}{q}} {d{u}:}afnin.aft {d{u}:}{afout.aft} {[id]}'
  373. db cr,lf
  374. db t,      '  /     /',t,   ' /',t, t,     '  /',t, t,     '     /'
  375. db cr,lf
  376. db '   confirm   purge   source',t,'destination',t,t,      'idstring'
  377. db cr,lf,lf
  378. ;   1234567-1234567-1234567-1234567-1234567-1234567-1234567-1234567-
  379. db t,'[idstring] is anything enclosed in []',cr,lf
  380. db t,'default destination is source name with modified "typ"',cr,lf,lf
  381. db 'ex: FCRUNCH -p b5:fcopy.* c6:',t,'(crunches to C6: and erases)'
  382. db cr,lf,'$'
  383. xcrnmsg:    db    'File already squeezed/crunched',cr,lf,'$'
  384. emptymsg:    db    'Empty file',cr,lf,'$'
  385. nomemsg:    db    cr,lf,'Insufficient memory, '
  386. abtmsg:        db    '..ABORTED..$'
  387. wildmsg:    db    'Incompatible wild cards, from/to$'
  388. selfmsg:    db    'Can''t crunch file to itself$'
  389. nodirmsg:    db    'Can''t create, directory full?$'
  390. wrterrmsg:    db    'Write error, disk full?$'
  391. badlibmsg:    db    'Linked to obsolete library$'
  392. ignoremsg:    db    ' Not erased..',cr,lf,'$'
  393. badnamsg:    db    ' Rename this input file$'
  394. nofind:        db    ' Not found, no'
  395. filesmsg:    db    ' files crunched$'
  396. ;
  397. ; mark end-of-line with nul, text buffer de^
  398. ; a,f,h,l
  399. markeol:
  400.     ldax    d
  401.     mov    l,a
  402.     xra    a
  403.     mov    h,a
  404.     dad    d
  405.     inx    h
  406.     mov    m,a;        mark eol
  407.     ret
  408. ;
  409. ; Check for existance of file de^, user a.  If found, query for
  410. ; erasure. Return z flag if not found, or if erasure permitted
  411. ; a,f
  412. chkpurge:
  413.     dcr    a;        Using buffers variant for user
  414.     call    .setusr
  415.     mvi    a,@fopen
  416.     call    .dos
  417.     inr    a
  418.     rz;            not found, all well
  419.     lda    keepem
  420.     ora    a
  421.     jz    chkpg1;        0 is not a Y, no purge
  422.     push    d
  423.     lxi    d,query
  424.     call    tstr
  425.     pop    d
  426.     call    cupsft
  427. chkpg1:    cpi    'Y';        Z flag for permission
  428.     ret
  429. ;
  430. query:    db    ' Exists, ok to purge (y/N) ? $'
  431. qcnfm:    db    ' Crunch it (Y/n) ? $'
  432. ;
  433. ; ask to confirm squeezing this file.  Z flag for no
  434. ; a,f
  435. askcfm:    push    d
  436.     lxi    d,qcnfm
  437.     call    tstr
  438.     pop    d
  439. ;    "    "
  440. ; Console input char and kludgy upshift.  Compared to 'N'
  441. ; a,f
  442. cupsft:    mvi    a,cin
  443.     call    .dos
  444.     ani    05fh
  445.     cpi    'N'
  446.     ret
  447. ;
  448. ; make file de^ same name as hl^ (name/ext only) if no spec
  449. ; a,f
  450. sdefault:
  451.     inx    d
  452.     ldax    d
  453.     sui    ' '
  454.     sta    outspec;    non-zero means output specified
  455.     ldax    d
  456.     dcx    d
  457.     rnz
  458.     jmp    .fncpy;        no specification, copy it
  459. ;
  460. ; Column header for noisy display
  461. colhdr:    lxi    d,colmsg
  462. ;    "    "
  463. ; String de^ to console
  464. ; a,f
  465. tstr:    mvi    a,pstrg
  466.     jmp    .dos
  467.  
  468. colmsg:    db    '    in   out ratio    ca    cr',cr,lf
  469.     db    '    ==   === =====    ==    ==',cr,lf,'$'
  470. ;
  471. ; All files open, and buffers assigned.
  472. ; Crunch fcbin to fcbout byte by byte.
  473. crnch:    lda    quiet
  474.     ora    a
  475.     cnz    colhdr
  476.     lxi    h,0
  477.     shld    cksum
  478.     dad    sp
  479.     shld    savesp;        in case of error
  480.     call    header;        Make the standard header
  481.     lhld    @freemem;    Where to put the tables
  482.     mvi    a,044h;        use existing stack assignments &
  483.     call    crn;        allow reset when tbl full & 1024 ca's
  484.     rc;            error exit
  485.     lhld    cksum
  486.     mov    a,l
  487.     call    outbyt
  488.     mov    a,h
  489.     call    outbyt;        include the checksum
  490.     lhld    @outbuff
  491.     call    .bfclose;    close the output file
  492.     lhld    xtraout
  493.     inx    h
  494.     inx    h
  495.     shld    xtraout;    allow for checksum
  496.     lda    quiet
  497.     ora    a
  498.     rz
  499.     call    show
  500.     call    .blk
  501.     mvi    a,'('
  502.     call    .couta
  503.     call    inout;        hl := input; de := output rcds
  504.     xchg
  505.     call    .dcmp;        flags on hl-de
  506.     xchg
  507.     cnc    chksav;        not smaller
  508.     jnc    crnch8;        not saved, de has message ptr.
  509.     call    dvd8hl;        rounding up
  510.     call    .tdzs;        input kbytes
  511.     xchg
  512.     lxi    d,ktok
  513.     call    tstr
  514.     call    dvd8hl
  515.     call    .tdzs;        output kbytes
  516.     lxi    d,kend
  517. crnch8:    call    tstr
  518.     xra    a;        no error
  519.     ret
  520. ;
  521. ktok:    db    'k --> $'
  522. kend:    db    'k)',cr,lf,'$'
  523. nosave:    db    'Not smaller, not saved)',cr,lf,'$'
  524. ;
  525. ; Check for save of output file.  Forced to no save here
  526. ; Set carry if file to be saved.
  527. ; Reset carry if file purged, when de is message pointer.
  528. ; a,f (de if no save only)
  529. chksav:    call    delout
  530.     ora    a
  531.     lxi    d,nosave
  532.     ret
  533.  
  534. ; setup input/output file names in fcbin/fcbout, using the globals
  535. ; fnptr, tfcb.  Carry if unable to create a suitable file name.
  536. ; a,f,b,c,d,e,h,l
  537. setfiles:
  538.     lxi    d,fcbin
  539.     lhld    fnptr
  540.     call    .nxtfn;        load the next file name
  541.     lxi    d,16
  542.     dad    d
  543.     shld    fnptr;        advance source name pointer
  544.     lxi    d,fcbout;    setup fcbout by
  545.     lxi    h,tfcb;         copying template
  546.     lxi    b,fcbin;     and replacing wild loc'ns
  547.     call    .nxtout
  548.     lda    outspec
  549.     ora    a
  550.     rnz;            file specified
  551. ;    "    "
  552. ; Now modify the output file type
  553.     lxi    h,fcbout+9
  554.     mov    a,m
  555.     cpi    ' '
  556.     jz    setf1;        no extension, make it ZZZ
  557.     inx    h
  558.     mov    a,m
  559.     cpi    'Z'
  560.     jnz    setf2;        Revised file type to xZx
  561.     mvi    m,'Z'
  562.     inx    h
  563.     mov    a,m
  564.     cpi    'Z'
  565.     jnz    setf2;        xZZ does it
  566.     mvi    m,'Z'
  567.     dcx    h
  568.     dcx    h
  569.     mov    a,m
  570.     cpi    'Z'
  571.     jnz    setf2;        ZZZ does it
  572.     stc
  573.     ret;            Can't rename this file
  574. setf1:    mvi    m,'Z'
  575.     inx    h
  576.     mvi    m,'Z'
  577.     inx    h
  578. setf2:    mvi    m,'Z'
  579.     ora    a;        clear any carry
  580.     ret    
  581. ;
  582. ; show file to be transferred
  583. ; a,f,b,c,d,e,h,l
  584. showf:    lda    quiet
  585.     ora    a
  586.     cnz    .crlf
  587.     lda    inuser
  588.     dcr    a;        to cpm usage
  589.     lxi    d,fcbin
  590.     call    .tfnam;        input file id
  591.     lxi    d,xfrtomsg
  592.     call    tstr;        '==>'
  593.     lda    outuser
  594.     dcr    a;        to cpm usage
  595.     lxi    d,fcbout
  596.     call    .tfnam;        output file id
  597. ;    "    "
  598. ; Check for user abort
  599. ; a,f
  600. ckabt:    mvi    a,csta
  601.     call    .dos
  602.     rz;            no console interrupt
  603.     mvi    a,cin
  604.     call    .dos
  605.     cpi    3
  606.     mvi    a,xusrabt
  607.     jz    exeunt;        user abort
  608.     ret
  609. ;
  610. xfrtomsg:    db    ' ==> $'
  611. ;
  612. ; check fcbs de^ and hl^ are different names, else zero flag
  613. ; a,f
  614. cmpfns:    push    b
  615.     push    d
  616.     push    h
  617.     dcx    h;        pre-decrement
  618.     dcx    d
  619.     mvi    b,12;        names and drive ids
  620. cmpfn1:    inx    h
  621.     inx    d
  622.     ldax    d
  623.     xra    m
  624.     ani    07fh;        ignore attributes
  625.     jnz    cmpfn2
  626.     dcr    b
  627.     jnz    cmpfn1
  628. cmpfn2:    pop    h
  629.     pop    d
  630.     pop    b
  631.     ret
  632. ;
  633. ; Make a standard crunched file header
  634. header:    mvi    a,crnchid shr 8
  635.     ora    a;        set nz, no display yet
  636.     call    outbyt
  637.     mvi    a,crnchid AND 0ffh
  638.     ora    a;        set nz, no display yet
  639.     call    outbyt
  640.     lxi    h,3;        2 already, 0 byte coming
  641.     xchg
  642.     lxi    h,fcbin
  643.     call    outnm;        mark the source file id
  644.     lxi    h,stamp
  645.     call    outstg;        emit the user stamp
  646.     xchg
  647.     shld    xtraout;    save string size etc.
  648.     ori    0ffh;        reset z flag
  649.     mvi    a,0;        emit the 0 string terminator
  650. ;    "    "
  651. ; output a to buffered output file.  Savesp initialized. 
  652. ; Input Z flag triggers display mechanism.  CRN module linkage
  653. ; a,f,c
  654. outbyt:    mov    c,a
  655.     push    h
  656.     cz    show;        display statistics etc.
  657.     lhld    @outbuff
  658.     call    .bfputc
  659.     pop    h
  660.     rnc;            no error
  661.     lhld    savesp
  662.     sphl
  663.     mvi    a,xwrterr
  664.     jmp    exeunt;        i/o error
  665. ;
  666. ; Linkage for crn module
  667. ; a,f,h,l
  668. getchr:    lhld    @inbuff
  669.     call    .bfgetc;    get a byte.  Carry for eof.
  670.     rc;            no checksum update at eof
  671.     lhld    cksum
  672.     push    psw
  673.     add    l
  674.     mov    l,a
  675.     adc    h
  676.     sub    l
  677.     mov    h,a
  678.     shld    cksum
  679.     pop    psw
  680.     ret
  681. ;
  682. ; Output string hl^ until 0 byte. Countem in de
  683. ; a,f,c,h,l
  684. outstg:    mov    a,m
  685.     ora    a
  686.     rz
  687.     inx    d;        count chars
  688.     call    outbyt;        nz flag, will not trip display
  689.     inx    h
  690.     jmp    outstg
  691. ;
  692. ; Output file name hl^.  Full blank fill the type field
  693. outnm:    push    b
  694.     mvi    b,8;        max chars in file name
  695.     push    h;        save start point
  696. outnm1:    inx    h
  697.     mov    a,m
  698.     inx    d;        count chars emitted
  699.     cpi    ' '
  700.     jz    outnm2;        done file name
  701.     call    outbyt;        nz, no display trip
  702.     dcr    b
  703.     jnz    outnm1
  704.     inx    d;        for coming '.'
  705. outnm2:    mvi    a,'.'
  706.     ora    a;        nz, prevent display
  707.     call    outbyt
  708.     pop    h;        get start point back
  709.     lxi    b,8;        point to type field
  710.     dad    b
  711.     mvi    b,3
  712. outnm3:    inx    h
  713.     mov    a,m
  714.     inx    d
  715.     ora    a;        nz, prevent display
  716.     call    outbyt
  717.     dcr    b
  718.     jnz    outnm3
  719.     pop    b
  720.     ret
  721. ;
  722. ; Get input/output records to hl, de respectively
  723. ; a,f,d,e,h,l
  724. inout:    lhld    incnt+1;    LS byte is zero
  725.     dad    h;        double, in records
  726.     lda    incnt
  727.     add    a
  728.     jnc    inout1;        not an extra record
  729.     inx    h
  730. inout1:    adi    252;        2 * (127-1). EOF was counted at end.
  731.     jnc    inout2;        no partial record to round up
  732.     inx    h
  733. inout2:    push    h
  734.     lhld    outcnt;        only useful at end
  735.     mvi    h,0
  736.     xchg
  737.     lhld    xtraout
  738.     dad    d
  739.     lxi    d,127;        round up to records
  740.     dad    d
  741.     dad    h;        double, records to h
  742.     mov    a,h;        additional
  743.     lhld    outcnt+1;    LS byte is zero
  744.     dad    h;        double, to records
  745.     add    l
  746.     mov    l,a;        + the extra bits
  747.     adc    h
  748.     sub    l
  749.     mov    h,a;        form records emitted (rounded up)
  750.     xchg
  751.     pop    h
  752.     ret
  753. ;
  754. ; Show any statistics etc.
  755. ; a,f,h,l
  756. show:    call    ckabt;        check for user abort
  757.     lda    quiet
  758.     ora    a
  759.     rz;            in quiet mode
  760.     push    b
  761.     push    d
  762.     mvi    a,cr
  763.     call    .couta
  764.     call    inout;        get input/output records
  765.     call    tdzs6f;        show input records
  766.     push    h
  767.     xchg
  768.     call    tdzs6f;        show output records
  769.     xchg
  770.     lxi    b,200;        for rounding
  771.     call    .imul;        dehl := de*bc
  772.     pop    b
  773.     call    .idiv;        de := dehl/bc = input/output*200
  774.     xchg
  775.     inx    h;        round result
  776.     call    dvd2hl;        divide / 2 (for 200 above)
  777.     mvi    a,5
  778.     call    .tdzsf
  779.     mvi    a,'%'
  780.     call    .couta
  781.     lhld    nxtcod
  782.     call    tdzs6f
  783.     lhld    ttotal
  784.     call    tdzs6f
  785.     pop    d
  786.     pop    b
  787.     ret
  788. ;
  789. ; Shift hl right 3 (divide by 8), rounding up
  790. ; a,f,h,l
  791. dvd8hl:    push    d
  792.     lxi    d,7
  793.     dad    d
  794.     pop    d
  795.     call    dvd2hl
  796.     call    dvd2hl
  797. ;    "    "
  798. ; Shift hl right 1.  RH bit to carry
  799. ; a,f,h,l
  800. dvd2hl:    mov    a,h
  801.     ora    a
  802.     rar
  803.     mov    h,a
  804.     mov    a,l
  805.     rar
  806.     mov    l,a
  807.     ret
  808. ;
  809. ; Write hl (dec) in 6 char. field. with at least 1 leading blank
  810. ; a,f
  811. tdzs6f:    mvi    a,6
  812.     jmp    .tdzsf
  813. ;
  814. ; Parse the command tail into the stamp buffer
  815. ; a,f,b,d,e,h,l
  816. rstamp:    lxi    h,stamp
  817.     call    .skipblks
  818.     rc;            EOL, no tail
  819.     cpi    '['
  820.     rnz;            not a valid marker
  821.     mvi    b,stpmax-1
  822. rstp1:    dcr    b
  823.     jz    rstp2;        max storage used
  824.     mov    m,a
  825.     inx    h
  826.     cpi    ']'
  827.     jz    rstp3
  828.     inx    d;        (CCP+ can allow lc command tails)
  829.     ldax    d;        not .nextch, don't upshift
  830.     cpi    ' '
  831.     jnc    rstp1
  832. rstp2:    mvi    m,']';        jam in the missing ']'
  833.     inx    h
  834. rstp3:    mvi    m,0;        default EOL
  835.     ret
  836. ;
  837. ; Lock the user # (0 means default) to an absolute value.
  838. ; Returns in range 1..maxuser, and cpm calls use this -1.
  839. ; This is because the buffer system can record "default user"
  840. ; as distinct from "specified user".
  841. ; a,f
  842. usrlok:    call    .xltusr;    now range 0..maxuser
  843.     inr    a;        now 0 is forbidden.
  844.     ret
  845. ;
  846.         dseg;    LINK AFTER all code areas
  847. options:    ds    2;    Standard header
  848. confirm:    ds    1;    Flog for confirmation per file
  849. keepem:        ds    1;    Flag to keep old files
  850. purge:        ds    1;    Flag for copy verification
  851. quiet:        ds    1;    flag for quiet operation
  852.     if    ($-options)-2 ne optlgh
  853.      +++ Error in option storage assignment +++
  854.     endif
  855. ;
  856. entryusr:    ds    1;    User in effect at startup
  857. outspec:    ds    1;    non-zero if output file specified
  858. ;
  859. ; inuser/outuser are 0 for current user, user+1 if specified
  860. inuser:        ds    1;    User # for fcbin
  861. outuser:    ds    1;    User # for fcbout
  862. ;
  863. fcbin:        ds    36;    Input fcb
  864. fcbout:        ds    36;    Output fcb
  865. bufsize:    ds    2;    space available for outbuff
  866. @inbuff:    ds    2;    pointer to input buffer, 2 * bufsize
  867. @outbuff:    ds    2;    pointer to output buffer, 1 * bufsize
  868. @freemem:    ds    2;    pointer to available memory
  869. cksum:        ds    2;    for checksum accumulation
  870. filesdone:    ds    2;    count of files processed
  871. fncount:    ds    2;    count of files to process
  872. fnptr:        ds    2;    pointer to NEXT file to process
  873. savesp:        ds    2;    for aborts during writes
  874. xtraout:    ds    2;    keep track of overhead bytes added
  875. stamp:        ds    stpmax;    User entered stamp
  876.         end
  877. hU