⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 analyze.c

📁 WinMerge可以显示两个文件的不同之处
💻 C
📖 第 1 页 / 共 3 页
字号:

static struct change *
build_reverse_script (filevec)
     struct file_data const filevec[];
{
  struct change *script = 0;
  char *changed0 = filevec[0].changed_flag;
  char *changed1 = filevec[1].changed_flag;
  int len0 = filevec[0].buffered_lines;
  int len1 = filevec[1].buffered_lines;

  /* Note that changedN[len0] does exist, and contains 0.  */

  int i0 = 0, i1 = 0;

  while (i0 < len0 || i1 < len1)
    {
      if (changed0[i0] || changed1[i1])
	{
	  int line0 = i0, line1 = i1;

	  /* Find # lines changed here in each file.  */
	  while (changed0[i0]) ++i0;
	  while (changed1[i1]) ++i1;

	  /* Record this change.  */
	  script = add_change (line0, line1, i0 - line0, i1 - line1, script);
	}

      /* We have reached lines in the two files that match each other.  */
      i0++, i1++;
    }

  return script;
}

/* Scan the tables of which lines are inserted and deleted,
   producing an edit script in forward order.  */

static struct change *
build_script (filevec)
     struct file_data const filevec[];
{
  struct change *script = 0;
  char *changed0 = filevec[0].changed_flag;
  char *changed1 = filevec[1].changed_flag;
  int i0 = filevec[0].buffered_lines, i1 = filevec[1].buffered_lines;

  /* Note that changedN[-1] does exist, and contains 0.  */

  while (i0 >= 0 || i1 >= 0)
    {
      if (changed0[i0 - 1] || changed1[i1 - 1])
	{
	  int line0 = i0, line1 = i1;

	  /* Find # lines changed here in each file.  */
	  while (changed0[i0 - 1]) --i0;
	  while (changed1[i1 - 1]) --i1;

	  /* Record this change.  */
	  script = add_change (i0, i1, line0 - i0, line1 - i1, script);
	}

      /* We have reached lines in the two files that match each other.  */
      i0--, i1--;
    }

  return script;
}

/* If CHANGES, briefly report that two files differed.  */
static void
briefly_report (changes, filevec)
     int changes;
     struct file_data const filevec[];
{
  if (changes)
    message (no_details_flag ? "Files %s and %s differ\n"
	     : "Binary files %s and %s differ\n",
	     filevec[0].name, filevec[1].name);
}

//  Report the differences of two files.  DEPTH is the current directory
// depth. 
struct change * diff_2_files (struct file_data filevec[], int depth, int * bin_status, int moved_blocks_flag)
{
	int diags;
	int i;
	struct change *script=NULL;
	int changes;
	
	
	//  If we have detected that either file is binary,
	// compare the two files as binary.  This can happen
	// only when the first chunk is read.
	// Also, --brief without any --ignore-* options means
	// we can speed things up by treating the files as binary.  
	
	if (read_files (filevec, no_details_flag & ~ignore_some_changes))
	{
		//  Files with different lengths must be different.  
		if (filevec[0].stat.st_size != filevec[1].stat.st_size
			&& (filevec[0].desc < 0 || S_ISREG (filevec[0].stat.st_mode))
			&& (filevec[1].desc < 0 || S_ISREG (filevec[1].stat.st_mode)))
			changes = 1;
		
		//  Standard input equals itself.  
		else if (filevec[0].desc == filevec[1].desc)
			changes = 0;
		else
			//  Scan both files, a buffer at a time, looking for a difference.  
		{
			//  Allocate same-sized buffers for both files.  
			size_t buffer_size = buffer_lcm (STAT_BLOCKSIZE (filevec[0].stat),
				STAT_BLOCKSIZE (filevec[1].stat));
			for (i = 0; i < 2; i++)
				filevec[i].buffer = (char *)xrealloc (filevec[i].buffer, buffer_size);
			
			for (;;  filevec[0].buffered_chars = filevec[1].buffered_chars = 0)
			{
				//  Read a buffer's worth from both files.  
				for (i = 0; i < 2; i++)
					if (0 <= filevec[i].desc)
						while (filevec[i].buffered_chars != buffer_size)
						{
							int r = read (filevec[i].desc,
								filevec[i].buffer
								+ filevec[i].buffered_chars,
								buffer_size - filevec[i].buffered_chars);
							if (r == 0)
								break;
							if (r < 0)
								pfatal_with_name (filevec[i].name);
							filevec[i].buffered_chars += r;
						}
						
						//  If the buffers differ, the files differ.  
						if (filevec[0].buffered_chars != filevec[1].buffered_chars
							|| (filevec[0].buffered_chars != 0
							&& memcmp (filevec[0].buffer,
							filevec[1].buffer,
							filevec[0].buffered_chars) != 0))
						{
							changes = 1;
							break;
						}
						
						//  If we reach end of file, the files are the same.  
						if (filevec[0].buffered_chars != buffer_size)
						{
							changes = 0;
							break;
						}
			}
		}
		
		briefly_report (changes, filevec);

		if (bin_status != NULL)
			*bin_status = (changes != 0 ? -1 : 1);
	}
	else
	{
		//  Allocate vectors for the results of comparison:
		// a flag for each line of each file, saying whether that line
		// is an insertion or deletion.
		// Allocate an extra element, always zero, at each end of each vector.  
		
		size_t s = filevec[0].buffered_lines + filevec[1].buffered_lines + 4;
		filevec[0].changed_flag = (char *)xmalloc (s);
		bzero (filevec[0].changed_flag, s);
		filevec[0].changed_flag++;
		filevec[1].changed_flag = filevec[0].changed_flag
			+ filevec[0].buffered_lines + 2;
		
		//  Some lines are obviously insertions or deletions
		// because they don't match anything.  Detect them now, and
		// avoid even thinking about them in the main comparison algorithm.  
		
		discard_confusing_lines (filevec);
		
		//  Now do the main comparison algorithm, considering just the
		// undiscarded lines.  
		
		xvec = filevec[0].undiscarded;
		yvec = filevec[1].undiscarded;
		diags = filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines + 3;
		fdiag = (int *) xmalloc (diags * (2 * sizeof (int)));
		bdiag = fdiag + diags;
		fdiag += filevec[1].nondiscarded_lines + 1;
		bdiag += filevec[1].nondiscarded_lines + 1;
		
      /* Set TOO_EXPENSIVE to be approximate square root of input size,
	 bounded below by 256.  */
      too_expensive = 1;
      for (i = filevec[0].nondiscarded_lines + filevec[1].nondiscarded_lines;
	   i != 0; i >>= 2)
	too_expensive <<= 1;
      too_expensive = max (256, too_expensive);

		files[0] = filevec[0];
		files[1] = filevec[1];
		
		compareseq (0, filevec[0].nondiscarded_lines,
		  0, filevec[1].nondiscarded_lines, no_discards);
		
		free (fdiag - (filevec[1].nondiscarded_lines + 1));
		
		//  Modify the results slightly to make them prettier
		// in cases where that can validly be done.  
		
		shift_boundaries (filevec);
		
		//  Get the results of comparison in the form of a chain
		// of `struct change's -- an edit script.  
		
		if (output_style == OUTPUT_ED)
			script = build_reverse_script (filevec);
		else
			script = build_script (filevec);
		
		//  Set CHANGES if we had any diffs.
		// If some changes are ignored, we must scan the script to decide.  
		if (ignore_blank_lines_flag || ignore_regexp_list)
		{
			struct change *next = script;
			changes = 0;
			
			while (next && changes == 0)
			{
				struct change *thisob, *end;
				int first0, last0, first1, last1, deletes, inserts;
				
				//  Find a set of changes that belong together.  
				thisob = next;
				end = find_change (next);
				
				//  Disconnect them from the rest of the changes, making them
				// a hunk, and remember the rest for next iteration.  
				next = end->link;
				end->link = 0;
				
				//  Determine whether thisob hunk is really a difference.  
				analyze_hunk (thisob, &first0, &last0, &first1, &last1,
					&deletes, &inserts);
				
				//  Reconnect the script so it will all be freed properly.  
				end->link = next;
				
				if (deletes || inserts)
					changes = 1;

			}
			if (script)
				script->trivial = !changes;
		}
		else
		{
			changes = (script != 0);
		}

		/* WinMerge moved block support */
		if (moved_blocks_flag)
		{
			moved_block_analysis(&script, filevec);
		}
		
		if (no_details_flag)
			briefly_report (changes, filevec);
		else
		{
			if (changes==0 && ignore_blank_lines_flag)
			{
				// determined that there were no nontrivial changes after considering flags
			}
			else if (changes == 0 && ignore_regexp_list )
			{
				// determined that there were no nontrivial changes after considering flags
			}
			else if (changes || ! no_diff_means_no_output)
			{
				//  Record info for starting up output,
				// to be used if and when we have some output to print.  
				setup_output (files[0].name, files[1].name, depth);
				
				/*switch (output_style)
				{
				case OUTPUT_CONTEXT:
					print_context_script (script, 0);
					break;
					
				case OUTPUT_UNIFIED:
					print_context_script (script, 1);
					break;
					
				case OUTPUT_ED:
					print_ed_script (script);
					break;
					
				case OUTPUT_FORWARD_ED:
					pr_forward_ed_script (script);
					break;
					
				case OUTPUT_RCS:
					print_rcs_script (script);
					break;
					
				case OUTPUT_NORMAL:
					print_normal_script (script);
					break;
					
				case OUTPUT_IFDEF:
					print_ifdef_script (script);
					break;
					
				case OUTPUT_SDIFF:
					print_sdiff_script (script);
				}
				
				finish_output ();*/
			}
		}
		
		//free (filevec[0].undiscarded);
		
		//free (filevec[0].changed_flag - 1);
		
		//for (i = 1; i >= 0; --i)
		//	free (filevec[i].equivs);
		
		//for (i = 0; i < 2; ++i)
		//	free (filevec[i].linbuf + filevec[i].linbuf_base);
		
		
		/*cleanup the script
		for (e = script; e; e = p)
		{
			p = e->link;
			free (e);
		}*/
		
		if (! ROBUST_OUTPUT_STYLE (output_style))
			for (i = 0; i < 2; ++i)
				if (filevec[i].missing_newline)
				{
					error ("No newline at end of file %s", filevec[i].name, "");
					changes = 2;
				}
    }
	
	//if (filevec[0].buffer != filevec[1].buffer)
	//	free (filevec[0].buffer);
	//free (filevec[1].buffer);
	
	return script;
}

void cleanup_file_buffers(struct file_data fd[])
{
	int i;
	free (fd[0].undiscarded);
	
	if (fd[0].changed_flag != NULL)
		free (fd[0].changed_flag - 1);
	
	for (i = 1; i >= 0; --i)
		free (fd[i].equivs);
	
	for (i = 0; i < 2; ++i)
		free ((void *)(fd[i].linbuf + fd[i].linbuf_base));

	if (fd[0].buffer != fd[1].buffer)
		free (fd[0].buffer);
	free (fd[1].buffer);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -