📄 diff3.c
字号:
*set_length = line_ptr - *set_start; if (line_ptr < limit && *line_ptr == '\\') { if (edscript) fprintf (stderr, "%s:", program_name); else --*set_length; line_ptr++; do { if (edscript) putc (*line_ptr, stderr); } while (*line_ptr++ != '\n'); } return line_ptr;}/* Output a three way diff passed as a list of diff3_block's. The argument MAPPING is indexed by external file number (in the argument list) and contains the internal file number (from the diff passed). This is important because the user expects outputs in terms of the argument list number, and the diff passed may have been done slightly differently (if the last argument was "-", for example). REV_MAPPING is the inverse of MAPPING. */static voidoutput_diff3 (FILE *outputfile, struct diff3_block *diff, int const mapping[3], int const rev_mapping[3]){ int i; int oddoneout; char *cp; struct diff3_block *ptr; lin line; size_t length; int dontprint; static int skew_increment[3] = { 2, 3, 1 }; /* 0==>2==>1==>3 */ char const *line_prefix = initial_tab ? "\t" : " "; for (ptr = diff; ptr; ptr = D_NEXT (ptr)) { char x[2]; 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[ptr->correspond - 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]; lin lowt = D_LOWLINE (ptr, realfile); lin hight = D_HIGHLINE (ptr, realfile); long int llowt = lowt; long int lhight = hight; fprintf (outputfile, "%d:", i + 1); switch (lowt - hight) { case 1: fprintf (outputfile, "%lda\n", llowt - 1); break; case 0: fprintf (outputfile, "%ldc\n", llowt); break; default: fprintf (outputfile, "%ld,%ldc\n", llowt, lhight); 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\\ %s\n", _("No newline at end of file")); } } }}/* Output to OUTPUTFILE the lines of B taken from FILENUM. Double any initial '.'s; yield nonzero if any initial '.'s were doubled. */static booldotlines (FILE *outputfile, struct diff3_block *b, int filenum){ lin i; bool leading_dot = false; for (i = 0; i < D_NUMLINES (b, filenum); i++) { char *line = D_RELNUM (b, filenum, i); if (line[0] == '.') { leading_dot = true; fprintf (outputfile, "."); } fwrite (line, sizeof (char), D_RELLEN (b, filenum, i), outputfile); } return leading_dot;}/* Output to OUTPUTFILE a '.' line. If LEADING_DOT is true, also output a command that removes initial '.'s starting with line START and continuing for NUM lines. (START is long int, not lin, for convenience with printf %ld formats.) */static voidundotlines (FILE *outputfile, bool leading_dot, long int start, lin num){ fprintf (outputfile, ".\n"); if (leading_dot) { if (num == 1) fprintf (outputfile, "%lds/^\\.//\n", start); else fprintf (outputfile, "%ld,%lds/^\\.//\n", start, start + num - 1); }}/* Output a diff3 set of blocks as an ed script. This script applies the changes between file's 2 & 3 to file 1. Take the precise format of the ed script to be output from global variables set during options processing. Reverse the order of the set of diff3 blocks in DIFF; this gets around the problems involved with changing line numbers in an ed script. As in `output_diff3', 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. 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. Return 1 if conflicts were found. */static booloutput_diff3_edscript (FILE *outputfile, struct diff3_block *diff, int const mapping[3], int const rev_mapping[3], char const *file0, char const *file1, char const *file2){ bool leading_dot; bool conflicts_found = false; bool 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 : DIFF_1ST + rev_mapping[b->correspond - DIFF_1ST]); long int low0, high0; /* If we aren't supposed to do this output block, skip it. */ switch (type) { default: continue; case DIFF_2ND: if (!show_2nd) continue; conflict = true; break; case DIFF_3RD: if (overlap_only) continue; conflict = false; break; case DIFF_ALL: if (simple_only) continue; conflict = flagging; break; } low0 = D_LOWLINE (b, mapping[FILE0]); high0 = D_HIGHLINE (b, mapping[FILE0]); if (conflict) { conflicts_found = true; /* Mark end of conflict. */ fprintf (outputfile, "%lda\n", high0); leading_dot = false; 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, high0 + 2, (D_NUMLINES (b, mapping[FILE1]) + D_NUMLINES (b, mapping[FILE2]) + 1)); /* Mark start of conflict. */ fprintf (outputfile, "%lda\n<<<<<<< %s\n", low0 - 1, type == DIFF_ALL ? file0 : file1); leading_dot = false; if (type == DIFF_2ND) { /* Prepend lines from FILE1. */ leading_dot = dotlines (outputfile, b, mapping[FILE1]); fprintf (outputfile, "=======\n"); } undotlines (outputfile, leading_dot, low0 + 1, D_NUMLINES (b, mapping[FILE1])); } else if (D_NUMLINES (b, mapping[FILE2]) == 0) /* Write out a delete */ { if (low0 == high0) fprintf (outputfile, "%ldd\n", low0); else fprintf (outputfile, "%ld,%ldd\n", low0, high0); } else /* Write out an add or change */ { switch (high0 - low0) { case -1: fprintf (outputfile, "%lda\n", high0); break; case 0: fprintf (outputfile, "%ldc\n", high0); break; default: fprintf (outputfile, "%ld,%ldc\n", low0, high0); break; } undotlines (outputfile, dotlines (outputfile, b, mapping[FILE2]), low0, 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. Return 1 if conflicts were found. */static booloutput_diff3_merge (FILE *infile, FILE *outputfile, struct diff3_block *diff, int const mapping[3], int const rev_mapping[3], char const *file0, char const *file1, char const *file2){ int c; lin i; bool conflicts_found = false; bool conflict; struct diff3_block *b; lin linesread = 0; for (b = diff; b; b = b->next) { /* Must do mapping correctly. */ enum diff_type type = ((b->correspond == DIFF_ALL) ? DIFF_ALL : DIFF_1ST + rev_mapping[b->correspond - 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 = true; break; case DIFF_3RD: if (overlap_only) continue; conflict = false; 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 (_("read failed")); else if (feof (infile)) fatal ("input file shrank"); } putc (c, outputfile); } while (c != '\n'); if (conflict) { conflicts_found = true; 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 (_("read failed")); 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 (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 voidfatal (char const *msgid){ error (EXIT_TROUBLE, 0, "%s", _(msgid)); abort ();}static voidperror_with_exit (char const *string){ error (EXIT_TROUBLE, errno, "%s", string); abort ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -