📄 patch.c
字号:
return first_guess+offset; } if (0 < offset && offset <= max_neg_offset && patch_match (first_guess, -offset, prefix_fuzz, suffix_fuzz)) { if (debug & 1) say ("Offset changing from %s to %s\n", format_linenum (numbuf0, last_offset), format_linenum (numbuf1, last_offset - offset)); last_offset -= offset; return first_guess-offset; } } return 0;}/* We did not find the pattern, dump out the hunk so they can handle it. */static voidabort_hunk (void){ register LINENUM i; register LINENUM pat_end = pch_end (); /* add in last_offset to guess the same as the previous successful hunk */ LINENUM oldfirst = pch_first() + last_offset; LINENUM newfirst = pch_newfirst() + last_offset; LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1; LINENUM newlast = newfirst + pch_repl_lines() - 1; char const *stars = (int) NEW_CONTEXT_DIFF <= (int) diff_type ? " ****" : ""; char const *minuses = (int) NEW_CONTEXT_DIFF <= (int) diff_type ? " ----" : " -----"; fprintf(rejfp, "***************\n"); for (i=0; i<=pat_end; i++) { char numbuf0[LINENUM_LENGTH_BOUND + 1]; char numbuf1[LINENUM_LENGTH_BOUND + 1]; switch (pch_char(i)) { case '*': if (oldlast < oldfirst) fprintf(rejfp, "*** 0%s\n", stars); else if (oldlast == oldfirst) fprintf (rejfp, "*** %s%s\n", format_linenum (numbuf0, oldfirst), stars); else fprintf (rejfp, "*** %s,%s%s\n", format_linenum (numbuf0, oldfirst), format_linenum (numbuf1, oldlast), stars); break; case '=': if (newlast < newfirst) fprintf(rejfp, "--- 0%s\n", minuses); else if (newlast == newfirst) fprintf (rejfp, "--- %s%s\n", format_linenum (numbuf0, newfirst), minuses); else fprintf (rejfp, "--- %s,%s%s\n", format_linenum (numbuf0, newfirst), format_linenum (numbuf1, newlast), minuses); break; case ' ': case '-': case '+': case '!': fprintf (rejfp, "%c ", pch_char (i)); /* fall into */ case '\n': pch_write_line (i, rejfp); break; default: fatal ("fatal internal error in abort_hunk"); } if (ferror (rejfp)) write_fatal (); }}/* We found where to apply it (we hope), so do it. */static boolapply_hunk (struct outstate *outstate, LINENUM where){ register LINENUM old = 1; register LINENUM lastline = pch_ptrn_lines (); register LINENUM new = lastline+1; register enum {OUTSIDE, IN_IFNDEF, IN_IFDEF, IN_ELSE} def_state = OUTSIDE; register char const *R_do_defines = do_defines; register LINENUM pat_end = pch_end (); register FILE *fp = outstate->ofp; where--; while (pch_char(new) == '=' || pch_char(new) == '\n') new++; while (old <= lastline) { if (pch_char(old) == '-') { assert (outstate->after_newline); if (! copy_till (outstate, where + old - 1)) return false; if (R_do_defines) { if (def_state == OUTSIDE) { fprintf (fp, outstate->after_newline + not_defined, R_do_defines); def_state = IN_IFNDEF; } else if (def_state == IN_IFDEF) { fprintf (fp, outstate->after_newline + else_defined); def_state = IN_ELSE; } if (ferror (fp)) write_fatal (); outstate->after_newline = pch_write_line (old, fp); outstate->zero_output = false; } last_frozen_line++; old++; } else if (new > pat_end) { break; } else if (pch_char(new) == '+') { if (! copy_till (outstate, where + old - 1)) return false; if (R_do_defines) { if (def_state == IN_IFNDEF) { fprintf (fp, outstate->after_newline + else_defined); def_state = IN_ELSE; } else if (def_state == OUTSIDE) { fprintf (fp, outstate->after_newline + if_defined, R_do_defines); def_state = IN_IFDEF; } if (ferror (fp)) write_fatal (); } outstate->after_newline = pch_write_line (new, fp); outstate->zero_output = false; new++; } else if (pch_char(new) != pch_char(old)) { char numbuf0[LINENUM_LENGTH_BOUND + 1]; char numbuf1[LINENUM_LENGTH_BOUND + 1]; if (debug & 1) say ("oldchar = '%c', newchar = '%c'\n", pch_char (old), pch_char (new)); fatal ("Out-of-sync patch, lines %s,%s -- mangled text or line numbers, maybe?", format_linenum (numbuf0, pch_hunk_beg() + old), format_linenum (numbuf1, pch_hunk_beg() + new)); } else if (pch_char(new) == '!') { assert (outstate->after_newline); if (! copy_till (outstate, where + old - 1)) return false; assert (outstate->after_newline); if (R_do_defines) { fprintf (fp, 1 + not_defined, R_do_defines); if (ferror (fp)) write_fatal (); def_state = IN_IFNDEF; } do { if (R_do_defines) { outstate->after_newline = pch_write_line (old, fp); } last_frozen_line++; old++; } while (pch_char (old) == '!'); if (R_do_defines) { fprintf (fp, outstate->after_newline + else_defined); if (ferror (fp)) write_fatal (); def_state = IN_ELSE; } do { outstate->after_newline = pch_write_line (new, fp); new++; } while (pch_char (new) == '!'); outstate->zero_output = false; } else { assert(pch_char(new) == ' '); old++; new++; if (R_do_defines && def_state != OUTSIDE) { fprintf (fp, outstate->after_newline + end_defined); if (ferror (fp)) write_fatal (); outstate->after_newline = true; def_state = OUTSIDE; } } } if (new <= pat_end && pch_char(new) == '+') { if (! copy_till (outstate, where + old - 1)) return false; if (R_do_defines) { if (def_state == OUTSIDE) { fprintf (fp, outstate->after_newline + if_defined, R_do_defines); def_state = IN_IFDEF; } else if (def_state == IN_IFNDEF) { fprintf (fp, outstate->after_newline + else_defined); def_state = IN_ELSE; } if (ferror (fp)) write_fatal (); outstate->zero_output = false; } do { if (! outstate->after_newline && putc ('\n', fp) == EOF) write_fatal (); outstate->after_newline = pch_write_line (new, fp); outstate->zero_output = false; new++; } while (new <= pat_end && pch_char (new) == '+'); } if (R_do_defines && def_state != OUTSIDE) { fprintf (fp, outstate->after_newline + end_defined); if (ferror (fp)) write_fatal (); outstate->after_newline = true; } return true;}/* Create an output file. */static FILE *create_output_file (char const *name, int open_flags){ int fd = create_file (name, O_WRONLY | binary_transput | open_flags, instat.st_mode); FILE *f = fdopen (fd, binary_transput ? "wb" : "w"); if (! f) pfatal ("Can't create file %s", quotearg (name)); return f;}/* Open the new file. */static voidinit_output (char const *name, int open_flags, struct outstate *outstate){ outstate->ofp = name ? create_output_file (name, open_flags) : (FILE *) 0; outstate->after_newline = true; outstate->zero_output = true;}/* Open a file to put hunks we can't locate. */static voidinit_reject (void){ int exclusive = TMPREJNAME_needs_removal ? 0 : O_EXCL; TMPREJNAME_needs_removal = 1; rejfp = create_output_file (TMPREJNAME, exclusive);}/* Copy input file to output, up to wherever hunk is to be applied. */static boolcopy_till (register struct outstate *outstate, register LINENUM lastline){ register LINENUM R_last_frozen_line = last_frozen_line; register FILE *fp = outstate->ofp; register char const *s; size_t size; if (R_last_frozen_line > lastline) { say ("misordered hunks! output would be garbled\n"); return false; } while (R_last_frozen_line < lastline) { s = ifetch (++R_last_frozen_line, false, &size); if (size) { if ((! outstate->after_newline && putc ('\n', fp) == EOF) || ! fwrite (s, sizeof *s, size, fp)) write_fatal (); outstate->after_newline = s[size - 1] == '\n'; outstate->zero_output = false; } } last_frozen_line = R_last_frozen_line; return true;}/* Finish copying the input file to the output file. */static boolspew_output (struct outstate *outstate){ if (debug & 256) { char numbuf0[LINENUM_LENGTH_BOUND + 1]; char numbuf1[LINENUM_LENGTH_BOUND + 1]; say ("il=%s lfl=%s\n", format_linenum (numbuf0, input_lines), format_linenum (numbuf1, last_frozen_line)); } if (last_frozen_line < input_lines) if (! copy_till (outstate, input_lines)) return false; if (outstate->ofp && ! outfile) { if (fclose (outstate->ofp) != 0) write_fatal (); outstate->ofp = 0; } return true;}/* Does the patch pattern match at line base+offset? */static boolpatch_match (LINENUM base, LINENUM offset, LINENUM prefix_fuzz, LINENUM suffix_fuzz){ register LINENUM pline = 1 + prefix_fuzz; register LINENUM iline; register LINENUM pat_lines = pch_ptrn_lines () - suffix_fuzz; size_t size; register char const *p; for (iline=base+offset+prefix_fuzz; pline <= pat_lines; pline++,iline++) { p = ifetch (iline, offset >= 0, &size); if (canonicalize) { if (!similar(p, size, pfetch(pline), pch_line_len(pline) )) return false; } else if (size != pch_line_len (pline) || memcmp (p, pfetch (pline), size) != 0) return false; } return true;}/* Do two lines match with canonicalized white space? */static boolsimilar (register char const *a, register size_t alen, register char const *b, register size_t blen){ /* Ignore presence or absence of trailing newlines. */ alen -= alen && a[alen - 1] == '\n'; blen -= blen && b[blen - 1] == '\n'; for (;;) { if (!blen || (*b == ' ' || *b == '\t')) { while (blen && (*b == ' ' || *b == '\t')) b++, blen--; if (alen) { if (!(*a == ' ' || *a == '\t')) return false; do a++, alen--; while (alen && (*a == ' ' || *a == '\t')); } if (!alen || !blen) return alen == blen; } else if (!alen || *a++ != *b++) return false; else alen--, blen--; }}/* Make a temporary file. */#if HAVE_MKTEMP && ! HAVE_DECL_MKTEMP && ! defined mktempchar *mktemp (char *);#endif#ifndef TMPDIR#define TMPDIR "/tmp"#endifstatic char const *make_temp (char letter){ char *r;#if HAVE_MKTEMP char const *tmpdir = getenv ("TMPDIR"); /* Unix tradition */ if (!tmpdir) tmpdir = getenv ("TMP"); /* DOS tradition */ if (!tmpdir) tmpdir = getenv ("TEMP"); /* another DOS tradition */ if (!tmpdir) tmpdir = TMPDIR; r = xmalloc (strlen (tmpdir) + 10); sprintf (r, "%s/p%cXXXXXX", tmpdir, letter); /* It is OK to use mktemp here, since the rest of the code always opens temp files with O_EXCL. It might be better to use mkstemp to avoid some DoS problems, but simply substituting mkstemp for mktemp here will not fix the DoS problems; a more extensive change would be needed. */ mktemp (r); if (!*r) pfatal ("mktemp");#else r = xmalloc (L_tmpnam); if (! (tmpnam (r) == r && *r)) pfatal ("tmpnam");#endif return r;}/* Fatal exit with cleanup. */voidfatal_exit (int sig){ cleanup (); if (sig) exit_with_signal (sig); exit (2);}static voidremove_if_needed (char const *name, int volatile *needs_removal){ if (*needs_removal) { unlink (name); *needs_removal = 0; }}static voidcleanup (void){ remove_if_needed (TMPINNAME, &TMPINNAME_needs_removal); remove_if_needed (TMPOUTNAME, &TMPOUTNAME_needs_removal); remove_if_needed (TMPPATNAME, &TMPPATNAME_needs_removal); remove_if_needed (TMPREJNAME, &TMPREJNAME_needs_removal);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -