📄 diff3.c
字号:
switch (ptr->correspond) { case DIFF_ALL: x[0] = '\0'; dontprint = 3; /* Print them all */ oddoneout = 3; /* Nobody's odder than anyone else */ break; case DIFF_1ST: case DIFF_2ND: case DIFF_3RD: oddoneout = rev_mapping[(int) ptr->correspond - (int) DIFF_1ST]; x[0] = oddoneout + '1'; x[1] = '\0'; dontprint = oddoneout==0; break; default: fatal ("internal error: invalid diff type passed to output"); } fprintf (outputfile, "====%s\n", x); /* Go 0, 2, 1 if the first and third outputs are equivalent. */ for (i = 0; i < 3; i = (oddoneout == 1 ? skew_increment[i] : i + 1)) { int realfile = mapping[i]; int lowt = D_LOWLINE (ptr, realfile), hight = D_HIGHLINE (ptr, realfile); fprintf (outputfile, "%d:", i + 1); switch (lowt - hight) { case 1: fprintf (outputfile, "%da\n", lowt - 1); break; case 0: fprintf (outputfile, "%dc\n", lowt); break; default: fprintf (outputfile, "%d,%dc\n", lowt, hight); break; } if (i == dontprint) continue; if (lowt <= hight) { line = 0; do { fprintf (outputfile, line_prefix); cp = D_RELNUM (ptr, realfile, line); length = D_RELLEN (ptr, realfile, line); fwrite (cp, sizeof (char), length, outputfile); } while (++line < hight - lowt + 1); if (cp[length - 1] != '\n') fprintf (outputfile, "\n\\ No newline at end of file\n"); } } }}/* * Output to OUTPUTFILE the lines of B taken from FILENUM. * Double any initial '.'s; yield nonzero if any initial '.'s were doubled. */static intdotlines (outputfile, b, filenum) FILE *outputfile; struct diff3_block *b; int filenum;{ int i; int leading_dot = 0; for (i = 0; i < D_NUMLINES (b, filenum); i++) { char *line = D_RELNUM (b, filenum, i); if (line[0] == '.') { leading_dot = 1; fprintf (outputfile, "."); } fwrite (line, sizeof (char), D_RELLEN (b, filenum, i), outputfile); } return leading_dot;}/* * Output to OUTPUTFILE a '.' line. If LEADING_DOT is nonzero, * also output a command that removes initial '.'s * starting with line START and continuing for NUM lines. */static voidundotlines (outputfile, leading_dot, start, num) FILE *outputfile; int leading_dot, start, num;{ fprintf (outputfile, ".\n"); if (leading_dot) if (num == 1) fprintf (outputfile, "%ds/^\\.//\n", start); else fprintf (outputfile, "%d,%ds/^\\.//\n", start, start + num - 1);}/* * This routine outputs a diff3 set of blocks as an ed script. This * script applies the changes between file's 2 & 3 to file 1. It * takes the precise format of the ed script to be output from global * variables set during options processing. Note that it does * destructive things to the set of diff3 blocks it is passed; it * reverses their order (this gets around the problems involved with * changing line numbers in an ed script). * * Note that this routine has the same problem of mapping as the last * one did; the variable MAPPING maps from file number according to * the argument list to file number according to the diff passed. All * files listed below are in terms of the argument list. * REV_MAPPING is the inverse of MAPPING. * * The arguments FILE0, FILE1 and FILE2 are the strings to print * as the names of the three files. These may be the actual names, * or may be the arguments specified with -L. * * Returns 1 if conflicts were found. */static intoutput_diff3_edscript (outputfile, diff, mapping, rev_mapping, file0, file1, file2) FILE *outputfile; struct diff3_block *diff; int const mapping[3], rev_mapping[3]; char const *file0, *file1, *file2;{ int leading_dot; int conflicts_found = 0, conflict; struct diff3_block *b; for (b = reverse_diff3_blocklist (diff); b; b = b->next) { /* Must do mapping correctly. */ enum diff_type type = ((b->correspond == DIFF_ALL) ? DIFF_ALL : ((enum diff_type) (((int) DIFF_1ST) + rev_mapping[(int) b->correspond - (int) DIFF_1ST]))); /* If we aren't supposed to do this output block, skip it. */ switch (type) { default: continue; case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; case DIFF_ALL: if (simple_only) continue; conflict = flagging; break; } if (conflict) { conflicts_found = 1; /* Mark end of conflict. */ fprintf (outputfile, "%da\n", D_HIGHLINE (b, mapping[FILE0])); leading_dot = 0; if (type == DIFF_ALL) { if (show_2nd) { /* Append lines from FILE1. */ fprintf (outputfile, "||||||| %s\n", file1); leading_dot = dotlines (outputfile, b, mapping[FILE1]); } /* Append lines from FILE2. */ fprintf (outputfile, "=======\n"); leading_dot |= dotlines (outputfile, b, mapping[FILE2]); } fprintf (outputfile, ">>>>>>> %s\n", file2); undotlines (outputfile, leading_dot, D_HIGHLINE (b, mapping[FILE0]) + 2, (D_NUMLINES (b, mapping[FILE1]) + D_NUMLINES (b, mapping[FILE2]) + 1)); /* Mark start of conflict. */ fprintf (outputfile, "%da\n<<<<<<< %s\n", D_LOWLINE (b, mapping[FILE0]) - 1, type == DIFF_ALL ? file0 : file1); leading_dot = 0; if (type == DIFF_2ND) { /* Prepend lines from FILE1. */ leading_dot = dotlines (outputfile, b, mapping[FILE1]); fprintf (outputfile, "=======\n"); } undotlines (outputfile, leading_dot, D_LOWLINE (b, mapping[FILE0]) + 1, D_NUMLINES (b, mapping[FILE1])); } else if (D_NUMLINES (b, mapping[FILE2]) == 0) /* Write out a delete */ { if (D_NUMLINES (b, mapping[FILE0]) == 1) fprintf (outputfile, "%dd\n", D_LOWLINE (b, mapping[FILE0])); else fprintf (outputfile, "%d,%dd\n", D_LOWLINE (b, mapping[FILE0]), D_HIGHLINE (b, mapping[FILE0])); } else /* Write out an add or change */ { switch (D_NUMLINES (b, mapping[FILE0])) { case 0: fprintf (outputfile, "%da\n", D_HIGHLINE (b, mapping[FILE0])); break; case 1: fprintf (outputfile, "%dc\n", D_HIGHLINE (b, mapping[FILE0])); break; default: fprintf (outputfile, "%d,%dc\n", D_LOWLINE (b, mapping[FILE0]), D_HIGHLINE (b, mapping[FILE0])); break; } undotlines (outputfile, dotlines (outputfile, b, mapping[FILE2]), D_LOWLINE (b, mapping[FILE0]), D_NUMLINES (b, mapping[FILE2])); } } if (finalwrite) fprintf (outputfile, "w\nq\n"); return conflicts_found;}/* * Read from INFILE and output to OUTPUTFILE a set of diff3_ blocks DIFF * as a merged file. This acts like 'ed file0 <[output_diff3_edscript]', * except that it works even for binary data or incomplete lines. * * As before, MAPPING maps from arg list file number to diff file number, * REV_MAPPING is its inverse, * and FILE0, FILE1, and FILE2 are the names of the files. * * Returns 1 if conflicts were found. */static intoutput_diff3_merge (infile, outputfile, diff, mapping, rev_mapping, file0, file1, file2) FILE *infile, *outputfile; struct diff3_block *diff; int const mapping[3], rev_mapping[3]; char const *file0, *file1, *file2;{ int c, i; int conflicts_found = 0, conflict; struct diff3_block *b; int linesread = 0; for (b = diff; b; b = b->next) { /* Must do mapping correctly. */ enum diff_type type = ((b->correspond == DIFF_ALL) ? DIFF_ALL : ((enum diff_type) (((int) DIFF_1ST) + rev_mapping[(int) b->correspond - (int) DIFF_1ST]))); char const *format_2nd = "<<<<<<< %s\n"; /* If we aren't supposed to do this output block, skip it. */ switch (type) { default: continue; case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; case DIFF_ALL: if (simple_only) continue; conflict = flagging; format_2nd = "||||||| %s\n"; break; } /* Copy I lines from file 0. */ i = D_LOWLINE (b, FILE0) - linesread - 1; linesread += i; while (0 <= --i) do { c = getc (infile); if (c == EOF) if (ferror (infile)) perror_with_exit ("input file"); else if (feof (infile)) fatal ("input file shrank"); putc (c, outputfile); } while (c != '\n'); if (conflict) { conflicts_found = 1; if (type == DIFF_ALL) { /* Put in lines from FILE0 with bracket. */ fprintf (outputfile, "<<<<<<< %s\n", file0); for (i = 0; i < D_NUMLINES (b, mapping[FILE0]); i++) fwrite (D_RELNUM (b, mapping[FILE0], i), sizeof (char), D_RELLEN (b, mapping[FILE0], i), outputfile); } if (show_2nd) { /* Put in lines from FILE1 with bracket. */ fprintf (outputfile, format_2nd, file1); for (i = 0; i < D_NUMLINES (b, mapping[FILE1]); i++) fwrite (D_RELNUM (b, mapping[FILE1], i), sizeof (char), D_RELLEN (b, mapping[FILE1], i), outputfile); } fprintf (outputfile, "=======\n"); } /* Put in lines from FILE2. */ for (i = 0; i < D_NUMLINES (b, mapping[FILE2]); i++) fwrite (D_RELNUM (b, mapping[FILE2], i), sizeof (char), D_RELLEN (b, mapping[FILE2], i), outputfile); if (conflict) fprintf (outputfile, ">>>>>>> %s\n", file2); /* Skip I lines in file 0. */ i = D_NUMLINES (b, FILE0); linesread += i; while (0 <= --i) while ((c = getc (infile)) != '\n') if (c == EOF) if (ferror (infile)) perror_with_exit ("input file"); else if (feof (infile)) { if (i || b->next) fatal ("input file shrank"); return conflicts_found; } } /* Copy rest of common file. */ while ((c = getc (infile)) != EOF || !(ferror (infile) | feof (infile))) putc (c, outputfile); return conflicts_found;}/* * Reverse the order of the list of diff3 blocks. */static struct diff3_block *reverse_diff3_blocklist (diff) struct diff3_block *diff;{ register struct diff3_block *tmp, *next, *prev; for (tmp = diff, prev = 0; tmp; tmp = next) { next = tmp->next; tmp->next = prev; prev = tmp; } return prev;}static size_tmyread (fd, ptr, size) int fd; char *ptr; size_t size;{ size_t result = read (fd, ptr, size); if (result == -1) perror_with_exit ("read failed"); return result;}static VOID *xmalloc (size) size_t size;{ VOID *result = (VOID *) malloc (size ? size : 1); if (!result) fatal ("memory exhausted"); return result;}static VOID *xrealloc (ptr, size) VOID *ptr; size_t size;{ VOID *result = (VOID *) realloc (ptr, size ? size : 1); if (!result) fatal ("memory exhausted"); return result;}static voidfatal (string) char const *string;{ fprintf (stderr, "%s: %s\n", program_name, string); exit (2);}static voidperror_with_exit (string) char const *string;{ int e = errno; fprintf (stderr, "%s: ", program_name); errno = e; perror (string); exit (2);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -