home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume13 / combine / part01 next >
Encoding:
Text File  |  1990-06-15  |  48.3 KB  |  1,392 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v13i054: combine: 3 file compare/merge utility (part 1of3)
  3. from: cliff@gcx1.SSD.CSD.HARRIS.COM (Cliff Van Dyke)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 13, Issue 54
  7. Submitted-by: cliff@gcx1.SSD.CSD.HARRIS.COM (Cliff Van Dyke)
  8. Archive-name: combine/part01
  9.  
  10. Please acknowledge receipt of this submission.
  11.  
  12. The combine utility is a general purpose utility to compare 2 or 3 ASCII files.
  13. The output of the utility is either a report describing the differences
  14. between the files or a file which is the composite of the original files.
  15. The output report format of this utility is friendlier than the Unix diff
  16. utility. The composite output file feature of this utility is unique in
  17. its presentation of file differences.
  18.  
  19. The combine utility uses a fundamental comparison algorithm as described
  20. in "A technique for Isolating differences between files";
  21. Communications of the ACM; April 1978; Volume 21 Number 4.
  22.  
  23. The combine utility is being contributed to the public domain. The disclaimer
  24. at the begining of each file is required by my employer (Harris Computer
  25. Systems Division) to ensure that Harris is not liable in the event
  26. of errors in the software.
  27.  
  28. The combine utility has been in use at HCSD for 5 years. It runs on
  29. Harris HCX and GCX architectures (CX/UX 4.1) and a SUN 3/160
  30. (SUNOS version 4.0), 
  31. --
  32. Cliff Van Dyke                   cliff@ssd.csd.harris.com
  33. Harris Computer Systems          ...!{uunet,novavax}!hcx1!cliff
  34. 2101 W. Cypress Creek Rd.
  35. Ft. Lauderdale, FL 33309-1892    Tel: (305) 973-5349
  36. # This is a shell archive.  Remove anything before this line,
  37. # then unpack it by saving it in a file and typing "sh file".
  38. #
  39. # Wrapped by cliff on Tue Feb 13 14:26:20 EST 1990
  40. # Contents:  README combine.1 design_spec combine.h Makefile
  41.  
  42. echo x - README
  43. sed 's/^@//' > "README" <<'@//E*O*F README//'
  44. The combine utility is a general purpose utility to compare 2 or 3 ASCII files.
  45. The output of the utility is either a report describing the differences
  46. between the files or a file which is the composite of the original files.
  47. The output report format of this utility is friendlier than the Unix diff
  48. utility. The composite output file feature of this utility is unique in
  49. its presentation of file differences.
  50.  
  51. The combine utility uses a fundamental comparison algorithm as described
  52. in "A technique for Isolating differences between files";
  53. Communications of the ACM; April 1978; Volume 21 Number 4.
  54.  
  55. The combine utility is being contributed to the public domain. The disclaimer
  56. at the begining of each file is required by my employer (Harris Computer
  57. Systems Division) to ensure that Harris is not liable in the event
  58. of errors in the software.
  59.  
  60. The combine utility has been in use at HCSD for 5 years. It runs on
  61. Harris HCX and GCX architectures (CX/UX 4.1) and a SUN 3/160
  62. (SUNOS version 4.0), 
  63. --
  64. Cliff Van Dyke                   cliff@ssd.csd.harris.com
  65. Harris Computer Systems          ...!{uunet,novavax}!hcx1!cliff
  66. 2101 W. Cypress Creek Rd.
  67. Ft. Lauderdale, FL 33309-1892    Tel: (305) 973-5349
  68. @//E*O*F README//
  69. chmod u=rw,g=r,o=r README
  70.  
  71. echo x - combine.1
  72. sed 's/^@//' > "combine.1" <<'@//E*O*F combine.1//'
  73. '\"
  74. '\" The combine utility is a product of Harris, Inc. and is provided for
  75. '\" unrestricted use provided that this legend is included on all tape
  76. '\" media and as a part of the software program in whole or part.  Users
  77. '\" may copy, modify, license or distribute the combine utility without charge.
  78. '\" 
  79. '\" THE COMBINE UTILITY IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND
  80. '\" INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
  81. '\" PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE
  82. '\" PRACTICE.
  83. '\" 
  84. '\" The combine utility is provided with no support and without any obligation
  85. '\" on the part of Harris, Inc. to assist in its use, correction,
  86. '\" modification or enhancement.
  87. '\" 
  88. '\" HARRIS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  89. '\" INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THE COMBINE
  90. '\" UTILITY OR ANY PART THEREOF.
  91. '\" 
  92. '\" In no event will Harris, Inc. be liable for any lost revenue
  93. '\" or profits or other special, indirect and consequential damages, even if
  94. '\" Harris has been advised of the possibility of such damages.
  95. '\" 
  96. '\" Harris Computer Systems Division
  97. '\" 2101 W Cypress Creek Rd
  98. '\" Fort Lauderdale, Florida 33309
  99. '\"
  100. @.TH COMBINE 1 "" "CX/UX User's Reference Manual" 
  101. @.SH NAME
  102. combine, combine2 \- compare or combine 2 or 3 source files
  103. @.SH SYNOPSIS
  104. @.B combine
  105. [
  106. @.B \-options
  107. ] old_file new1_file [ new2_file ]
  108. @.br
  109. @.B combine2
  110. temp_file merged_file
  111. @.SH DESCRIPTION
  112. @.I Combine
  113. compares the differences between 2 or 3 source files and produces
  114. a result file.
  115. Where 'old_file' is the name of the original file, 'new1_file' is a file
  116. containing modifications to 'old_file', and 'new2_file' is a file containing
  117. a different set of modifications to 'old_file'.
  118. @.sp
  119. The option arguments are:
  120. @.TP 9
  121. @.B \-b
  122. Blank compress option --
  123. Causes
  124. @.I combine
  125. to treat all sequences of blanks and horizontal tabs
  126. as a single blank.
  127. @.TP
  128. @.B \-B
  129. Blank remove option --
  130. Causes
  131. @.I combine
  132. to ignore all blanks and horizontal tabs in a line
  133. when comparing lines.
  134. @.TP
  135. @.B \-c #,#
  136. Column specification option -- Specifies the column range to be compared.
  137. By default, all columns are compared.
  138. The number of the
  139. first column to compare immediately follows the -c option.
  140. The number of the last column to compare is separated from the first column
  141. to compare by a comma.
  142. Up to 32 different column ranges may be given.
  143.  
  144. For example,
  145.  
  146.       combine -c10,20 a b c
  147.  
  148. compares only columns 10 through 20.
  149. @.TP
  150. @.B \-d flag
  151. Debug options -- specifies how much debug information is to be output.
  152. The possibilities are:
  153. @.B \-d1,
  154. pass1 debug;
  155. @.B \-d2,
  156. pass2 debug;
  157. @.B \-d3,
  158. pass3 debug;
  159. @.B \-d4,
  160. pass4 debug;
  161. @.B \-d5,
  162. pass5 debug; and
  163. @.B \-da,
  164. all debug.
  165. @.TP
  166. @.B \-h
  167. h option -- produces a composite file on standard output suitable
  168. for input into
  169. @.IR combine2 (1).
  170. The file is an ASCII text file which may be manually modified by an text
  171. editor such as
  172. @.IR vi (1).
  173. The example below describes the use of this option in detail.
  174. @.TP
  175. @.B \-p #
  176. Postfix option -- The number of unchanged lines to output to the standard
  177. output file following any group of changed lines.
  178. The number of unchanged lines is specified by the argument following the -p
  179. option. The default is 5.
  180. This option is used only if the
  181. @.B \-h
  182. option is not specified.
  183. @.TP
  184. @.B \-P #
  185. Prefix option -- The number of unchanged lines to output to the standard
  186. output file prior to any group of changed lines.
  187. The number of unchanged lines is specified by the argument following the -P
  188. option. The default is 5.
  189. This option is used only if the
  190. @.B \-h
  191. option is not specified.
  192. @.TP
  193. @.B \-q
  194. Quiet option -- Specifies that no output is to be generated to the standard
  195. output file if no changes are detected.
  196. @.TP
  197. @.B \-s
  198. Statistics option -- Specifies that performance statistics are to be output
  199. to standard output when 
  200. @.B combine 
  201. is finished.
  202. @.TP
  203. @.B \-1 text
  204. New1 file description -- Symbolic description of the 'new1' file. This text
  205. is printed as the description of the new1 file on the listing output and
  206. h option output file.
  207. @.TP
  208. @.B \-2 text
  209. New2 file description -- Symbolic description of the 'new2' file. This text
  210. is printed as the description of the new1 file on the listing output and
  211. h option output file.
  212. @.SH EXAMPLE
  213. @.I Combine
  214. may be used to perform a simple two file comparison.
  215. by merely omitting the name of the third file.
  216. @.PP
  217. @.I Combine
  218. is best suited to do a three file comparison.
  219. Consider a file which is being modified along two development paths.
  220. The original copy of the file with no modifications is called the 'old' file.
  221. The copy modified along one development path is called the 'new1' file.
  222. The copy modified along the other development path is called the 'new2' file.
  223. The following is a guide for producing a 'merged' file which contains
  224. both set of modifications.
  225.  
  226. First,
  227. @.I combine
  228. is called with the following command line:
  229.  
  230.    combine -h old new1 new2 >temp_file
  231.  
  232. The 'temp_file' contains all of the lines from the 'old', 'new1' and 'new2'
  233. files combined with control lines. A control line identifies those
  234. portions of the 'temp_file' which represent modifications made by the 'new1'
  235. and 'new2' files.
  236.  
  237. Text which is inserted by the 'new1' or 'new2' file is surrounded by
  238. an ~~Insert line and an ~End line. The ~~Insert line also contains comments
  239. indicating which of the two files the inserted lines came from and whether
  240. the insertion was involved in a 'move' operation.
  241. In the example below, the line 'apple' was inserted between two already
  242. existing lines 'bob' and 'fred'.
  243.  
  244.     bob
  245.     ~~Insert 'file2'
  246.     apple
  247.     ~End of changes
  248.     fred
  249.  
  250. Text which is deleted by the 'new1' or 'new2' file is surrounded by
  251. an ~~Delete line and an ~End line. The ~~Delete line also contains comments
  252. indicating which of the two files deleted the specified lines an whether
  253. the deletion is a side effect of a 'move' operation.
  254. In the example below, the line 'apple' was deleted from between the
  255. lines 'bob' and 'fred'.
  256.  
  257.     bob
  258.     ~~Delete 'file1'
  259.     apple
  260.     ~End of changes
  261.     fred
  262.  
  263. The 'temp_file' may be edited with any text editor. Changes in the 'temp_file'
  264. can easily be found by finding lines with two tildes (~~) on them. Changes
  265. which are correct should be left alone. Changes which are wrong should be
  266. fixed. Deleted text can be allowed to remain in the file by merely deleting
  267. the ~~Delete line. Things to watch out for during this process include:
  268. Lines which are inserted by both the 'new1' and 'new2' files, and lines
  269. which are deleted by both the 'new1' and 'new2' files.
  270.  
  271. After all of the changes have been made in the tempfile,
  272. @.IR combine2(1)
  273. should be used to produce the merged file.
  274. @.IR Combine2(1)
  275. is called with the following command line:
  276.  
  277.       combine2 temp_file merged_file
  278.  
  279. @.IR Combine2(1)
  280. produces a merged file by removing the control lines and the deleted
  281. lines from the temp file. If the name of the temp file is omitted, standard
  282. input is used. If the name of the merged file is omitted, standard output
  283. is used.
  284. @.SH SEE ALSO
  285. cmp(1), combine2(1), comm(1), diff(1), diff3(1)
  286. @.SH DIAGNOSTICS
  287. Exit status is 0 for files identical, 1 for some differences, 2 for errors.
  288. @.SH AUTHOR
  289. Clifford P. Van Dyke
  290. @.SH BUGS
  291. Does not allow input file to be specified as \- to indicate stdin.
  292.  
  293. Does not allow comparison of binary files. Does not always complain if an
  294. input file is a binary file.
  295.  
  296. Does not check to see if two files have the same inode.
  297. @.Em
  298. @//E*O*F combine.1//
  299. chmod u=rw,g=r,o=r combine.1
  300.  
  301. echo x - design_spec
  302. sed 's/^@//' > "design_spec" <<'@//E*O*F design_spec//'
  303. '\"
  304. '\" The combine utility is a product of Harris, Inc. and is provided for
  305. '\" unrestricted use provided that this legend is included on all tape
  306. '\" media and as a part of the software program in whole or part.  Users
  307. '\" may copy, modify, license or distribute the combine utility without charge.
  308. '\" 
  309. '\" THE COMBINE UTILITY IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND
  310. '\" INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
  311. '\" PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE
  312. '\" PRACTICE.
  313. '\" 
  314. '\" The combine utility is provided with no support and without any obligation
  315. '\" on the part of Harris, Inc. to assist in its use, correction,
  316. '\" modification or enhancement.
  317. '\" 
  318. '\" HARRIS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  319. '\" INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THE COMBINE
  320. '\" UTILITY OR ANY PART THEREOF.
  321. '\" 
  322. '\" In no event will Harris, Inc. be liable for any lost revenue
  323. '\" or profits or other special, indirect and consequential damages, even if
  324. '\" Harris has been advised of the possibility of such damages.
  325. '\" 
  326. '\" Harris Computer Systems Division
  327. '\" 2101 W Cypress Creek Rd
  328. '\" Fort Lauderdale, Florida 33309
  329. '\"
  330. @.so /usr/lib/tmac/tmac.m
  331. @.de )k                      \" remove -- lines at top of page
  332. @..
  333. @.nr Cl 7                    \" keep level 1-7 headers in table of contents
  334. @.nr Hb 7                    \" all text after heading starts on new line
  335. @.nr Hs 7                    \" all headers followed by 1 line
  336. @.nr Li 10                   \" AL indent: 10 spaces
  337. @.nr Pi 10                   \" BL indent: 10 spaces
  338. @.nr Ps 2                    \" paragraph spacing: 2 lines
  339. @.ds HF 3 3 3 3 2 2 2        \" header fonts: bold, italic, normal
  340. @.ds HP +6 +4 +2 +2          \" print first level headings 2 ps larger
  341. @.ds T \t
  342. @.ll 6.5i
  343. @.de HX                \" macro to ensure 15 lines on page before heading
  344. @.nr ;3 (15-\\n(;0)v
  345. @..
  346. @.de HZ                      \" macro to output a blank line after heading
  347. @.sp 0.5v
  348. @..
  349. @.PH "''Combine Utility Design Spec''"
  350. @.PF "'' - Page \\\\nP -''"
  351. @.TL
  352. Combine Utility
  353. @.br
  354. Design Specification
  355. @.AF "Harris Computer Systems"
  356. @.AU "Cliff Van Dyke"
  357. @.MT 4
  358. @.ce
  359. January 1985
  360. \}
  361. This utility compares the differences in 3 source files and produces
  362. a result file.
  363. @.H 1 "Invocation Sequence"
  364. The combine utility accepts the following UNIX-like invocation sequence.
  365.  
  366.    combine [option-args] old_file new1_file [new2_file] [>list_output]
  367.  
  368. where 'old_file' is the name of the original file, 'new1_file' is a file
  369. containing modification to 'old_file', and 'new2_file' is a file containing
  370. a different set of modifications to 'old_file'. (Actually, see the
  371. functionality section for a description of other possible uses.)
  372.  
  373. where the option arguments are:
  374. @.VL 10
  375. @.LI -b
  376. Blank compress option --
  377. Causes COMBINE to treat all sequences of blanks and horizontal tabs
  378. as a single blank.
  379. @.LI -B
  380. Blank remove option --
  381. Causes COMBINE to ignore all blanks and horizontal tabs in a line
  382. when comparing lines.
  383. @.LI "-c #,#"
  384. Column specification option -- Specifies the column range to be compared.
  385. If column range is not specified, columns 1 through 135 are compared.
  386. The number of the
  387. first column to compare immediately follows the -c option.
  388. The number of the last column to compare is separated from the first column
  389. to compare by a comma.
  390. Up to 32 different column ranges may be given.
  391.  
  392. For example,
  393.  
  394.       combine -c10,20 a b c
  395.  
  396. compares only columns 10 through 20.
  397.  
  398. IMPORTANT NOTE: On VOS, the comma which separates the column values must
  399. be enclosed in quotes.
  400. @.LI "-d flag"
  401. Debug options -- specifies how much debug information is to be output.
  402. The possibilities are: -d1, pass1 debug; -d2, pass2 debug; -d3, pass3 debug;
  403. -d4, pass4 debug; -d5, pass5 debug; and -da, all debug.
  404. @.LI "-e area"
  405. MERGE editor option -- specifies the name of the disk area to write the
  406. MERGE script to. This script contains adequate information to allow MERGE
  407. to edit the 'old' file and insert the changes from
  408. the 'new1' and 'new2' files.
  409. The file name is specified by the argument following the -e option.
  410. This option is not yet implemented.
  411. @.LI "-h area"
  412. HED editor option -- specifies the name of the disk area to write the
  413. HED script to. This script contains adequate information to allow HED
  414. to highlight changes to the 'old' file which produce the 'new1' and 'new2'
  415. files.
  416. The file name is specified by the argument following the -h option.
  417. @.LI "-p #"
  418. Postfix option -- The number of unchanged lines to output to the standard
  419. output file following any group of changed lines.
  420. The number of unchanged lines is specified by the argument following the -p
  421. option. The default is 5.
  422. @.LI "-P #"
  423. Prefix option -- The number of unchanged lines to output to the standard
  424. output file prior to any group of changed lines.
  425. The number of unchanged lines is specified by the argument following the -p
  426. option. The default is 5.
  427. @.LI -q
  428. Quiet option -- Specifies that no output is to be generated to the standard
  429. output file if no changes are detected.
  430. @.LI "-1 text"
  431. New1 file description -- Symbolic description of the 'new1' file. This text
  432. is printed as the description of the new1 file on the listing output and
  433. HED output file.
  434. @.LI "-2 text"
  435. New2 file description -- Symbolic description of the 'new2' file. This text
  436. is printed as the description of the new1 file on the listing output and
  437. HED output file.
  438. @.LE
  439. @.H 1 Uses
  440. @.H 2 "Two file comparison"
  441. The combine utility may be used to perform a simple two file comparison
  442. by merely omitting the name of the third file.
  443. @.H 2 "Three file comparison"
  444. The combine utility is best suited to do a three file comparison.
  445. Consider a file which is being modified along two development paths.
  446. The original copy of the file with no modifications is called the 'old' file.
  447. The copy modified along one development path is called the 'new1' file.
  448. The copy modified along the other development path is called the 'new2' file.
  449. The following is a guide for producing a 'merged' file which contains
  450. both set of modifications.
  451.  
  452. First, combine is called with the following command line:
  453.  
  454.    combine -h temp_file old new1 new2 >listing
  455.  
  456. The output in the 'listing' file is a 'pretty' summary of the changes.
  457. The 'temp_file' contains all of the lines from the 'old', 'new1' and
  458. 'new2' files combined with control lines. A control line identifies those
  459. portions of the 'temp_file' which represent modifications made by the
  460. 'new1' and 'new2' files.
  461.  
  462. Text which is inserted by the 'new1' or 'new2' file is surrounded by an
  463. @~~Insert line and an ~End line. The ~~Insert line also contains comments
  464. indicating which of the two files the inserted lines came from and whether
  465. the insertion was involved in a 'move' operation.
  466. In the example below, the line 'apple' was inserted between two already
  467. existing lines 'bob' and 'fred'.
  468.  
  469.  
  470.     bob
  471.     ~~Insert 'file2'
  472.     apple
  473.     ~End of changes
  474.     fred
  475.  
  476.  
  477. Text which is deleted by the 'new1' or 'new2' file is surrounded by
  478. an ~~Delete line and an ~End line. The ~~Delete line also contains comments
  479. indicating which of the two files deleted the specified lines an whether
  480. the deletion is a side effect of a 'move' operation.
  481. In the example below, the line 'apple' was deleted from between the
  482. lines 'bob' and 'fred'.
  483.  
  484.  
  485.     bob
  486.     ~~Delete 'file1'
  487.     apple
  488.     ~End of changes
  489.     fred
  490.  
  491.  
  492. The 'temp_file' may be edited with any text editor. Changes in the 'temp_file'
  493. can easily be found by finding lines with two tildas (~~) on them. Changes
  494. which are correct should be left alone. Changes which are wrong should be
  495. fixed. Deleted text can be allowed to remain in the file by merely deleting
  496. to ~~Delete line. Things to watch out for during this process include:
  497. the ~~Delete line. Things to watch out for during this process include:
  498. Lines which are inserted by both the 'new1' and 'new2' files, and lines
  499. which are deleted by both the 'new1' and 'new2' files.
  500.  
  501. After all of the changes have been made in the tempfile, the 'combine2'
  502. utility should be used to produce the merged file. Combine2 is called
  503. with the following command line:
  504.  
  505.  
  506.       combine2 temp_file merged_file
  507.  
  508.  
  509. Combine2 produces a merged file by removing the control lines and the deleted
  510. lines from the temp file. If the name of the temp file is omitted, standard
  511. input is used. If the name of the merged file is omitted, standard output
  512. is used.
  513. @.H 1 Algorithm
  514. Combine uses the general algorithm as described in "A technique for Isolating
  515. differences between files"; Communications of the ACM; April 1978; Volume 21
  516. Number 4. This document presents a very, very brief overview of that algorithm
  517. and modifications made to that algorithm to overcome its weaknesses and
  518. to allow support for a 3 file comparison.
  519. @.H 2 "Term Definition"
  520. This section contains definitions of several terms
  521. used in the description of the algorithm.
  522.  
  523. The 'current file' is one of the files being compared.
  524. At any point in the algorithm, the 'current
  525. file' is the one which is being compared to the 'corresponding file'.
  526. The 'other file' is the file which is neither the current file
  527. nor the corresponding file.
  528. @.H 2 "Record Array Description"
  529. For each file which is being compared, a record array exists. There is one
  530. entry in the array for every record in the file. There is also a dummy entry
  531. at the beginning of the array and a dummy entry at the end of the array. These
  532. dummy entries allow easy detection of beginning of file and end of file.
  533.  
  534. Each entry in the array contains an 'rfa'. An 'rfa' is a
  535. record's file address. An rfa can be used to position the file to the particular
  536. record. On VOS, the rfa is merely the record's CRA (current record address).
  537. On UNIX, the rfa is byte displacement into the file.
  538.  
  539. Each entry in the array also contains two 'value' fields. Each value field
  540. describes the relationship between the current file and the other two files.
  541. The content of the value field will become obvious as we progress through
  542. the description of the algorithm. For now, suffice it to say that the field
  543. contains either a negative displacement into the symbol table or a positive
  544. displacement into the record array of the corresponding file.
  545. @.H 2 "Symbol Table Description"
  546. The symbol table consists of four arrays each indexed by the same value.
  547. The index into the symbol table is a unique
  548. hash code computed from the text of the record from any of the files. Identical
  549. records always hash to the same location. Different records always hash to
  550. different locations.
  551.  
  552. The first symbol table array is the cache pointer array.
  553. The value in this array is 0 if the symbol
  554. table entry is not used. The value is a pointer to the cache entry if
  555. the symbol table entry is used and the record is still in cache. The value
  556. is -1 if the symbol table entry is used but the record is not in cache.
  557.  
  558. One symbol table array exists for each file being compared. The value in
  559. this array is 0 if the hashed record does not occur in the current file at all.
  560. The value is a positive record number if the hash record occurs in the
  561. current file precisely once. The value is a negative record number if the
  562. hash code occurs in the current file more than once.
  563. @.H 2 Cache
  564. The cache maintains a copy of the text of the 300 most recently read records.
  565. Combine ensures that two records that hash to the same value are indeed
  566. the same record by comparing actual record contents. The cache allows the
  567. comparison to be done efficiently. See the description of pass1 for detailed
  568. information.
  569. @.H 2 Pass1
  570. Pass1 reads all of the records from all of the files and initializes the
  571. symbol table and record arrays. On completion of this pass,
  572. the symbol table is initialized as described above and the record array
  573. for each file contains a negative hash code for each record in the file.
  574.  
  575. Pass1 reads a record from a file into a cache entry.
  576. Pass1 then computes the hash code for the record.
  577. If the hash code has never been used before, pass1 links the cache entry from
  578. the symbol table, marks the symbol table of the current file to indicate
  579. that this line exists precisely once in the file, and marks the record array
  580. of the current file to contain the negative hash code.
  581.  
  582. If the hash code has been used before, the value of the current record is
  583. compared with the value of the other record which hashed to the same value.
  584. The other record is either already in cache or is read into cache at this
  585. time.
  586.  
  587. If the current record and the other record are the same, pass1 marks the
  588. symbol table of the current file to indicate that this line exists in the
  589. file and marks the record array of the current file to contain the negative
  590. hash code. This condition can occur under two circumstances. First, a
  591. record from one file and the same record from the corresponding file will
  592. hash to the same location. Second, a record from one file and the same
  593. record at a different location in the same file will hash to the same location.
  594. The symbol table entry is marked to indicate whether a record occurs precisely
  595. once in a particular file or whether is occurs multiple times in a particular
  596. file.
  597.  
  598. If the current record and the other record are different, pass1 computes a
  599. different hash code for the current record and the above
  600. algorithm is repeated.
  601.  
  602. Pass1 alternately reads one record from each file. Thus, if a record is read
  603. into cache on the first file, the record will probably still be in cache
  604. when it is read on the second file. Cache is only used as described here in
  605. pass1. Nothing in the cache is passed between passes.
  606. @.H 2 Pass2
  607. Pass2 determines anchor points in the files. Pass2 identifies lines
  608. which occur precisely once in at least two of the files and no more than
  609. once in the third file. On completion of this pass, the record array
  610. for each file
  611. contains either a negative hash code for those records which don't meet
  612. the above criteria or contains a positive index into the record array
  613. of the corresponding file for those records which do meet the criteria.
  614. The symbol table is no longer used following this pass.
  615. @.H 2 Pass3
  616. Pass3 expands the anchor points to non-unique records. A non-unique record
  617. is a record which occurs more than once in at least one file. On completion
  618. of this pass, record array for each file will contain more positive indexes
  619. into the record array of another file and less negative hash codes.
  620. In general, following this pass, records which have negative hash codes
  621. are records which exist in the current file and have absolutely no corresponding
  622. records in the corresponding file. (I'll be more specific on this when I
  623. discuss pass4.)
  624.  
  625. Each pair of two files is scanned first in the forward direction and then
  626. in the backward direction. If, in the pair of files, there are lines which
  627. are adjacent to an anchor point and which are identical to each other, these
  628. lines are considered to be anchor points themselves. Lines are compared by
  629. comparing their negative hash codes.
  630. @.H 2 Pass4
  631. Pass4 expands the anchor points into non-unique record clusters.
  632. Pass4 tries to fix up problems which arise due to groups of non-unique
  633. records which are surrounded by insertions. When pass3 completed these
  634. records were treated as a part of the insertion. If, indeed, a large
  635. portion of the insertion actually matches a large portion of an insertion
  636. in another file, but if the match went undetected because the records
  637. were non-unique, then pass4 finds these non-unique lines and matches them.
  638.  
  639. Pass4 finds a pair of anchor records which have inserted lines between
  640. them (See diagram below). All inserted lines are compared to one another
  641. trying to find a group of non-unique lines which match. Such lines are
  642. considered equal and are flagged as anchor points.
  643.  
  644.           match1                       match1
  645.           insert
  646.           non-unique1                  non-unique1
  647.           insert
  648.           match2                       match2
  649.  
  650. The current implementation of the algorithm runs in M x N time where M is
  651. the number of inserted lines at the current position in the first file and
  652. N is the number of inserted lines at the current position in the second file.
  653. @.H 2 Pass5
  654. Pass5 outputs the result of the comparison. The record arrays for the
  655. three files are traversed. An index is maintained into each of the record
  656. arrays. As each index is incremented the corresponding record is output.
  657. Pass5 merely determines which file the next record is to come from.
  658.  
  659. The hardest problem for pass5 to resolve is one of record movement. That is,
  660. if a group of records from one file is moved to a different position in the
  661. second file. In this situation, the 'shortest' group of records is considered
  662. to have moved. This group of records is output first by pass5.
  663.  
  664. Pass5 uses the record cache to maintain a list of the last several records
  665. output. This cache is used to enable the 'prefix' lines capability of
  666. the comparison listing.
  667. @//E*O*F design_spec//
  668. chmod u=rw,g=rw,o=rw design_spec
  669.  
  670. echo x - combine.h
  671. sed 's/^@//' > "combine.h" <<'@//E*O*F combine.h//'
  672. /*
  673.  * The combine utility is a product of Harris, Inc. and is provided for
  674.  * unrestricted use provided that this legend is included on all tape
  675.  * media and as a part of the software program in whole or part.  Users
  676.  * may copy, modify, license or distribute the combine utility without charge.
  677.  * 
  678.  * THE COMBINE UTILITY IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND
  679.  * INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
  680.  * PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE
  681.  * PRACTICE.
  682.  * 
  683.  * The combine utility is provided with no support and without any obligation
  684.  * on the part of Harris, Inc. to assist in its use, correction,
  685.  * modification or enhancement.
  686.  * 
  687.  * HARRIS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  688.  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THE COMBINE
  689.  * UTILITY OR ANY PART THEREOF.
  690.  * 
  691.  * In no event will Harris, Inc. be liable for any lost revenue
  692.  * or profits or other special, indirect and consequential damages, even if
  693.  * Harris has been advised of the possibility of such damages.
  694.  * 
  695.  * Harris Computer Systems Division
  696.  * 2101 W Cypress Creek Rd
  697.  * Fort Lauderdale, Florida 33309
  698.  */
  699. #ifdef ALLOC
  700. #   define EXTERN
  701. #   define INIT( _x ) = _x
  702. #else
  703. #   define EXTERN extern
  704. #   define INIT( _x )
  705. #endif
  706.  
  707. /* 
  708.  * Some OS dependent stuff
  709.  */
  710. #define rfa_type long
  711.  
  712. #define SZ$_FILE_NAME 256
  713. #ifdef VOS    /* 24-bit word */
  714. #define HI7       077400000    /* Hi 7 bits of a word */
  715. #else        /* 32-bit word */
  716. #define HI7       0xFE000000    /* Hi 7 bits of a word */
  717. #endif
  718.  
  719. /*
  720.  * Cache Entry:
  721.  *
  722.  * This structure describes a single entry in the cache of lines.
  723.  * The cache is organized as a linked list of cache entries.
  724.  * The entries at the front of the list are the most recently accessed.
  725.  * The variables 'cache_head_ptr' and 'cache_tail_ptr' point to the
  726.  * head and the tail of the cache.
  727.  */
  728.  
  729. struct cache_entry_struct;
  730. typedef struct cache_entry_struct       cache_entry_type;
  731.  
  732. struct cache_entry_struct {
  733.  
  734.     cache_entry_type * cache_next_ptr;/* Link to the next cache entry */
  735.  
  736.     cache_entry_type * cache_prev_ptr;/* Link to the prev cache entry */
  737.  
  738.     int     hash_code;    /* The hash code for the line. A a value of
  739.                    HASH_FREE_ENTRY indicates this is a free
  740.                    cache entry. */
  741.  
  742.     int     record_length;    /* Length of the record */
  743.  
  744.     char    *recordp;    /* Actual record contents. */
  745.  
  746.     int    record_alen;    /* Allocated length of recordp buffer */
  747.  
  748. };
  749.  
  750. #define CACHE_ENTRIES 500    /* Total number of cache entries */
  751. EXTERN cache_entry_type * cache_head_ptr;/* Head of the cache linked list. */
  752. EXTERN cache_entry_type * cache_tail_ptr;/* Head of the cache linked list. */
  753.  
  754.  
  755. #define LINE_LENGTH 135        /* Default line length */
  756.  
  757. /* Maximum number of characters in a record */
  758. /*
  759.  * record_type:
  760.  *
  761.  * This structure describes a single record in a file.
  762.  * The 'file_type' structure points to an array of these entries.
  763.  */
  764.  
  765. struct record_struct;
  766. typedef struct record_struct    record_type;
  767.  
  768. struct record_struct {
  769.  
  770.     rfa_type rfa;        /* The record's file address. This is an
  771.                    operating system dependent value which is a
  772.                    token which can be used to seek to the
  773.                    specified record. */
  774.  
  775. /*
  776.  * The 'value' field describes the relationship between this record and
  777.  * another record in another file. Valid values are:
  778.  *
  779.  * Negative:        hash code for the record (See 'is_hash_code' macro).
  780.  *                  A hash code is an index into the symbol table.
  781.  * 0 or Positive:   index into record array of other file.
  782.  *
  783.  * The defines below are used to describes whether the 'value[0]' or
  784.  * 'value[1]' field is used to describe a relationship between files.
  785.  */
  786.  
  787. #define MAX_VALUE_SUB 2
  788.  
  789.     int     value[MAX_VALUE_SUB];
  790.                 /* Describes the relationship between this
  791.                    record and another record in another file.
  792.                 */
  793.  
  794.  
  795. #define OLD_TO_NEW1         0    /* Old file: index into new1  */
  796. #define OLD_TO_NEW2         1    /* Old file: index into new2  */
  797. #define NEW1_TO_OLD         0    /* new1 file: index into old  */
  798. #define NEW1_TO_NEW2        1    /* new1 file: index into new2 */
  799. #define NEW2_TO_OLD         0    /* new2 file: index into old  */
  800. #define NEW2_TO_NEW1        1    /* new2 file: index into new1 */
  801.  
  802. };
  803.  
  804. /*
  805.  * Record index values:
  806.  *
  807.  * Record indexes include a special record at the beginning of the file
  808.  * and a special record at the end of the file. These definitions describe
  809.  * that phenomena.
  810.  */
  811.  
  812. #define BEGIN_INDEX 0        /* Index of the dummy begin record */
  813. #define DUMMY_RECORD_COUNT 2    /* Number of dummy records */
  814.  
  815. /*
  816.  * File Description:
  817.  *
  818.  * This structure describes a single input file.
  819.  * A structure of this type occurs for the 'old' file, 'new1' file,
  820.  * and 'new2' file.
  821.  */
  822.  
  823. struct file_struct;
  824. typedef struct file_struct      file_type;
  825.  
  826. struct file_struct {
  827.  
  828.     char   *name_ptr;    /* Zero terminated name of file */
  829.  
  830.     char   *text_ptr;    /* Zero terminated text describing file */
  831.  
  832.     char   *lw_ptr;        /* Zero terminated last written date */
  833.  
  834.     FILE *  seq_fd;        /* fd to use for sequential access */
  835.  
  836.     FILE *  rnd_fd;        /* fd to use for random access */
  837.  
  838.     int     record_array_size;/* number of lines in the file (including
  839.                      DUMMY_RECORD_COUNT). */
  840.  
  841.     int    record_array_alloc;/* number of allocated entries in the
  842.                    record array. */
  843.  
  844. #define RA_ORIG    5000        /* Original # of records in record array */
  845. #define RA_INCR 5000        /* Number of records to add on each increment */
  846.  
  847.     record_type * record;    /* Allocated array of record descriptions.
  848.                    This field contains 0 if the file does not
  849.                    exists. (i.e., this is the third file in a
  850.                    two file comparison ) */
  851.  
  852. /*
  853.  * The entry below is actually the portion of the symbol table which
  854.  * needs an entry for each file. The array is indexed by 'hash_code'.
  855.  *
  856.  * Each index below is an index into the array for the specified file.
  857.  * Valid values are:
  858.  *
  859.  * 0:                      This line is not in this file.
  860.  * negative:               This line is not unique in the file.
  861.  *                         Value is negative index to one of the records.
  862.  * not negative:           This line occurs precisely once in the file.
  863.  *                         Value is index to the record.
  864.  */
  865.  
  866.     int    *sym_tab_index;    /* Index into 'record'. */
  867.                 /* There are 'sym_tab_size' elements in this array. */
  868. };
  869.  
  870. #define OLD_FILE   0        /* Array index of 'old' file */
  871. #define NEW1_FILE  1        /* Array index of 'new1' file */
  872. #define NEW2_FILE  2        /* Array index of 'new2' file */
  873. #define MAX_FILE_COUNT 3    /* Maximum number of files */
  874.  
  875. EXTERN int      file_count;    /* actual number of files */
  876.  
  877. EXTERN file_type files[MAX_FILE_COUNT];/* Description of the each file. */
  878.  
  879. /*
  880.  * For each record, six different relationships exist. That is,
  881.  * for each of the three files there is a relationship to each of the
  882.  * other two files.
  883.  * The tables below describe the six relationships.
  884.  */
  885.  
  886. #define MATCH_COUNT ( 2*MAX_FILE_COUNT )
  887.  
  888. EXTERN int      curr_file[MATCH_COUNT]
  889. #ifdef ALLOC
  890. = {
  891.     OLD_FILE, OLD_FILE, NEW1_FILE, NEW1_FILE, NEW2_FILE, NEW2_FILE
  892. }
  893. #endif
  894.            ;
  895.  
  896. /*Array of subsrcipts into the 'files' array of files which have
  897. relationships */
  898.  
  899. EXTERN int      corres_file[MATCH_COUNT]
  900. #ifdef ALLOC
  901. = {
  902.     NEW1_FILE, NEW2_FILE, OLD_FILE, NEW2_FILE, OLD_FILE, NEW1_FILE
  903. }
  904. #endif
  905.            ;
  906. /* Array of subscripts into the 'files' array of the file which is related to */
  907.  
  908.  
  909. EXTERN int      other_file[MATCH_COUNT]
  910. #ifdef ALLOC
  911. = {
  912.     NEW2_FILE, NEW1_FILE, NEW2_FILE, OLD_FILE, NEW1_FILE, OLD_FILE
  913. }
  914. #endif
  915.            ;
  916.  /* Array of subscripts into the 'files' array of the file which is not
  917.     involved in the current relationship */
  918.  
  919. EXTERN int      value_sub[MATCH_COUNT]
  920. #ifdef ALLOC
  921. = {
  922.     OLD_TO_NEW1, OLD_TO_NEW2, NEW1_TO_OLD, NEW1_TO_NEW2,
  923.     NEW2_TO_OLD, NEW2_TO_NEW1
  924. }
  925. #endif
  926.            ;
  927.  /* Array of subscripts to the 'value' array. This subscript identifies which
  928.     of the two relationships are being tested. */
  929.  
  930. EXTERN int      rev_value_sub[MATCH_COUNT]
  931. #ifdef ALLOC
  932. = {
  933.     NEW1_TO_OLD, NEW2_TO_OLD, OLD_TO_NEW1, NEW2_TO_NEW1,
  934.     OLD_TO_NEW2, NEW1_TO_NEW2
  935. }
  936. #endif
  937.            ;
  938.  /* Array of subscripts to the 'value' array. This subscript identifies the
  939.     relationship between the 'corres' file and the 'curr' file */
  940.  
  941. EXTERN int      other_value_sub[MATCH_COUNT]
  942. #ifdef ALLOC
  943. = {
  944.     NEW2_TO_OLD, NEW1_TO_OLD, NEW2_TO_NEW1, OLD_TO_NEW1,
  945.     NEW1_TO_NEW2, OLD_TO_NEW2
  946. }
  947. #endif
  948.            ;
  949.  /* Array of subscripts to the 'value' array. This subscript identifies the
  950.     relationship between the 'other' file and the 'curr' file */
  951.  
  952.  
  953. #define UNIQUE_MATCH_COUNT (MATCH_COUNT / 2)
  954.  
  955. EXTERN int      unique_match[UNIQUE_MATCH_COUNT]
  956. #ifdef ALLOC
  957. = {
  958.     0, 1, 3
  959. }
  960. #endif
  961.            ;
  962.  /* Array of subscripts into the relation arrays defined above. These are the
  963.     subscripts of the relations pairing each pair of files precisely once. */
  964. /*
  965.  * is_hash_code:
  966.  *
  967.  * This macro determines if the value in the record array is a hash code
  968.  * or an index into another file array. This macro relies on the fact
  969.  * that all hash codes are nagetive.
  970.  *
  971.  * Return value:
  972.  *      TRUE:  The value represents a hash code
  973.  *      FALSE: The value represents an index into a file array.
  974.  *
  975.  * Parameter:
  976.  *      value: The value from the file array.
  977.  */
  978.  
  979. #define is_hash_code( _value )  ((_value) < 0)
  980. /*
  981.  * Options:
  982.  */
  983.  
  984. EXTERN bool blank_compress INIT (FALSE);
  985.                 /* TRUE if blank compression is desired */
  986.  
  987. EXTERN bool blank_remove INIT (FALSE);/* TRUE if blank removal is desired */
  988.  
  989. EXTERN bool compress_records INIT (FALSE);
  990.                 /* TRUE if any record compression needs to
  991.                    occur */
  992.  
  993. EXTERN int      prefix_lines INIT (5);/* Number of prefix lines */
  994.  
  995. EXTERN int      postfix_lines INIT (5);/* Number of postfix lines */
  996.  
  997. EXTERN bool quiet_option INIT (FALSE);
  998.                 /* TRUE if COMBINE is to be quiet if there are
  999.                    no differences */
  1000.  
  1001. EXTERN bool pa_debug INIT (FALSE);/* TRUE for generic debugging */
  1002. EXTERN bool p1_debug INIT (FALSE);/* TRUE for debug of pass 1 */
  1003. EXTERN bool p2_debug INIT (FALSE);/* TRUE for debug of pass 2 */
  1004. EXTERN bool p3_debug INIT (FALSE);/* TRUE for debug of pass 3 */
  1005. EXTERN bool p4_debug INIT (FALSE);/* TRUE for debug of pass 4 */
  1006. EXTERN bool p5_debug INIT (FALSE);/* TRUE for debug of pass 5 */
  1007.  
  1008. EXTERN bool statistics_flag INIT (FALSE);/* TRUE to output statistics */
  1009.  
  1010. EXTERN bool hed_flag INIT (FALSE);/* TRUE to output hed file */
  1011.  
  1012. EXTERN char     exec_time[LINE_LENGTH];/* Begin execution time */
  1013.  
  1014. /*
  1015.  * Column specifications:
  1016.  */
  1017.  
  1018. #define MAX_COLUMNS 32        /* maximum number of column ranges */
  1019.  
  1020. EXTERN int      column_count INIT (0);/* Actual number of column ranges */
  1021.  
  1022. EXTERN int      first_column[MAX_COLUMNS];/* first column to compare */
  1023.                 /* Column numbers are 0 relative */
  1024.  
  1025. EXTERN int      last_column[MAX_COLUMNS];/* last column to compare */
  1026.                  /* Column numbers are 0 relative */
  1027.  
  1028. /*
  1029.  * other_sub:
  1030.  *
  1031.  * This macro is given the subscript to one of the elements in the
  1032.  * 'value' array and returns the subscript to the other element.
  1033.  * This macro is heavily dependent on the fact that there are only
  1034.  * two elements in the value array.
  1035.  *
  1036.  * Return value:
  1037.  *      other subscript
  1038.  *
  1039.  * Parameter:
  1040.  *      value_sub: Subsrcipt into the value array.
  1041.  */
  1042.  
  1043. #define other_sub( _sub )  ( 1 - (_sub) )
  1044.  
  1045. /*
  1046.  * Primes: list of prime numbers.
  1047.  *
  1048.  * This array defines a set of prime numbers. For all multiples of 1024,
  1049.  * this table contains the prime number which is less than but closest
  1050.  * to that number.
  1051.  *
  1052.  * The list is terminated by a -1.
  1053.  */
  1054.  
  1055. EXTERN int      primes[]
  1056. #ifdef ALLOC
  1057. = {
  1058.     1021, 2039, 3067, 4093, 5119, 6143, 7159, 8191, 9209,
  1059.     10223, 11261, 12281, 13309, 14327, 15359, 16381, 17401, 18427,
  1060.     19447, 20479, 21503, 22511, 23549, 24571, 25589, 26597, 27647,
  1061.     28669, 29683, 30713, 31741, 32749, 33791, 34807, 35839, 36857,
  1062.     37879, 38903, 39929, 40949, 41983, 43003, 44029, 45053, 46073,
  1063.     47093, 48121, 49139, 50159, 51199, 52223, 53239, 54269, 55291,
  1064.     56311, 57331, 58367, 59387, 60413, 61417, 62459, 63487, 64499,
  1065.     65521, 66553, 67579, 68597, 69623, 70639, 71671, 72701, 73727,
  1066.     74747, 75773, 76781, 77813, 78839, 79867, 80863, 81919, 82939,
  1067.     83939, 84991, 86011, 87037, 88037, 89087, 90107, 91129, 92153,
  1068.     93179, 94207, 95231, 96233, 97259, 98299, 99317, 100343, 101363,
  1069.     102397, 103423, 104417, 105467, 106487, 107509, 108541, 109567,
  1070.     110587, 111611, 112621, 113657, 114679, 115693, 116731, 117757,
  1071.     118757, 119797, 120829, 121853, 122869, 123887, 124919, 125941,
  1072.     126967, 127997, 129023, 130043, 131071, 132071, 133117, 134129,
  1073.     135151, 136189, 137209, 138239, 139241, 140281, 141311, 142327,
  1074.     143357, 144383, 145399, 146423, 147451, 148471, 149503, 150523,
  1075.     151549, 152567, 153589, 154621, 155627, 156671, 157679, 158699,
  1076.     159739, 160757, 161783, 162791, 163819, 164839, 165887, 166909,
  1077.     167917, 168943, 169957, 171007, 172031, 173053, 174079, 175103,
  1078.     176123, 177131, 178169, 179173, 180221, 181243, 182261, 183289,
  1079.     184309, 185327, 186343, 187387, 188407, 189439, 190409, 191473,
  1080.     192499, 193513, 194543, 195581, 196597, 197621, 198647, 199679,
  1081.     200699, 201709, 202751, 203773, 204797, 205823, 206827, 207869,
  1082.     208891, 209917, 210943, 211949, 212987, 214009, 214993, 216061,
  1083.     217081, 218111, 219133, 220151, 221173, 222199, 223229, 224251,
  1084.     224737,
  1085.     -1
  1086. }
  1087. #endif
  1088.            ;
  1089.  
  1090. /*
  1091.  * relate_type:
  1092.  *
  1093.  * This structure describes the relationsip between between a particular
  1094.  * record of a particular file and corresponding records in the other
  1095.  * files.
  1096.  *
  1097.  * This structure is built by 'pass5_analyze_relationship'. This structure
  1098.  * is used by all of the other pass5 routines to determine whether the
  1099.  * current record is the next one to be output.
  1100.  */
  1101.  
  1102. struct relate_struct;
  1103. typedef struct relate_struct    relate_type;
  1104.  
  1105. struct relate_struct {
  1106.  
  1107.     int     index[MAX_FILE_COUNT];
  1108.                 /* Index that this record appears at in the
  1109.                    file. Value will be a hash code if this
  1110.                    record is not in the corresponding file */
  1111.  
  1112.     bool current[MAX_FILE_COUNT];
  1113.                 /* TRUE if the record at the current position
  1114.                    in the corresponding file */
  1115.  
  1116.     int     relation;    /* A summary of the relationship of this record
  1117.                    to the current record in each file */
  1118.     /* The zeroeth element is represented in the least significant bit,
  1119.        etc. */
  1120.  
  1121. #define INSERT_NONE           0
  1122. #define INSERT_OLD            1
  1123. #define INSERT_NEW1           2
  1124. #define INSERT_OLD_NEW1       (INSERT_OLD + INSERT_NEW1)
  1125. #define INSERT_NEW2           4
  1126. #define INSERT_OLD_NEW2       (INSERT_OLD + INSERT_NEW2)
  1127. #define INSERT_NEW1_NEW2      (INSERT_NEW1 + INSERT_NEW2)
  1128. #define INSERT_OLD_NEW1_NEW2  (INSERT_OLD + INSERT_NEW1 + INSERT_NEW2)
  1129. #define INSERT_EOT            -1
  1130.  
  1131.     bool moved;        /* TRUE if this record is involved in a record
  1132.                    movement. */
  1133.  
  1134.     bool in_all;        /* TRUE if the record is at the current
  1135.                    position in all of the files. */
  1136.  
  1137. };
  1138.  
  1139. /*
  1140.  * Statistics:
  1141.  */
  1142.  
  1143. EXTERN int      cache_miss;    /* total number of cache misses. */
  1144.  
  1145. EXTERN int      hash_collisions;/* total number of hash collsions */
  1146.  
  1147. EXTERN int      old_new1_change_count;
  1148.                 /* Number of differences between old and new1
  1149.                    files */
  1150.  
  1151. EXTERN int      old_new2_change_count;
  1152.                 /* Number of differences between old and new2
  1153.                    files */
  1154.  
  1155. EXTERN int      new1_new2_change_count;
  1156.                 /* Number of differences between new1 and new2
  1157.                    files */
  1158.  
  1159. /*
  1160.  * Symbol Table:
  1161.  *
  1162.  * This structure describes a the symbol table.
  1163.  * Each entry in the symbol table represents a record in one of the files.
  1164.  * The contents of each record is hashed.
  1165.  * The hash value is used as an index into the arrays.
  1166.  * If the hash value is not unique, a re-hash is performed until a
  1167.  * unique hash value is obtained.
  1168.  *
  1169.  * The symbol table is organized as four arrays of entries.
  1170.  * There is one array for each file and one array of cache entry pointers
  1171.  * described below.
  1172.  */
  1173.  
  1174. /*
  1175.  * The index into the symbol table is a hash code. Hash codes are positive.
  1176.  * Significant hash codes include:
  1177.  *
  1178.  * 0: Not valid
  1179.  * 1: begin record
  1180.  * 2: end record
  1181.  * 3: eof (some archaic operating systems allow multiple eof's in a file.)
  1182.  */
  1183.  
  1184. #define HASH_FREE_ENTRY 0    /* A hash code of this value indicates a free
  1185.                    entry. This value is used in a cache entry
  1186.                    to indicate an unused cache entry */
  1187.  
  1188. /*
  1189.  * The cache ptr below is a pointer to the cache entry for the line.
  1190.  * Valid values are:
  1191.  *
  1192.  * CACHE_FREE_ENTRY:       This symbol table entry is unused.
  1193.  * CACHE_NOT_IN_CACHE:     This line is no longer in the cache.
  1194.  * positive:               Pointer to cache entry.
  1195.  */
  1196.  
  1197. EXTERN cache_entry_type * *sym_tab_cache_ptr;
  1198.                 /* Pointer to table of pointers to cache
  1199.                    entries */
  1200.  
  1201. #define CACHE_FREE_ENTRY 0    /* Symbol table entry is unused */
  1202.  /* The code depends on the fact that the allocator zeros this entry upon
  1203.     allocation */
  1204.  
  1205. #define CACHE_NOT_IN_CACHE -1    /* This line no longer in cache */
  1206.  
  1207. EXTERN int      sym_tab_size;    /* Number of entries in the symbol table. */
  1208. /*
  1209.  * Procedure forwards:
  1210.  */
  1211.  
  1212. void dump_arrays() ;
  1213. void dump_statistics() ;
  1214. void dump_sym_tab() ;
  1215.  
  1216. void error() ;
  1217. char * mem_alloc() ;
  1218. void init() ;
  1219. void link_records() ;
  1220.  
  1221. void pass1() ;
  1222. int  pass1_read_record() ;
  1223. void pass1_record_compress() ;
  1224.  
  1225. void pass2() ;
  1226.  
  1227. void pass3() ;
  1228. void pass3_scan() ;
  1229.  
  1230. void pass4() ;
  1231. void pass4_scan() ;
  1232.  
  1233. void pass5() ;
  1234. void pass5_analyze_relationship() ;
  1235. int  pass5_move() ;
  1236. void pass5_dump_record() ;
  1237. void pass5_write_hed() ;
  1238. void pass5_write_listing() ;
  1239. void pass5_write_listing_line() ;
  1240. void pass5_write_listing_head() ;
  1241. @//E*O*F combine.h//
  1242. chmod u=rw,g=rw,o=rw combine.h
  1243.  
  1244. echo x - Makefile
  1245. sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
  1246. # The combine utility is a product of Harris, Inc. and is provided for
  1247. # unrestricted use provided that this legend is included on all tape
  1248. # media and as a part of the software program in whole or part.  Users
  1249. # may copy, modify, license or distribute the combine utility without charge.
  1250. # THE COMBINE UTILITY IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND
  1251. # INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A
  1252. # PARTICULAR PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE
  1253. # PRACTICE.
  1254. # The combine utility is provided with no support and without any obligation
  1255. # on the part of Harris, Inc. to assist in its use, correction,
  1256. # modification or enhancement.
  1257. # HARRIS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  1258. # INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THE COMBINE
  1259. # UTILITY OR ANY PART THEREOF.
  1260. # In no event will Harris, Inc. be liable for any lost revenue
  1261. # or profits or other special, indirect and consequential damages, even if
  1262. # Harris has been advised of the possibility of such damages.
  1263. # Harris Computer Systems Division
  1264. # 2101 W Cypress Creek Rd
  1265. # Fort Lauderdale, Florida 33309
  1266. #
  1267. #
  1268. # Makefile
  1269. #
  1270.  
  1271. OBJ = pass1.o pass2.o pass3.o pass4.o pass5.o main.o unix.o data.o
  1272. SRC = pass1.c pass2.c pass3.c pass4.c pass5.c main.c unix.c data.c
  1273. OBJ2 = combine2.o
  1274. SRC2 = combine2.c
  1275. LFLAGS = $(LFL)
  1276. CFLAGS=${CFL} -O
  1277.  
  1278. all: combine combine2
  1279.  
  1280. combine: ${OBJ}
  1281.     ${CC} ${CFLAGS} ${OBJ} -o combine
  1282.  
  1283. combine2: ${OBJ2} unix.o
  1284.     ${CC} ${CFLAGS} ${OBJ2} unix.o -o combine2
  1285.  
  1286. ${OBJ} ${OBJ2} :
  1287.     ${CC} -c ${CFLAGS} $*.c
  1288.  
  1289. install: all
  1290.     install -r -f $(ROOT)/usr/bin combine
  1291.     install -r -f $(ROOT)/usr/bin combine2
  1292.  
  1293.  
  1294. clean:
  1295.     rm -f ${OBJ} ${OBJ2} core a.out errs
  1296.  
  1297. clobber: clean
  1298.     rm -f combine combine2
  1299.  
  1300. depend: combine.mk
  1301.     for i in ${SRC} ${SRC2}; do \
  1302.         (echo $$i: $$i >>makedep; \
  1303.         /bin/grep '^#[     ]*include' /dev/null $$i | sed \
  1304.             -e 's,<\(.*\)>,"$${ROOT}/usr/include/\1",' \
  1305.             -e 's/:[^"]*"\([^"]*\)".*/: \1/' >>makedep); done
  1306.     sed <makedep -e 's/\.c/\.o/' >makedep2
  1307.     echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
  1308.     echo '$$r makedep2' >>eddep
  1309.     echo 'w' >>eddep
  1310.     cp combine.mk combine.mk.bak
  1311.     ed - combine.mk < eddep
  1312.     rm eddep makedep makedep2
  1313.     echo '# DEPENDENCIES MUST END AT END OF FILE' >> combine.mk
  1314.     echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> combine.mk
  1315.     echo '# see make depend above' >> combine.mk
  1316.  
  1317.  
  1318. # DO NOT DELETE THIS LINE -- make depend uses it
  1319. # DEPENDENCIES MUST END AT END OF FILE
  1320. pass1.o: pass1.c
  1321. pass1.o: ${ROOT}/usr/include/stdio.h
  1322. pass1.o: ${ROOT}/usr/include/ctype.h
  1323. pass1.o: util.h
  1324. pass1.o: os_dep.h
  1325. pass1.o: combine.h
  1326. pass2.o: pass2.c
  1327. pass2.o: ${ROOT}/usr/include/stdio.h
  1328. pass2.o: ${ROOT}/usr/include/ctype.h
  1329. pass2.o: util.h
  1330. pass2.o: os_dep.h
  1331. pass2.o: combine.h
  1332. pass3.o: pass3.c
  1333. pass3.o: ${ROOT}/usr/include/stdio.h
  1334. pass3.o: ${ROOT}/usr/include/ctype.h
  1335. pass3.o: util.h
  1336. pass3.o: os_dep.h
  1337. pass3.o: combine.h
  1338. pass4.o: pass4.c
  1339. pass4.o: ${ROOT}/usr/include/stdio.h
  1340. pass4.o: ${ROOT}/usr/include/ctype.h
  1341. pass4.o: util.h
  1342. pass4.o: os_dep.h
  1343. pass4.o: combine.h
  1344. pass5.o: pass5.c
  1345. pass5.o: ${ROOT}/usr/include/stdio.h
  1346. pass5.o: ${ROOT}/usr/include/ctype.h
  1347. pass5.o: util.h
  1348. pass5.o: os_dep.h
  1349. pass5.o: combine.h
  1350. main.o: main.c
  1351. main.o: ${ROOT}/usr/include/ctype.h
  1352. main.o: ${ROOT}/usr/include/stdio.h
  1353. main.o: ${ROOT}/usr/include/sys/types.h
  1354. main.o: ${ROOT}/usr/include/sys/stat.h
  1355. main.o: util.h
  1356. main.o: os_dep.h
  1357. main.o: combine.h
  1358. unix.o: unix.c
  1359. unix.o: ${ROOT}/usr/include/sys/types.h
  1360. unix.o: ${ROOT}/usr/include/sys/uio.h
  1361. unix.o: ${ROOT}/usr/include/sys/socket.h
  1362. unix.o: ${ROOT}/usr/include/sys/ioctl.h
  1363. unix.o: ${ROOT}/usr/include/sys/file.h
  1364. unix.o: util.h
  1365. unix.o: os_dep.h
  1366. unix.o: ${ROOT}/usr/include/stdio.h
  1367. unix.o: ${ROOT}/usr/include/ctype.h
  1368. data.o: data.c
  1369. data.o: ${ROOT}/usr/include/stdio.h
  1370. data.o: ${ROOT}/usr/include/ctype.h
  1371. data.o: util.h
  1372. data.o: os_dep.h
  1373. data.o: combine.h
  1374. comb2.o: comb2.c
  1375. comb2.o: ${ROOT}/usr/include/stdio.h
  1376. comb2.o: ${ROOT}/usr/include/ctype.h
  1377. comb2.o: util.h
  1378. comb2.o: os_dep.h
  1379. # DEPENDENCIES MUST END AT END OF FILE
  1380. # IF YOU PUT STUFF HERE IT WILL GO AWAY
  1381. # see make depend above
  1382. @//E*O*F Makefile//
  1383. chmod u=rw,g=rw,o=rw Makefile
  1384.  
  1385. exit 0
  1386.  
  1387.