home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / epmsmp.zip / CMPTREE.E < prev    next >
Text File  |  1995-01-09  |  15KB  |  323 lines

  1. /* This compares 2 directories and presents a list of all
  2. files in the first which are different or missing in the second.  I use
  3. it to keep stuff in synch.  E.g., if I bring home a new set of macros,
  4. I do a 'cmptree a:\e_macros f:\e_macros' to see which files have
  5. changed, then do an 'epairs' (see next append) to edit the pairs of
  6. differing files.  Finally, EPM 6.01's EPMCOMP lets me do a fast
  7. comparison of the files to see what's been changed (and to ensure I
  8. don't overwrite modifications I made at home with others I made at
  9. work).  Note:  this only compares directories, not trees.  The name is
  10. because it presents the result in the same format as EPM's TREE command. */
  11.  
  12. -- CMPTREE.E, by Larry Margolis - MARGOLI at YKTVMV
  13.  
  14. compile if not defined(ERROR__MSG)
  15.    include 'english.e'
  16. compile endif
  17.  
  18. compile if not defined(MB_OK)
  19.    include 'stdconst.e'
  20. compile endif
  21.  
  22. const
  23.    TREES_HEADER = '  Date        Time     FileSize    EA-size  Attr.  Full name...'
  24.  
  25. defmain
  26.    'cmptree' arg(1)
  27.  
  28. defc cmptree =
  29.    parse arg filespec1 filespec2 junk
  30.    if filespec1='' | junk<>'' then
  31.       sayerror 'Invalid parameters - takes 2 directory specs.'
  32.       return
  33.    endif
  34.    if filespec2='' then
  35.       filespec2=filespec1
  36.       filespec1='a:'
  37.    endif
  38.    if substr(filespec1,2)=':\' then filespec1=leftstr(filespec1,2); endif
  39.    if rightstr(filespec1,1)<>'\' & not verify(filespec1,'*?','M') then
  40.       filespec1=filespec1'\*.*'
  41.    endif
  42.    l1prefix=leftstr(filespec1, lastpos('\',filespec1))
  43.    if rightstr(filespec2,1)<>'\' then filespec2=filespec2'\'; endif
  44.  
  45.    getfileid startid
  46. compile if EPM
  47.    'xcom e /c .tree'
  48. compile else
  49.    'xcom e /q /n .tree'
  50. compile endif
  51.    if rc & rc<>sayerror('New file') then
  52. compile if EPM
  53.       sayerror ERROR__MSG rc BAD_TMP_FILE__MSG sayerrortext(rc)
  54. compile else
  55.       sayerror ERROR__MSG rc BAD_TMP_FILE__MSG
  56. compile endif
  57.       return rc
  58.    endif
  59.    getfileid tree_id
  60.    file_count = 0
  61.    pair_count = 0
  62.    attribute = 55        -- Want to see all files
  63.    files_truncated = 0
  64.    res = tree_searchdir(filespec1, attribute, file_count, pair_count, tree_id, filespec2)
  65.  
  66.    if tree_id.modify then
  67. compile if EVERSION < '5.60'
  68.       if res = -278 then  -- sayerror("Lines truncated")
  69.          replaceline TREES_HEADER'   ('LINES_TRUNCATED__MSG')', 1
  70.       else
  71.          replaceline TREES_HEADER, 1
  72.       endif
  73. compile else
  74.       replaceline TREES_HEADER, 1
  75. compile endif
  76.       insertline '══════════  ════════  ═════════  ═════════  ═════  ════════════', 2
  77.       insertline '          'file_count 'file(s), 'pair_count 'pairs', .last+1
  78. compile if EVERSION >= '5.50'
  79.       .lineg = 3
  80. compile else
  81.       3
  82. compile endif
  83.       .col = 52
  84. compile if EPM
  85.       .titletext = 'CmpTree:' arg(1)
  86.       'postme monofont'
  87.       'postme tabs 1 13 23 34 45 52'
  88. compile else
  89.       .filename = '.CmpTree:' arg(1)
  90.       .tabs = 1 13 23 34 45 52
  91. compile endif
  92.       sayerror ALT_1_LOAD__MSG
  93.       .modify = 0
  94. compile if EVERSION < '5.60'
  95.       if res = -278 then  -- sayerror("Lines truncated")
  96.          refresh
  97.  compile if EPM  -- Do a sayerror; it will stay on messageline
  98.          sayerror 'Warning:  Some lines truncated at column 255.'
  99.  compile else  -- must do a messageNwait to be sure it's not erased by a "Tree incomplete" message.
  100.          messageNwait('Warning:  Some lines truncated at column 255.')
  101.  compile endif
  102.       endif
  103. compile endif
  104.    else
  105.       'xcom q'
  106.       sayerror 'No new files.'
  107.    endif
  108.  
  109.  
  110. ; The arguments to Tree_SearchDir are as follows:
  111. ;
  112. ; filename:  The fully-qualified name we're searching for.
  113. ; attribute:  The file attributes we pass to DosFindFirst
  114. ; file_count:  Incremented for each "hit".
  115. ; pair_count:  Incremented for each "hit" on *both* directories.
  116. ; out_fid:  The fileid where the output is to be appended.
  117. ; filespec2: The path prefix of the directory we're comparing with.
  118. ;
  119. defproc tree_searchdir(filename, attribute, var file_count, var pair_count, out_fid, filespec2)
  120.    wild_prefix=substr(filename,1,lastpos('\', filename))
  121.    if wild_prefix='' & substr(filename, 2, 1)=':' then wild_prefix = leftstr(filename, 2); endif
  122.    truncated = 0  -- Initialize
  123.    namez    = filename\0    -- ASCIIZ
  124. compile if EPM
  125.    resultbuf = copies(\0, 300)  -- Might need to allocate a buffer if < EPM 5.60
  126. compile else
  127.    resultbuf = substr('', 1, 300, \0)
  128. compile endif
  129.    resultbuf2 = resultbuf
  130. compile if EVERSION >= 6  -- EPM32:  32-bit version
  131.    dirhandle = \xff\xff\xff\xff  -- Ask system to assign us a handle
  132.    searchcnt = atol(1)   -- Search count; we're only asking for 1 file at a time here.
  133.    result=dynalink32('DOSCALLS',             -- dynamic link library name
  134.                      '#264',                 -- ordinal value for DOS32FINDFIRST
  135.                      address(namez)      ||  -- Filename we're looking for
  136.                      address(dirhandle)  ||  -- Pointer to the handle
  137.                      atol(attribute)     ||  -- Attribute value describing desired files
  138.                      address(resultbuf)  ||  -- string address
  139.                      atol(length(resultbuf)) ||
  140.                      address(searchcnt)  ||  -- Pointer to the count; system updates
  141.                      atol(2), 2)             -- File info level 2 requested
  142. compile else
  143.    dirhandle = \255\255  -- Ask system to assign us a handle
  144.    searchcnt = atoi(1)   -- Search count; we're only asking for 1 file at a time here.
  145.    result=dynalink('DOSCALLS',             -- dynamic link library name
  146.                    '#184',                 -- ordinal value for DOSFINDFIRST2
  147.                    address(namez)      ||  -- Filename we're looking for
  148.                    address(dirhandle)  ||  -- Pointer to the handle
  149.                    atoi(attribute)     ||  -- Attribute value describing desired files
  150.                    address(resultbuf)  ||  -- string address
  151.                    atoi(length(resultbuf)) ||
  152.                    address(searchcnt)  ||  -- Pointer to the count; system updates
  153.                    atoi(2)             ||  -- FileInfoLevel
  154.                    atol(0))                -- reserved
  155. compile endif -- EVERSION >= 6
  156.  
  157.    if result & result<>18 then  -- unexpected error
  158.       sayerror 'result' result 'from DosFindFirst' filename
  159.       return result
  160.    endif
  161.    if not result then
  162.       loop
  163. compile if EVERSION >= 6  -- EPM32:  32-bit version
  164.          filename = substr(resultbuf, 34, asc(substr(resultbuf, 33, 1)))
  165.          skip = filename='.' | filename='..'
  166.          if not skip then
  167.             tmphandle = atol(1)
  168.             searchcnt = atol(1)   -- Search count; we're only asking for 1 file at a time here.
  169.             filename2=filespec2 || filename
  170.             namez=filename2 || \0
  171.             result2=dynalink32('DOSCALLS',            -- dynamic link library name
  172.                               '#264',                 -- ordinal value for DOS32FINDFIRST
  173.                               address(namez)      ||  -- Filename we're looking for
  174.                               address(tmphandle)  ||  -- Pointer to the handle
  175.                               atol(55)            ||  -- Attribute value describing desired files
  176.                               address(resultbuf2) ||  -- string address
  177.                               atol(length(resultbuf2)) ||
  178.                               address(searchcnt)  ||  -- Pointer to the count; system updates
  179.                               atol(2), 2)             -- File info level 2 requested
  180.             if not result2 &                                        -- Good return code
  181.                substr(resultbuf, 13,4) = substr(resultbuf2, 13,4) & -- Dates the same
  182.                substr(resultbuf, 17,4) = substr(resultbuf2, 17,4)   -- Sizes the same
  183.             then
  184.                skip = 1
  185.             endif
  186.          endif
  187. compile else
  188.          filename = substr(resultbuf, 28, asc(substr(resultbuf, 27, 1)))
  189.          skip = filename='.' | filename='..'
  190.          if not skip then
  191.             tmphandle = atoi(1)
  192.             searchcnt = atoi(1)   -- Search count; we're only asking for 1 file at a time here.
  193.             filename2=filespec2 || filename
  194.             namez=filename2 || \0
  195.             result2=dynalink('DOSCALLS',            -- dynamic link library name
  196.                             '#184',                 -- ordinal value for DOSFINDFIRST2
  197.                             address(namez)      ||  -- Filename we're looking for
  198.                             address(tmphandle)  ||  -- Pointer to the handle
  199.                             atoi(55)            ||  -- Attribute value describing desired files
  200.                             address(resultbuf2) ||  -- string address
  201.                             atoi(length(resultbuf2)) ||
  202.                             address(searchcnt)  ||  -- Pointer to the count; system updates
  203.                             atoi(2)             ||  -- FileInfoLevel
  204.                             atol(0))                -- reserved
  205.             if not result2 &                                        -- Good return code
  206.                substr(resultbuf,  9,4) = substr(resultbuf2,  9,4) & -- Dates the same
  207.                substr(resultbuf, 13,4) = substr(resultbuf2, 13,4)   -- Sizes the same
  208.             then
  209.                skip = 1
  210.             endif
  211.          endif
  212. compile endif -- EVERSION >= 6
  213.          if not skip then
  214.             filename = wild_prefix || filename
  215.             file_count = file_count + 1 + (result2=0)
  216.             call format_record(resultbuf, filename, out_fid)
  217.             if not result2 then
  218.                pair_count = pair_count + 1
  219.                call format_record(resultbuf2, filename2, out_fid)
  220. compile if EVERSION < '5.60'
  221.                if length(filename2) > 203 then  -- Full filename starts in col 52
  222.                   truncated = 1
  223.                endif
  224. compile endif
  225.             endif
  226. compile if EVERSION < '5.60'
  227.             if length(filename) > 203 then  -- Full filename starts in col 52
  228.                truncated = 1
  229.             endif
  230. compile endif
  231.          endif
  232. compile if EVERSION >= 6  -- EPM32:  32-bit version
  233.          result=dynalink32('DOSCALLS',             -- dynamic link library name
  234.                           '#265',                 -- ordinal value for DOS32FINDNEXT
  235.                           dirhandle           ||  -- Directory handle, returned by DosFindFirst(2)
  236.                           address(resultbuf)  ||  -- address of result buffer
  237.                           atol(length(resultbuf)) ||
  238.                           address(searchcnt), 2)  -- Pointer to the count; system updates
  239. compile else
  240.          result=dynalink('DOSCALLS',             -- dynamic link library name
  241.                          '#65',                  -- ordinal value for DOSFINDNEXT
  242.                          dirhandle           ||  -- Directory handle, returned by DosFindFirst(2)
  243.                          address(resultbuf)  ||  -- address of result buffer
  244.                          atoi(length(resultbuf)) ||
  245.                          address(searchcnt) )    -- Pointer to the count; system updates
  246. compile endif -- EVERSION >= 6
  247.          if result then
  248. compile if EVERSION >= 6  -- EPM32:  32-bit version
  249.             call dynalink32('DOSCALLS',             -- dynamic link library name
  250.                             '#263',                 -- ordinal value for DOS32FINDCLOSE
  251.                             dirhandle)              -- Directory handle, returned by DosFindFirst(2)
  252. compile else
  253.             call dynalink('DOSCALLS',             -- dynamic link library name
  254.                           '#63',                  -- ordinal value for DOSFINDCLOSE
  255.                           dirhandle)              -- Directory handle, returned by DosFindFirst(2)
  256. compile endif -- EVERSION >= 6
  257.             if result<>18 then
  258.                sayerror 'Unexpected error' result 'from DosFindNext'
  259.             endif
  260.             leave
  261.          endif
  262.       endloop
  263.    endif  -- result from DosFindFirst
  264. compile if EVERSION < '5.60'
  265.    if truncated then
  266.       return -278  -- sayerror("Lines truncated")
  267.    endif
  268. compile endif
  269.  
  270. defproc format_record(resultbuf, filename, out_fid)
  271. compile if EVERSION >= 6  -- EPM32:  32-bit version
  272.          fileattrib = ltoa(substr(resultbuf,25,4),10)
  273.          filedate = substr(resultbuf, 13, 4)
  274.          file_size = ltoa(substr(resultbuf,17,4),10)
  275. ;        filealloc = ltoa(substr(resultbuf,21,4),10)
  276.          ea_size = ltoa(substr(resultbuf,29,4),10)
  277. compile else
  278.          fileattrib = itoa(substr(resultbuf,21,2),10)
  279.          filedate = substr(resultbuf, 9, 4)
  280.          file_size = ltoa(substr(resultbuf,13,4),10)
  281. ;        filealloc = ltoa(substr(resultbuf,17,4),10)
  282.          ea_size = ltoa(substr(resultbuf,23,4),10)
  283. compile endif -- EVERSION >= 6
  284.          date = ltoa(substr(filedate,1,2)\0\0,10); time = ltoa(substr(filedate,3,2)\0\0,10)
  285.          year = date % 512; date = date // 512
  286.          month = date % 32; day = date // 32 % 1     -- %1 to drop fraction.
  287.          date = year+1980'-'rightstr(month,2,0)'-'rightstr(day,2,0)
  288.          hour = time % 2048; time = time // 2048
  289.          min = time % 32; sec = time // 32 * 2 % 1
  290.          time = rightstr(hour,2)':'rightstr(min,2,0)':'rightstr(sec,2,0)
  291.          if ea_size=4 then
  292.             ea_size=0
  293. compile if EVERSION >= 6
  294.          else
  295.             ea_size=ea_size%2
  296. compile endif
  297.          endif
  298.          fileattrib = fileattrib // 64
  299.          attr_string = '     '
  300.          if fileattrib % 32 then
  301.             attr_string = overlay('A', attr_string, 1)
  302.             fileattrib = fileattrib // 32
  303.          endif
  304.          if fileattrib % 16 then
  305.             attr_string = overlay('D', attr_string, 2)
  306.             file_size = '<dir>'
  307.             fileattrib = fileattrib // 16
  308.          endif
  309.          if fileattrib % 4 then
  310.             attr_string = overlay('S', attr_string, 3)
  311.             fileattrib = fileattrib // 4
  312.          endif
  313.          if fileattrib % 2 then
  314.             attr_string = overlay('H', attr_string, 4)
  315.             fileattrib = fileattrib // 2
  316.          endif
  317.          if fileattrib  then
  318.             attr_string = overlay('R', attr_string, 5)
  319.          endif
  320.          file_size = rightstr(file_size, 10)
  321.          out_line = date'  'time file_size rightstr(ea_size,10)'  'attr_string'  'filename
  322.          insertline out_line, out_fid.last + 1, out_fid
  323.