home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include "util.h"
- #include "combine.h"
- /*
- * pass5: Output compared records
- *
- * The record arrays for the three files are traversed outputing the
- * resultant file. An index is maintained into each of the record arrays.
- * As each index is incremented the record is output. This routine merely
- * determines which file the next record is to come from.
- *
- * Return value:
- * This procedure has no return value.
- */
- void pass5 () {
-
- int i; /* Misc. variable */
-
- int indexes[MAX_FILE_COUNT];
- /* index into each of the record arrays */
-
- int j; /* Misc. variable */
-
- record_type * new_rec_ptr;/* Pointer to the current record */
-
- record_type * old_rec_ptr;/* Pointer to the record for the previously
- current record */
-
- relate_type relate; /* Relationships for the current record under
- consideration */
-
-
- /*
- * Initialize the scan.
- *
- * Note: for files which don't exist, the value initialized below
- * needs to yield a TRUE result for the end of file comparison done
- * below.
- */
- for (i = 0; i < MAX_FILE_COUNT; ++i) {
- indexes[i] = BEGIN_INDEX + 1;/* skip the dummy begin record */
- }
-
- /*
- * For each line output.
- */
- for (;;) {
-
- /*
- * For each file,
- * if the current record in the file is not involved in a
- * move operation, then the record should be dumped
- * immediately.
- *
- * This condition occurs for the following cirucumstances:
- * The record exists in the current position in all
- * three files.
- * The record exists in the current position in this
- * file and one of the other files. However,
- * the record does not occur anywhere in the
- * third file.
- * The record exists in the current position in this
- * file and does not occur anywhere in the other
- * two files.
- */
- for (i = 0; i < file_count; ++i) {
-
- pass5_analyze_relationship (
- i,/* file containing record */
- indexes, /* current posit. in all files */
- &relate); /* Returns file relationships */
-
- if (!relate.moved) {
-
- if (indexes[OLD_FILE] >=
- files[OLD_FILE].record_array_size - 1 &&
- indexes[NEW1_FILE] >=
- files[NEW1_FILE].record_array_size-1 &&
- indexes[NEW2_FILE] >=
- files[NEW2_FILE].record_array_size-1) {
-
- relate.relation = INSERT_EOT;
- pass5_dump_record (i, indexes, &relate);
- return;
- }
-
- pass5_dump_record (i, indexes, &relate);
- goto continue_big_loop;
- }
-
- }
-
- /*
- * All other cases involve a move of text from one location to
- * another.
- *
- * The 'pass5_move' routine analyses which text is the shortest text.
- */
-
- i = pass5_move (indexes);
-
- pass5_analyze_relationship (
- i, /* file containing record */
- indexes, /* current position in all files */
- &relate); /* Returns file relationships */
-
- old_rec_ptr = &(files[i].record[indexes[i]]);
-
- for (;;) {
-
- pass5_dump_record (i, indexes, &relate);
-
- /*
- * If any of the files involved in the move have now
- * reached EOT,
- * go on to process bigger and better things.
- */
- for (j = 0; j < file_count; ++j) {
- if (!is_hash_code (relate.index[j])) {
- relate.index[j]++;
- if (relate.index[j] + 1 >=
- files[j].record_array_size) {
- goto continue_big_loop;
- }
- }
- }
-
- /*
- * Note: this code should continue to dump records
- * without re-iterating the pass5_move routine.
- * Since the pass5_move routine executes in a loop,
- * the above_mentioned enhancement is required to ensure
- * that pass5 completes in linear time.
- *
- * The test below determines if the current record
- * is logically next to the previous record.
- * If so, the record is merely dumped.
- * Note: the record relationship does not change
- * for this record.
- *
- * A record is logically next to a previous one
- * if either the value field is a hash code for
- * both records or if the record index in the
- * value field is one greater then that of the
- * previous record.
- */
-
- new_rec_ptr = &(files[i].record[indexes[i]]);
-
- for (j = 0; j < MAX_VALUE_SUB; ++j) {
- if (is_hash_code (old_rec_ptr -> value[j])) {
- if(is_hash_code(new_rec_ptr->value[j])){
- continue;
- }
- } else if (old_rec_ptr->value[j]+1 ==
- new_rec_ptr -> value[j]) {
- continue;
- }
- goto continue_big_loop;
- }
-
- old_rec_ptr = new_rec_ptr;
-
- }
-
- continue_big_loop: ;
- }
-
- }
- /*
- * pass5_analyze_relationship -- determine relationsip to other files
- *
- * This routine determines the relationship between one record in one file
- * and the records at the current position in the other files.
- * The routine returns information regarding whether the record exists
- * in each file at the current position and whether the record is involved
- * in a move operation.
- *
- * Return value:
- * This procedure returns no value.
- */
- void pass5_analyze_relationship (file_no, indexes, rel_ptr)
- int file_no; /* input -- file number of the file
- containing the record to be compared. */
-
- int indexes[MAX_FILE_COUNT];/* input -- Array of the current
- indexes into the record arrays */
-
- relate_type * rel_ptr; /* output -- Returns relationship between
- current record and records at the current
- position in the corresponding files. */
-
- {
-
- int i; /* Misc. variable */
-
- int power; /* Current power of 2 */
-
- record_type * record_ptr;/* Pointer to the record block is the record
- currently being analyzed. */
-
-
-
- /*
- * Initialize the value_index array to contain the index of the current
- * record in each of the files.
- *
- * The record is at the current position in the current file. The record
- * is in the position indicated by the 'value' field in the record entry
- * for the other files.
- */
- record_ptr = &(files[file_no].record[indexes[file_no]]);
-
- rel_ptr -> index[file_no] = indexes[file_no];
- rel_ptr -> index[corres_file[file_no * 2]] =
- record_ptr -> value[value_sub[file_no * 2]];
- rel_ptr -> index[corres_file[file_no * 2 + 1]] =
- record_ptr -> value[value_sub[file_no * 2 + 1]];
-
- /*
- * Compare the current position in each file with the index of
- * this record in each file.
- */
- rel_ptr -> moved = FALSE;
- rel_ptr -> in_all = TRUE;
- rel_ptr -> relation = 0;
-
- power = 1;
-
- for (i = 0; i < file_count; ++i) {
-
- rel_ptr -> current[i] = (rel_ptr -> index[i] == indexes[i]);
-
- if (rel_ptr -> current[i]) {
- rel_ptr -> relation += power;
-
- } else {
- rel_ptr -> in_all = FALSE;
- if (!is_hash_code (rel_ptr -> index[i])) {
- rel_ptr -> moved = TRUE;
- }
- }
-
- power *= 2;
-
- }
-
- }
- /*
- * pass5_dump_record: write a record for pass 5
- *
- * This routine writes the specified record to the output files and
- * increments the appropriate indexes.
- *
- * Return value:
- * This routine returns no value.
- */
- void pass5_dump_record (file_no, indexes, rel_ptr)
- int file_no; /* input -- File number of the file to
- read record from. */
-
- int indexes[MAX_FILE_COUNT];/* input/output -- Indexes of the current
- records. Each index is incremented as
- appropriate */
-
- relate_type * rel_ptr; /* input -- Relationships
- of this record to other files. */
-
- {
-
- cache_entry_type * cache_ptr;/* Current cache entry pointer */
-
- file_type * file_ptr; /* Pointer to the current file */
-
- int i; /* Misc. variable */
-
- /*
- * Consider the case that the comparison was done with the -B
- * option. In that case, records reported to be identical here
- * may actually only be similar. The loop below computes the
- * largest file_no which has a record "identical" to the
- * current one. The theory is that the largest file_no contains
- * the "newest" record (and by deduction, the "best" record).
- */
- for (i = file_no+1; i < file_count; ++i) {
- if (rel_ptr -> current[i]) {
- if ( p5_debug ) {
- printf ( "debug: oldfile:%d newfile: %d\n",
- file_no, i );
- }
- file_no = i;
- }
- }
-
- /*
- * If this is the end of the world,
- * Pass the word on.
- */
- if (rel_ptr -> relation == INSERT_EOT) {
- if (hed_flag) {
- pass5_write_hed (rel_ptr, (cache_entry_type *) 0);
- } else {
- pass5_write_listing(indexes, rel_ptr,
- (cache_entry_type *) 0);
- }
- return;
- }
-
- /*
- * Initialize local variables.
- *
- * The cache of records is maintained as a queue of the previously seen
- * records. This queue is used by the 'write' routines.
- */
-
- file_ptr = &files[file_no];
- deq_tail_dll (cache_head_ptr, cache_tail_ptr, cache_ptr,
- cache_next_ptr, cache_prev_ptr);
- enq_head_dll (cache_head_ptr, cache_tail_ptr, cache_ptr,
- cache_next_ptr, cache_prev_ptr);
-
- /*
- * Write record to output files.
- */
- if (p5_debug) {
- printf ( "debug: file:%d indexes:%5d %5d %5d current: %d %d %d move: %d\n",
- file_no, indexes[0], indexes[1], indexes[2],
- rel_ptr -> current[0], rel_ptr -> current[1], rel_ptr -> current[2],
- rel_ptr -> moved);
- }
- if (hed_flag) {
- /* if hed_flag, always read record into cache */
- reread_into_cache( file_ptr, indexes[file_no], cache_ptr );
- pass5_write_hed (rel_ptr, cache_ptr);
- } else {
- /* for normal output, wait to read into cache until we
- know for sure it is going to be needed. Most
- records are merely skipped and not output at all. */
- pass5_write_listing (indexes, rel_ptr, cache_ptr);
- }
-
- /*
- * Increment the count of differences.
- */
- switch (rel_ptr -> relation) {
- case INSERT_OLD:
- case INSERT_NEW1_NEW2:
- old_new1_change_count++;
- old_new2_change_count++;
- break;
- case INSERT_NEW1:
- case INSERT_OLD_NEW2:
- old_new1_change_count++;
- new1_new2_change_count++;
- break;
- case INSERT_NEW2:
- case INSERT_OLD_NEW1:
- old_new2_change_count++;
- new1_new2_change_count++;
- break;
- case INSERT_OLD_NEW1_NEW2:
- break;
- default:
- error ("pass5_dump_record: invalid relation");
- }
-
- /*
- * Increment the record indexes.
- */
- for (i = 0; i < file_count; ++i) {
- if (rel_ptr -> current[i]) {
- indexes[i]++;
- }
- }
- }
- /*
- * pass5_move: Analyse which text moved.
- *
- * This routine is called when a group of moved lines is detected.
- * A group of moved lines exists when (for the current position in
- * the file) the next line occurs in all three files but at different
- * relative positions. This routine scans forward in the each of the
- * 3 files trying to determine the shortest group of lines.
- *
- * In determining the shortest group of lines, inserted and deleted records
- * are not considered. Rather, the scan continues until a line which is
- * before the current line is found.
- *
- * Return value:
- * This procedure return the file number of the file to be traversed
- * to indicate the shortest common sequence of lines.
- */
- int pass5_move (indexes)
- int *indexes; /* Array of pointers to the current indexes
- into the record arrays */
-
- {
-
- int corres_file_recno;
- /* Record number in the corresponding file */
-
- int depth; /* Number of lines tested */
-
- int i; /* Misc. variable */
-
- record_type * record; /* Pointer to record array for the current
- file. */
-
- /*
- * For each record, six different comparison need to be made. That is,
- * for each of the three files there is a relationship to each of the
- * other two files. A comparison needs to be made for each of those
- * relationships. The tables below describe the six relationships.
- */
-
- int index[MATCH_COUNT];/* Current index into the record array of
- 'curr_file' */
-
- int prev_value[MATCH_COUNT];
- /* Previous contents of the 'value' field for
- the record */
-
- bool bypass[MATCH_COUNT];/* TRUE if file should not by considered for
- processing */
-
-
- /*
- * Initialize the index array and the prev_value array from the values
- * passed in.
- *
- * During this initialization, all entries which contain hash codes
- * are skipped over. All such entries represent a line which exists in
- * only two of the files.
- */
-
- for (i = 0; i < MATCH_COUNT; ++i) {
-
- bypass[i] = (files[curr_file[i]].record == 0) ||
- (files[corres_file[i]].record == 0) ||
- (indexes[curr_file[i]] + 1 >=
- files[curr_file[i]].record_array_size);
-
- if (!bypass[i]) {
- record = files[curr_file[i]].record;
- index[i] = indexes[curr_file[i]];
- while(is_hash_code(
- record[index[i]].value[value_sub[i]])) {
-
- index[i]++;
- }
- prev_value[i] = record[index[i]].value[value_sub[i]];
- }
-
- }
-
- /*
- * Indentify the shortest common sequence of lines.
- *
- * For each iteration of this loop the index into the record array for
- * each of the six cases is incremented by one. The record detected at the
- * new index is compared against the previous record for the same case.
- *
- * In the documentation below, the 'current' file is the one which
- * has a relationship and the 'corresponding' file is the one related to.
- */
- for (depth = 0;; depth++) {
- for (i = 0; i < MATCH_COUNT; ++i) {
-
- /*
- * If this files has no records or no records left
- * to dump,
- * ignore the file.
- *
- * This happens in the case of a two file comparision.
- * or in the case of one file completely output.
- */
- if (bypass[i]) {
- continue;
- }
-
- /*
- * If we have reached the end of the 'current' file,
- * If this line is also the end of the
- * 'corresponding' file,
- * If the 'corresponding' file is at EOF already,
- * the 'current' file contains the
- * shortest sequence
- * else
- * the 'corresponding' file contains the
- * shortest sequence
- * else
- * the 'current' file contains the shortest
- * common sequence.
- */
- if(index[i]+1 >= files[curr_file[i]].record_array_size){
- if (prev_value[i] + 1 >=
- files[corres_file[i]].record_array_size) {
-
- if (indexes[corres_file[i]] + 1 >=
- files[corres_file[i]].
- record_array_size) {
-
- return (curr_file[i]);
- } else {
- return (corres_file[i]);
- }
- } else {
- return (curr_file[i]);
- }
- }
-
- /*
- * For each record in the 'current' file which doesn't
- * have a record in the 'corresponding' file,
- * skip past the record.
- *
- * Since what we are trying to find is the shortest
- * group of records in the 'corresponding' file,
- * the search should not be penalized by
- * inserted records in the 'current' file.
- */
- record = files[curr_file[i]].record;
- index[i]++;
- while (is_hash_code(record[index[i]].
- value[value_sub[i]])) {
-
- index[i]++;
- }
-
- /*
- * If the record number in the corresponding file
- * is one of the records being considered as
- * moved by the 'corresponding' file, the 'current'
- * file contains the shortest common sequence.
- *
- * Note: this routine is only invoked if all files
- * are currently involved in a move.
- *
- * By outputting lines from the 'current' file,
- * we will soon get to the current point in the
- * 'corresponding' file. At that point, the
- * current line in the 'corresponding' file will
- * no longer be diagnosed as having moved.
- */
- corres_file_recno = record[index[i]].
- value[value_sub[i]];
-
- if (corres_file_recno >= indexes[corres_file[i]] &&
- corres_file_recno <=
- indexes[corres_file[i]] + depth) {
- if (p5_debug)
- printf("move optimization found\n");
-
- return (curr_file[i]);
- }
- }
- /*
- * The above loop and this loop were split in order to give the
- * above loop every opportunity to find a move optimization.
- */
- for (i = 0; i < MATCH_COUNT; ++i) {
- if (bypass[i])
- continue;
- record = files[curr_file[i]].record;
- corres_file_recno = record[index[i]].
- value[value_sub[i]];
-
- /*
- * If the record numbers in the 'corresponding' file are
- * still going in the forward direction,
- * then we haven't completed the search.
- *
- * Record numbers need not be immediately next to
- * one another (e.g. record number 5 and record
- * number 6). Record numbers merely need to
- * following one another. This ensures that the common
- * sequence check isn't interrupted by deletions in the
- * 'corresponding' file.
- *
- * The above comment is hereby rescinded. Cliff 1/23/85
- */
- if (prev_value[i] + 1 == corres_file_recno) {
- prev_value[i] = corres_file_recno;
- } else {
- if (p5_debug)
- printf("short move found %d\n", depth);
- return (curr_file[i]);
- }
- }
- }
-
- }
-
- /*
- * pass5_write_hed: write a record to 'hed' file.
- *
- * This routine writes the specified record to the 'hed' output file.
- *
- * Return value:
- * This routine returns no value.
- */
- void pass5_write_hed (rel_ptr, cache_ptr)
- relate_type * rel_ptr; /* input */
- /* Relationships of this record to other files. */
-
- cache_entry_type * cache_ptr; /* input */
- /* Cache entry describing buffer */
-
- {
-
- bool flag; /* TRUE if NEW1 and OLD file not same */
-
- int i; /* Misc. variable */
-
- #define HED_END_RECORD "~End of changes"
-
- static int prev_relation = INSERT_NONE;
- /* Relationship of previous call */
-
- static bool prev_in_all = TRUE;
- /* TRUE if previous record was in all of the files */
-
-
- /*
- * Handle EOT case.
- */
- if (rel_ptr -> relation == INSERT_EOT) {
- if (!prev_in_all) {
- puts (HED_END_RECORD);
- }
- return;
- }
-
- /*
- * Write any header of trailing records to 'hed' file.
- */
-
- if (rel_ptr -> relation != prev_relation) {
- if (!prev_in_all) {
- puts (HED_END_RECORD);
- }
-
-
- if (!rel_ptr -> in_all) {
- (void) fputs ("~~", stdout);
-
- if (rel_ptr -> current[OLD_FILE]) {
- (void) fputs ("Delete ", stdout);
- } else {
- (void) fputs ("Insert ", stdout);
- }
-
- flag = FALSE;
-
- for (i = NEW1_FILE; i < file_count; ++i) {
-
- if (rel_ptr -> current[OLD_FILE] !=
- rel_ptr -> current[i]) {
-
- if (flag) {
- (void) fputs (" and ", stdout);
- }
-
- (void) fputs("'", stdout);
- (void) fputs(files[i].text_ptr?
- files[i].text_ptr:
- files[i].name_ptr,
- stdout);
- (void) fputs("'", stdout);
- flag = TRUE;
-
- if (!is_hash_code(rel_ptr->index[i]) &&
- !is_hash_code(
- rel_ptr->index[OLD_FILE])) {
-
- (void) fputs(" (MOVED)",stdout);
- }
-
- }
-
- }
-
- (void) putchar ('\n');
-
- }
-
- prev_relation = rel_ptr -> relation;
- prev_in_all = rel_ptr -> in_all;
- }
-
- /*
- * Write record to 'hed' file.
- */
- cache_ptr -> recordp[cache_ptr -> record_length] = '\0';
- (void) puts (cache_ptr -> recordp);
-
- }
- /*
- * pass5_write_listing: write a record to 'listing' file.
- *
- * This routine writes a summary of the changes to the standard output.
- *
- * This routine writes all changed lines to standard output. It also
- * writes a few (-prefix and -postifx options) unchanged lines immediately
- * preceeding and following the changed lines. This routine assumes that
- * the caller, 'pass5_dump_record', is maintaining a queue of all records
- * read in the cache. The current record should be at the head of the
- * cache. The previous record should immediately follow that, etc.
- *
- * Return value:
- * This routine returns no value.
- */
-
- void pass5_write_listing (indexes, rel_ptr, cache_ptr)
- int indexes[MAX_FILE_COUNT];/* input */
- /* Indexes of the current records. */
-
- relate_type * rel_ptr; /* input */
- /* Relationships of this record to other files. */
-
- cache_entry_type * cache_ptr; /* input */
- /* Cache entry describing buffer */
-
- {
-
- static relate_type all_rel;
- /* relation used for outputting prefix lines.*/
-
- int i; /* Misc. variable */
-
- static int postfix_count = 0;
- /* Number of postfix lines remaining to output*/
-
- cache_entry_type * prefix_cache_ptr;
- /* Pointer to cache entry containing the
- current prefix line */
-
- int prefix_count; /* Number of prefix lines to output */
-
- static int prev_relation = INSERT_NONE;
- /* Relationship of previous call */
-
- static bool prev_in_all = TRUE;
- /* TRUE if previous line was in all files at
- the current position */
-
- static int same_count = 0;
- /* Number of indentical lines scanned so far
- which might later be output as prefix lines.
- */
-
-
-
- /*
- * Handle EOT case.
- */
- if (rel_ptr -> relation == INSERT_EOT) {
- if (!quiet_option) {
- if (old_new1_change_count == 0 &&
- (file_count == 2 ||
- (old_new2_change_count == 0 &&
- new1_new2_change_count == 0))) {
-
- (void) strcpy (cache_tail_ptr -> recordp, "Files are identical");
- cache_tail_ptr -> record_length = strlen (cache_tail_ptr -> recordp);
- pass5_write_listing_line ((relate_type *) 0, cache_tail_ptr);
- } else {
- cache_tail_ptr -> record_length = 0;
- pass5_write_listing_line((relate_type *) 0,
- cache_tail_ptr);
- (void) strcpy(cache_tail_ptr->recordp,
- "[ Comparison Complete ]");
- cache_tail_ptr->record_length =
- strlen(cache_tail_ptr -> recordp);
- pass5_write_listing_line((relate_type *) 0,
- cache_tail_ptr);
- }
- if (page_length) (void) putchar('\f');
- }
- return;
- }
-
- /*
- * Write any prefix lines which need to be written.
- */
- if (rel_ptr -> relation != prev_relation && prev_in_all) {
-
- prefix_count = min (prefix_lines, same_count);
-
- if (same_count > prefix_count) {
- /* Output separator line */
- pass5_write_listing_line ((relate_type *) 0,
- (cache_entry_type *) 0);
- }
-
- prefix_cache_ptr = cache_ptr;
- for (i = 0; i < prefix_count; ++i) {
- prefix_cache_ptr = prefix_cache_ptr -> cache_next_ptr;
- }
-
- all_rel.relation = INSERT_OLD_NEW1_NEW2;
- all_rel.moved = FALSE;
- all_rel.in_all = TRUE;
-
- while (prefix_count > 0) {
-
- for (i = 0; i < file_count; ++i) {
- all_rel.index[i] = indexes[i] - prefix_count;
- all_rel.current[i] = TRUE;
- }
-
- pass5_write_listing_line (
- &all_rel, /* Indicate all lines are related */
- prefix_cache_ptr); /* Pointer to record in cache */
-
- prefix_count--;
- prefix_cache_ptr = prefix_cache_ptr -> cache_prev_ptr;
-
- }
-
- }
-
- /*
- * If this is the first identical line,
- * indicate how many postifx lines need to be output.
- */
- if (rel_ptr -> relation != prev_relation && rel_ptr -> in_all &&
- prev_relation != INSERT_NONE) {
- postfix_count = postfix_lines;
- }
-
- prev_relation = rel_ptr -> relation;
- prev_in_all = rel_ptr -> in_all;
-
- /*
- * If this line is a changed line or a postfix line,
- * dump it.
- */
- if (!rel_ptr -> in_all || postfix_count > 0) {
- pass5_write_listing_line (
- rel_ptr,/* Line relationships */
- cache_ptr);/* Pointer to record in cache */
- }
-
- /*
- * Count the number of identical lines
- * and keep track of the number of postfix lines printed.
- */
- if (rel_ptr -> in_all) {
- if (postfix_count <= 0) {
- same_count++;
- }
- postfix_count--;
- } else {
- same_count = 0;
- }
-
- }
- /*
- * pass5_write_listing_line: write a record to 'listing' file.
- *
- * This routine writes a single line to the 'listing' file. The line has
- * already been checked to ensure that the line is to be output.
- *
- * Return value:
- * This routine returns no value.
- */
-
- void pass5_write_listing_line (rel_ptr, cache_ptr)
- relate_type * rel_ptr; /* input -- Relationships of this record to
- other files. If this pointer is 0, write the line
- pointed to by cache_entry_type with
- no special formatting */
-
- cache_entry_type * cache_ptr; /* input -- Cache entry describing buffer
- If this pointer is 0, write a
- separator line between changes */
-
- {
-
- int i; /* Misc. variable */
-
- static int line_count = 0;/* Number of lines left on a page */
-
- static int page_count = 0;/* Number of pages output so far */
-
-
-
- /*
- * Output the header lines, if required.
- *
- * Don't output separator record too close to bottom of a page.
- *
- * Don't use any pagination if "page_length" is zero
- */
- if ( page_length ) --line_count;
- if ( (page_length || !page_count) &&
- (line_count <= 0 || (line_count <= 10 && cache_ptr == 0))
- ) {
-
- if ( (page_count > 0) && (line_count > 0) )
- (void) putchar('\f');
- page_count++;
- line_count = (page_length - HEAD_LENGTH);
- if ( page_count > 1 ) ++line_count;
-
- printf ("Time of comparison: %s", exec_time);
- if ( page_length )
- printf (" Page %d\n\n", page_count);
- else
- puts ("\n\n");
-
- if (file_count == 2) {
- pass5_write_listing_head("Old ", OLD_FILE);
- pass5_write_listing_head("New ", NEW1_FILE);
- (void) putchar ('\n');
- puts ("Status Old New Contents");
- puts ("------ --- --- --------");
- } else {
- pass5_write_listing_head("Old ", OLD_FILE);
- pass5_write_listing_head("New1", NEW1_FILE);
- pass5_write_listing_head("New2", NEW2_FILE);
- (void) putchar ('\n');
- puts ("Status Old New1 New2 Contents");
- puts ("------ --- ---- ---- --------");
- }
-
- puts ("\n");
-
- if (cache_ptr == 0) {
- return; /* Don't put separator record at top of page */
- }
-
- }
-
- /*
- * If rel_ptr exists,
- * Output the Line status and file line numbers:
- */
- if (rel_ptr != 0) {
- if (!rel_ptr -> in_all) {
-
- if (rel_ptr -> current[OLD_FILE]) {
- if (rel_ptr -> moved) {
- fputs ("MOV[O]", stdout);
- } else {
- fputs ("Delete", stdout);
- }
- } else {
- if (rel_ptr -> moved) {
- fputs ("MOV[N]", stdout);
- } else {
- fputs ("Insert", stdout);
- }
- }
-
- } else {
-
- fputs (" ", stdout);
-
- }
-
- cache_ptr->record_length = -1;
- for (i = 0; i < file_count; ++i) {
- if (is_hash_code (rel_ptr -> index[i])) {
- fputs (" ", stdout);
- } else {
- if (cache_ptr->record_length == -1) {
- reread_into_cache( &files[i],
- rel_ptr->index[i],
- cache_ptr );
- }
- printf ("%6d ", rel_ptr -> index[i]);
- }
- }
-
- } else if (cache_ptr == 0) {
-
- puts ("******");
- return;
-
- }
-
- /*
- * Finally, write the line.
- */
- if (cache_ptr -> record_length == -1) {
- puts (" < EOF.. >");
- } else {
- cache_ptr -> recordp[cache_ptr -> record_length] = '\0';
- puts (cache_ptr -> recordp);
- }
-
- }
- /*
- * pass5_write_listing_head: write a header line to 'listing' file.
- *
- * This routine writes a single header line to the 'listing' file.
- *
- * Return value:
- * This routine returns no value.
- */
- void pass5_write_listing_head (name_ptr, file_no)
- char * name_ptr; /* input -- name of header */
-
- int file_no; /* input -- file number of the file
- containing the record to be compared. */
-
- {
- printf ("%s area: '%s' Last Written: %s",
- name_ptr,
- files[file_no].name_ptr,
- files[file_no].lw_ptr);
-
- if ( files[file_no].text_ptr ) {
- printf (" Text: '%s'", files[file_no].text_ptr );
- }
- (void) putchar ('\n');
- }
-