home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / filutl / comp_pv.arc / COMP.A86 next >
Encoding:
Text File  |  1989-08-06  |  10.7 KB  |  605 lines

  1. ;    COMP    Replacement for the messy-dos command of the same name.
  2.  
  3. ;    Usage:    comp [/#] file1 [file2]
  4. ;        where file1 and file2 may be directories or may contain
  5. ;        wildcards (but not both).  The default for file2 is the current
  6. ;        directory on the current disk.  The switch gives the maximum
  7. ;        number of errors to report per file.  Default is 65535 if file1
  8. ;        refers to a single file, 10 otherwise.
  9. ;        The '/' in the switch refers to the switch character.
  10.  
  11. ;    Author:  Paul Vojta
  12.  
  13. stdout    equ    1
  14. stderr    equ    2
  15.  
  16. CR    equ    13
  17. LF    equ    10
  18. TAB    equ    9
  19.  
  20. fn1    equ    word [5ch]    ;filename portion of string 1
  21. str2    equ    word [5eh]    ;string 2
  22. fn2    equ    word [60h]
  23. pat2    equ    62h        ;pattern for filling in wild cards in filename 2
  24. str1    equ    70h
  25.  
  26. attr    equ    21        ;byte in area43 (see below)
  27. flname    equ    30        ;ditto
  28.  
  29. ;    Begin.  Set disk transfer address and slash.
  30.  
  31.     mov    dx,offset area43
  32.     mov    ah,1ah
  33.     int    21h
  34.     mov    ax,3700h
  35.     int    21h
  36.     cmp    dl,'/'
  37.     jne    f1
  38.     mov    byte slash,'\'
  39. f1:    cld
  40.  
  41. ;    Compute buffer size.
  42.  
  43.     mov    ax,sp
  44.     sub    ax,offset buf+100h
  45.     shr    ax,1
  46.     mov    al,0
  47.     mov    word buflen,ax
  48.  
  49. ;    Start scanning parameters.
  50.  
  51.     mov    si,81h
  52. f2:    lodsb            ;skip spaces
  53.     cmp    al,' '
  54.     je    f2        ;if space
  55.     cmp    al,TAB
  56.     je    f2        ;if tab
  57.     cmp    al,dl
  58.     jne    f7        ;if not switch
  59.     xor    bx,bx        ;value of parameter
  60.     mov    cx,10
  61. f3:    lodsb
  62.     sub    al,'0'
  63.     jb    f4        ;if not digit
  64.     cmp    al,9    
  65.     ja    f4        ;ditto
  66.     xchg    ax,bx
  67.     mul    cx
  68.     mov    bh,0
  69.     add    bx,ax
  70.     jmp    f3
  71.  
  72. f4:    mov    maxerrs,bx    ;save argument
  73.     inc    si        ;counteract later `dec'
  74.     cmp    al,' '-'0'
  75.     je    f7        ;if ended with space
  76.     cmp    al,TAB-'0'
  77.     je    f7        ;if ended with tab
  78.     mov    dx,offset msg1    ;illegal switch
  79.     cmp    al,CR-'0'
  80.     jne    f6        ;error quit
  81. f5:    mov    dx,offset msg2    ;insufficient parameters
  82. f6:    jmp    errend
  83.  
  84. f7:    dec    si        ;get first parameter
  85.     mov    di,str1
  86.     call    getparm
  87.     jz    f5        ;if no parameter present
  88.     pushf
  89.     push    area43+attr
  90.     mov    fn1,bx        ;beginning of file name 1
  91.     lea    di,[bx+14]
  92.     mov    str2,di        ;start of second string
  93.     call    getparm
  94.     mov    fn2,bx
  95.     mov    si,bx        ;set up pat2
  96.     mov    di,pat2
  97.     mov    cx,7
  98.     rep    movsw
  99.     pop    area43+attr
  100.     popf
  101.     jns    f9        ;if wild cards
  102.     cmp    word maxerrs,0
  103.     jnz    f8        ;if maxerrs given
  104.     mov    word maxerrs,-1    ;default = -1
  105.     mov    byte hyph,0    ;don't print hyphens
  106. f8:    call    doit
  107.     jmp    short quit
  108.  
  109. ;    Compare multiple files.
  110.  
  111. f9:    cmp    word maxerrs,0
  112.     jnz    f10        ;if maxerrs given
  113.     mov    word maxerrs,10    ;default = 10
  114. f10:    mov    dx,str1
  115.     mov    cx,1
  116.     mov    ah,4eh        ;find first file
  117.     int    21h
  118.     jc    f12        ;if not found
  119.     mov    word okmsg,offset crlf
  120.  
  121. f11:    mov    si,offset area43+flname
  122.     mov    di,fn1
  123.     mov    cx,7
  124.     rep    movsw
  125.     mov    dx,str1
  126.     call    print
  127.     call    doit
  128.     mov    ah,4fh        ;find next file
  129.     int    21h
  130.     jnc    f11
  131.  
  132. quit:    mov    ax,4c00h
  133.     int    21h
  134.  
  135. f12:    mov    dx,offset msg3    ;file not found
  136.     jmp    errend
  137.  
  138. ;    GETPARM    Get next parameter.  Upon entry, si points to the next character
  139. ;        in the command string and di points where to put it.  On exit,
  140. ;        si points to the next+1 character in the command line, di points
  141. ;        to the end of the parameter, and bx points to the beginning of
  142. ;        the filename part of the string.  AH=0 if no parameter, 1 if
  143. ;        wild cards are present, and 80h if it is a file.  Flags are set
  144. ;        according to AH.
  145.  
  146. getparm:mov    str2,di
  147.  
  148. gp0:    lodsb        ;skip separators
  149.     cmp    al,' '
  150.     je    getparm
  151.     cmp    al,TAB
  152.     je    getparm
  153.     cmp    al,CR
  154.     mov    ah,0
  155.     je    gp8        ;if C/R
  156.  
  157. gp1:    stosb        ;copy until separator
  158.     lodsb
  159.     cmp    al,' '        ;check for separator
  160.     je    gp2
  161.     cmp    al,TAB
  162.     je    gp2
  163.     cmp    al,CR
  164.     jne    gp1
  165.     dec    si
  166.  
  167. ;    Process the parameter.
  168.  
  169. gp2:    mov    byte [di],0
  170.     mov    bx,di
  171.     mov    ah,81h        ;scan for start of file name
  172.  
  173. gp3:    dec    bx
  174.     cmp    bx,str2
  175.     jl    gp5        ;if past beginning
  176.     mov    al,[bx]
  177.     cmp    al,slash
  178.     je    gp6        ;if '\' or '/'
  179.     cmp    al,'?'        ;check for wild cards
  180.     je    gp4
  181.     cmp    al,'*'
  182.     jne    gp3
  183. gp4:    and    ah,7fh        ;clear no-wild bit
  184.     jmp    gp3
  185.  
  186. gp5:    cmp    byte [bx+2],':'    ;no dir. given; remove drive letter
  187.     jne    gp6
  188.     inc    bx
  189.     inc    bx
  190.  
  191. gp6:    inc    bx
  192.     or    ah,ah
  193.     jns    gp9        ;if wild cards
  194.     cmp    bx,di
  195.     mov    ah,1
  196.     je    gp8        ;if no file name
  197.     mov    ax,4300h    ;see if directory
  198.     mov    dx,str2
  199.     int    21h
  200.     mov    ah,80h
  201.     jc    gp9        ;if not found
  202.     test    cl,10h        ;test attribute for directory
  203.     jz    gp9        ;if file
  204.  
  205. ;    It's a directory.
  206.  
  207.     mov    al,slash
  208.     stosb
  209.     mov    ah,1
  210.  
  211. gp8:    push    ax
  212.     mov    bx,di        ;add "*.*"
  213.     mov    ax,'.*'
  214.     stosw
  215.     stosb
  216.     mov    byte [di],0
  217.     pop    ax
  218.  
  219. ;    Return.
  220.  
  221. gp9:    or    ah,ah        ;set flags
  222.     ret
  223.  
  224. ;    DOIT    Do it.  Str1, str2, and pat2 are assumed to be set up.
  225.  
  226. doit:    mov    si,pat2
  227.     mov    bx,fn1
  228.     mov    di,fn2
  229.     mov    cx,8
  230.     call    dopart        ;translate wild cards for main part of file name
  231.     dec    si
  232. d1:    lodsb            ;skip to file extension
  233.     or    al,al
  234.     jz    d3        ;if end of file
  235.     cmp    al,'.'
  236.     jne    d1
  237.     stosb            ;store '.'
  238. d2:    mov    al,byte [bx]    ;skip to extension in first file name
  239.     cmp    al,0
  240.     jz    d2a
  241.     inc    bx
  242.     cmp    al,'.'
  243.     jne    d2
  244. d2a:    mov    cl,3        ;translate wild cards for file extension
  245.     call    dopart
  246.  
  247. ;    Set up files.
  248.  
  249. d3:    mov    byte [di],0    ;store terminating zero
  250.     mov    dx,str1        ;open file
  251.     mov    ax,3d00h
  252.     int    21h
  253.     if c    jmp    err    ;if error
  254.     mov    si,ax
  255.     mov    ax,3d00h    ;open file
  256.     mov    dx,str2
  257.     int    21h
  258.     jnc    d3a        ;if no error
  259.     cmp    ax,2
  260.     if ne    jmp    err1    ;if not file-not-found
  261.     call    hyphens
  262.     mov    dx,offset fil
  263.     call    print
  264.     mov    dx,str2
  265.     call    print
  266.     mov    dx,offset msg3+4;' not found.'
  267.     call    print
  268.     mov    ah,3eh        ;close other file
  269.     mov    bx,si
  270.     int    21h
  271.     if c    jmp    err
  272.     ret
  273.  
  274. d3a:    mov    bx,ax
  275.     mov    word bufno,0
  276.     mov    word errcnt,0
  277.  
  278. ;    Loop for comparing.  si, bx = file handles.
  279.  
  280. d4:    mov    cx,buflen    ;read from file 1
  281.     mov    dx,offset buf
  282.     xchg    bx,si
  283.     mov    ah,3fh
  284.     int    21h
  285.     if c    jmp    err    ;if error
  286.     mov    word len1,ax
  287.     push    bx
  288.     mov    bx,si
  289.     mov    si,dx
  290.     add    dx,cx        ;read from file 2
  291.     mov    ah,3fh
  292.     int    21h
  293.     if c    jmp    err
  294.     mov    word len2,ax
  295.     push    bx
  296.     mov    di,dx
  297.     cmp    ax,len1
  298.     jle    d4z        ;find minimum length
  299.     mov    ax,len1
  300. d4z:    cmp    ax,buflen    ;whether this is the last
  301.     pushf
  302.  
  303. ;    Begin loop over mini-buffers
  304.  
  305. d5:    mov    cx,256
  306.     cmp    ax,cx
  307.     jae    d5a
  308.     mov    cx,ax
  309. d5a:    sub    ax,cx
  310.     push    ax
  311.  
  312. ;    Do comparison.
  313.  
  314. d6:    repz    cmpsb
  315.     je    d11        ;if buffers equal
  316.  
  317. ;    Print error message.
  318.  
  319.     push    cx
  320.     push    di
  321.     cmp    word errcnt,0
  322.     jne    d7        ;if not the first error
  323.     mov    dx,offset hdr    ;print header
  324.     call    print
  325. d7:    inc    word errcnt
  326.     mov    di,offset lyne
  327.     mov    dx,di
  328.     mov    ax,bufno
  329.     cmp    ah,0
  330.     je    d8        ;if not a huge file
  331.     push    ax
  332.     mov    al,ah
  333.     call    hex
  334.     stosw
  335.     pop    ax
  336. d8:    call    hex
  337.     stosw
  338.     mov    ax,si
  339.     sub    ax,offset buf+1
  340.     call    hex
  341.     stosw
  342.     pop    bx        ;old di
  343.     mov    al,[si-1]    ;convert data bytes to hex
  344.     mov    di,offset lyne+6
  345.     call    dumpbyte
  346.     mov    al,[bx-1]
  347.     call    dumpbyte
  348.  
  349. ;    Trim spaces from input line.
  350.  
  351. d9:    dec    di
  352.     cmp    byte [di],' '
  353.     je    d9        ;if space
  354.     inc    di
  355.     mov    ax,CR+256*LF
  356.     stosw
  357.     mov    al,0
  358.     stosb
  359.     mov    di,bx
  360.     call    print        ;print the line
  361.     pop    cx
  362.     mov    ax,errcnt
  363.     cmp    ax,maxerrs
  364.     jb    d10        ;if within limits
  365.     mov    dx,offset atleast
  366.     call    print
  367.     pop    ax
  368.     popf
  369.     pop    bx
  370.     pop    si
  371.     jmp    short d14
  372.  
  373. d10:    or    cx,cx
  374.     jnz    d6        ;if more comparisons to do
  375.  
  376. d11:    inc    word bufno    ;end mini-buffer
  377.     pop    ax
  378.     or    ax,ax
  379.     if nz    jmp    d5        ;if more in this buffer
  380.     popf
  381.     pop    bx        ;get file handles
  382.     pop    si
  383.     if e    jmp    d4        ;if not eof yet
  384.     mov    ax,len2
  385.     sub    ax,len1
  386.     mov    cl,'2'
  387.     jg    d12        ;if excess bytes on file 2
  388.     je    d14        ;if exact match
  389.     dec    cx
  390.     xchg    bx,si
  391.     neg    ax
  392.  
  393. ;    Excess bytes on some file.
  394.  
  395. d12:    mov    byte xs+26,cl
  396.     mov    len1,ax
  397.     mov    cx,buflen
  398.     mov    dx,offset buf
  399.  
  400. d13:    mov    ah,3fh        ;read excess bytes
  401.     int    21h
  402.     jc    err
  403.     add    len1,ax
  404.     cmp    ax,cx
  405.     je    d13        ;if more to go
  406.  
  407.     mov    al,len1+1    ;form and print excess-bytes message
  408.     call    hex
  409.     mov    xs,ax
  410.     mov    al,len1
  411.     call    hex
  412.     mov    xs+2,ax
  413.     push    bx
  414.     mov    dx,offset xs
  415.     call    print
  416.     pop    bx
  417.     inc    word errcnt
  418.     
  419. ;    Close files and print error count.
  420.  
  421. d14:    mov    ah,3eh        ;close file
  422.     int    21h
  423.     jc    err
  424.     mov    ah,3eh
  425.     xchg    bx,si
  426.     int    21h
  427.     jc    err
  428.  
  429.     mov    dx,okmsg    ;get OK-message address
  430.     mov    ax,errcnt
  431.     or    ax,ax
  432.     jz    d17        ;if no errors
  433.     mov    bx,10
  434.     xor    cx,cx
  435.  
  436. d15:    xor    dx,dx        ;convert to decimal
  437.     div    bx
  438.     add    dl,'0'
  439.     push    dx
  440.     inc    cx
  441.     or    ax,ax
  442.     jnz    d15        ;if more digits
  443.     mov    ah,2
  444.  
  445. d16:    pop    dx        ;print the number
  446.     int    21h
  447.     loop    d16
  448.     mov    dx,offset nerrs
  449.  
  450. ;    Common ending routine.
  451.  
  452. d17:    jmp    short print    ;call print and return
  453.  
  454. ;    Process errors.
  455.  
  456. err1:    cmp    ax,5
  457.     jne    err        ;if not invalid path
  458.     call    hyphens
  459.     mov    dx,offset msg4
  460.     jmp    short errend
  461.  
  462. err:    mov    dx,offset msg3    ;file not found
  463.     cmp    ax,2
  464.     je    errend        ;if file not found
  465.     call    hyphens
  466.     mov    dx,offset msg5    ;I/O error
  467. ;    jmp    short errend    ;(control falls through)
  468.  
  469. ;    Ending stuff.
  470.  
  471. errend:    mov    bx,stderr
  472.     call    print0
  473.     mov    ax,4c01h
  474.     int    21h
  475.  
  476. ;    HYPHENS    Print hyphens (but only if this is a multiple comp).
  477. ;    PRINT    Print the line at (DX).  Destroys AX,CX.
  478. ;    PRINT0    Same as above, but also requires BX = output handle.
  479.  
  480. hyphens:mov    dx,offset hyph
  481. print:    mov    bx,stdout
  482. print0:    push    di
  483.     mov    di,dx
  484.     mov    cx,-1
  485.     mov    al,0        ;find length
  486.     repnz    scasb
  487.     not    cx
  488.     dec    cx
  489.     mov    ah,40h
  490.     int    21h
  491.     pop    di
  492.     ret
  493.  
  494. ;    DOPART    Copy string from [si] to [di], changing wild cards to those
  495. ;        present in [bx].  This copies up to CX characters.
  496.  
  497. dopart:    lodsb
  498.     cmp    al,'.'
  499.     je    dp5        ;if end of this part
  500.     cmp    al,0
  501.     je    dp5        ;if end
  502.     cmp    al,'*'
  503.     jne    dp1
  504.     dec    si
  505.     mov    al,'?'
  506. dp1:    cmp    al,'?'
  507.     jne    dp2        ;if not wild card
  508.     mov    al,[bx]
  509.     cmp    al,'.'
  510.     je    dp3
  511.     cmp    al,0
  512.     je    dp3
  513. dp2:    stosb
  514. dp3:    cmp    byte [bx],'.'    ;advance [bx], but not past '.' or end of string
  515.     je    dp4
  516.     cmp    byte [bx],0
  517.     je    dp4
  518.     inc    bx
  519. dp4:    loop    dopart
  520.     inc    si
  521. dp5:    ret
  522.  
  523. ;    DUMPBYTE Print a byte in hexadecimal and then as a character.
  524.  
  525. dumpbyte:push    ax
  526.     mov    ax,'  '
  527.     stosw
  528.     pop    ax
  529.     push    ax
  530.     call    hex
  531.     stosw
  532.     mov    al,' '
  533.     stosb
  534.     pop    ax
  535.     cmp    al,0
  536.     je    db2        ;if null character
  537.     cmp    al,' '
  538.     jb    db1        ;if control character
  539.     cmp    al,127
  540.     ja    db2        ;if not a character
  541.     mov    ah,al
  542.     mov    al,''''        ;save normal character
  543.     stosw
  544.     stosb
  545.     ret
  546.  
  547. db1:    add    al,'A'-1    ;control character
  548.     mov    ah,al
  549.     mov    al,'^'
  550.     jmp    db3
  551.  
  552. db2:    mov    ax,'  '        ;just put spaces
  553. db3:    stosw
  554.     mov    al,' '
  555.     stosb
  556.     ret
  557.  
  558. ;    HEX    Convert a byte to hexadecimal.  Destroys (CL).
  559.  
  560. hex:    mov    ah,0
  561.     mov    cl,4
  562.     shl    ax,cl
  563.     shr    al,cl
  564.     add    al,90h        ;these four instructions change to ascii hex
  565.     daa
  566.     adc    al,40h
  567.     daa
  568.     xchg    al,ah
  569.     add    al,90h
  570.     daa
  571.     adc    al,40h
  572.     daa
  573.     ret
  574.  
  575. slash    db    '/'
  576. msg1    db    'Illegal switch.',CR,LF,0
  577. msg2    db    'Insufficient parameters.',CR,LF,0
  578. msg3    db    'File not found.',CR,LF,0
  579. msg4    db    'Access denied.',CR,LF,0
  580. msg5    db    'I/O error.',CR,LF,0
  581. fil    db    'File ',0
  582. hyph    db    '--',0
  583. hdr    db    CR,LF,'Byte    File 1  File 2',CR,LF,0
  584. lyne    db    'xxxx    aa      bb "x"',CR,LF,0
  585. xs    db    'nnnn excess bytes on file x.',CR,LF,0
  586. nerrs    db    ' error(s).',CR,LF,0
  587. ok    db    'Files compare OK.'    ;(continues...)
  588. crlf    db    CR,LF,0
  589. atleast    db    'At least ',0
  590.  
  591. okmsg    dw    ok
  592. maxerrs    dw    0
  593.  
  594. end1:
  595.  
  596. area43    equ    end1
  597. errcnt    equ    word end1+43
  598. bufno    equ    word end1+45
  599. len1    equ    word end1+47
  600. len2    equ    word end1+49
  601. buflen    equ    word end1+51
  602. buf    equ    end1+53
  603.  
  604.     end
  605.