📄 patch.c
字号:
char rcsid[] = "$Header: patch.c,v 2.0.1.6 88/06/22 20:46:39 lwall Locked $";/* patch - a program to apply diffs to original files * * Copyright 1986, Larry Wall * * This program may be copied as long as you don't try to make any * money off of it, or pretend that you wrote it. * * $Log: patch.c,v $ * Revision 2.0.1.6 88/06/22 20:46:39 lwall * patch12: rindex() wasn't declared * * Revision 2.0.1.5 88/06/03 15:09:37 lwall * patch10: exit code improved. * patch10: better support for non-flexfilenames. * * Revision 2.0.1.4 87/02/16 14:00:04 lwall * Short replacement caused spurious "Out of sync" message. * * Revision 2.0.1.3 87/01/30 22:45:50 lwall * Improved diagnostic on sync error. * Moved do_ed_script() to pch.c. * * Revision 2.0.1.2 86/11/21 09:39:15 lwall * Fuzz factor caused offset of installed lines. * * Revision 2.0.1.1 86/10/29 13:10:22 lwall * Backwards search could terminate prematurely. * * Revision 2.0 86/09/17 15:37:32 lwall * Baseline for netwide release. * * Revision 1.5 86/08/01 20:53:24 lwall * Changed some %d's to %ld's. * Linted. * * Revision 1.4 86/08/01 19:17:29 lwall * Fixes for machines that can't vararg. * Added fuzz factor. * Generalized -p. * General cleanup. * * 85/08/15 van%ucbmonet@berkeley * Changes for 4.3bsd diff -c. * * Revision 1.3 85/03/26 15:07:43 lwall * Frozen. * * Revision 1.2.1.9 85/03/12 17:03:35 lwall * Changed pfp->_file to fileno(pfp). * * Revision 1.2.1.8 85/03/12 16:30:43 lwall * Check i_ptr and i_womp to make sure they aren't null before freeing. * Also allow ed output to be suppressed. * * Revision 1.2.1.7 85/03/12 15:56:13 lwall * Added -p option from jromine@uci-750a. * * Revision 1.2.1.6 85/03/12 12:12:51 lwall * Now checks for normalness of file to patch. * * Revision 1.2.1.5 85/03/12 11:52:12 lwall * Added -D (#ifdef) option from joe@fluke. * * Revision 1.2.1.4 84/12/06 11:14:15 lwall * Made smarter about SCCS subdirectories. * * Revision 1.2.1.3 84/12/05 11:18:43 lwall * Added -l switch to do loose string comparison. * * Revision 1.2.1.2 84/12/04 09:47:13 lwall * Failed hunk count not reset on multiple patch file. * * Revision 1.2.1.1 84/12/04 09:42:37 lwall * Branch for sdcrdcf changes. * * Revision 1.2 84/11/29 13:29:51 lwall * Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed * multiple calls to mktemp(). Will now work on machines that can only * read 32767 chars. Added -R option for diffs with new and old swapped. * Various cosmetic changes. * * Revision 1.1 84/11/09 17:03:58 lwall * Initial revision * *//* * 1992-01-15 * Modified by Saeko & Kouichi Hirabayashi to fit small memory (64K+64K) * system by adding "#if[n]def SMALL" parts. */#include "INTERN.h"#include "common.h"#include "EXTERN.h"#include "version.h"#include "util.h"#include "pch.h"#include "inp.h"/* procedures */_PROTOTYPE(int main , (int argc , char **argv ));_PROTOTYPE(void reinitialize_almost_everything , (void));_PROTOTYPE(void get_some_switches , (void));_PROTOTYPE(LINENUM locate_hunk , (LINENUM fuzz ));_PROTOTYPE(void abort_hunk , (void));_PROTOTYPE(void apply_hunk , (LINENUM where ));_PROTOTYPE(void init_output , (char *name ));_PROTOTYPE(void init_reject , (char *name ));_PROTOTYPE(void copy_till , (Reg1 LINENUM lastline ));_PROTOTYPE(void spew_output , (void));_PROTOTYPE(void dump_line , (LINENUM line ));_PROTOTYPE(bool patch_match , (LINENUM base , LINENUM offset , LINENUM fuzz ));_PROTOTYPE(bool similar , (Reg1 char *a , Reg2 char *b , Reg3 int len ));/* Apply a set of diffs as appropriate. */int main(argc,argv)int argc;char **argv;{ LINENUM where; LINENUM newwhere; LINENUM fuzz; LINENUM mymaxfuzz; int hunk = 0; int failed = 0; int failtotal = 0; int i; setbuf(stderr, serrbuf); for (i = 0; i<MAXFILEC; i++) filearg[i] = Nullch; Mktemp(TMPOUTNAME); Mktemp(TMPINNAME); Mktemp(TMPREJNAME); Mktemp(TMPPATNAME);#ifdef SMALL Mktemp(TMPSTRNAME);#endif /* parse switches */ Argc = argc; Argv = argv; get_some_switches(); /* make sure we clean up /tmp in case of disaster */ set_signals(0); for ( open_patch_file(filearg[1]); there_is_another_patch(); reinitialize_almost_everything() ) { /* for each patch in patch file */ if (outname == Nullch) outname = savestr(filearg[0]); /* initialize the patched file */ if (!skip_rest_of_patch) init_output(TMPOUTNAME); /* for ed script just up and do it and exit */ if (diff_type == ED_DIFF) { do_ed_script(); continue; } /* initialize reject file */ init_reject(TMPREJNAME); /* find out where all the lines are */ if (!skip_rest_of_patch) scan_input(filearg[0]); /* from here on, open no standard i/o files, because malloc */ /* might misfire and we can't catch it easily */ /* apply each hunk of patch */ hunk = 0; failed = 0; out_of_mem = FALSE; while (another_hunk()) { hunk++; fuzz = Nulline; mymaxfuzz = pch_context(); if (maxfuzz < mymaxfuzz) mymaxfuzz = maxfuzz; if (!skip_rest_of_patch) { do { where = locate_hunk(fuzz); if (hunk == 1 && where == Nulline && !force) { /* dwim for reversed patch? */ if (!pch_swap()) { if (fuzz == Nulline) say1("Not enough memory to try swapped hunk! Assuming unswapped.\n"); continue; } reverse = !reverse; where = locate_hunk(fuzz); /* try again */ if (where == Nulline) { /* didn't find it swapped */ if (!pch_swap()) /* put it back to normal */ fatal1("Lost hunk on alloc error!\n"); reverse = !reverse; } else if (noreverse) { if (!pch_swap()) /* put it back to normal */ fatal1("Lost hunk on alloc error!\n"); reverse = !reverse; say1("Ignoring previously applied (or reversed) patch.\n"); skip_rest_of_patch = TRUE; } else { ask3("%seversed (or previously applied) patch detected! %s -R? [y] ", reverse ? "R" : "Unr", reverse ? "Assume" : "Ignore"); if (*buf == 'n') { ask1("Apply anyway? [n] "); if (*buf != 'y') skip_rest_of_patch = TRUE; where = Nulline; reverse = !reverse; if (!pch_swap()) /* put it back to normal */ fatal1("Lost hunk on alloc error!\n"); } } } } while (!skip_rest_of_patch && where == Nulline && ++fuzz <= mymaxfuzz); if (skip_rest_of_patch) { /* just got decided */ Fclose(ofp); ofp = Nullfp; } } newwhere = pch_newfirst() + last_offset; if (skip_rest_of_patch) { abort_hunk(); failed++; if (verbose) say3("Hunk #%d ignored at %ld.\n", hunk, newwhere); } else if (where == Nulline) { abort_hunk(); failed++; if (verbose) say3("Hunk #%d failed at %ld.\n", hunk, newwhere); } else { apply_hunk(where); if (verbose) { say3("Hunk #%d succeeded at %ld", hunk, newwhere); if (fuzz) say2(" with fuzz %ld", fuzz); if (last_offset) say3(" (offset %ld line%s)", last_offset, last_offset==1L?"":"s"); say1(".\n"); } } } if (out_of_mem && using_plan_a) { Argc = Argc_last; Argv = Argv_last; say1("\n\nRan out of memory using Plan A--trying again...\n\n"); continue; } assert(hunk); /* finish spewing out the new file */ if (!skip_rest_of_patch) spew_output(); /* and put the output where desired */ ignore_signals(); if (!skip_rest_of_patch) { if (move_file(TMPOUTNAME, outname) < 0) { toutkeep = TRUE; chmod(TMPOUTNAME, filemode); } else chmod(outname, filemode); } Fclose(rejfp); rejfp = Nullfp; if (failed) { failtotal += failed; if (!*rejname) { Strcpy(rejname, outname);#ifndef FLEXFILENAMES { char *s = rindex(rejname,'/'); if (!s) s = rejname; if (strlen(s) > 13) if (s[12] == '.') /* try to preserve difference */ s[12] = s[13]; /* between .h, .c, .y, etc. */ s[13] = '\0'; }#endif Strcat(rejname, REJEXT); } if (skip_rest_of_patch) { say4("%d out of %d hunks ignored--saving rejects to %s\n", failed, hunk, rejname); } else { say4("%d out of %d hunks failed--saving rejects to %s\n", failed, hunk, rejname); } if (move_file(TMPREJNAME, rejname) < 0) trejkeep = TRUE; } set_signals(1); }#ifdef SMALL if (sfp != Nullfp) Fclose(sfp);#endif my_exit(failtotal);}/* Prepare to find the next patch to do in the patch file. */voidreinitialize_almost_everything(){ re_patch(); re_input(); input_lines = 0; last_frozen_line = 0; filec = 0; if (filearg[0] != Nullch && !out_of_mem) { free(filearg[0]); filearg[0] = Nullch; } if (outname != Nullch) { free(outname); outname = Nullch; } last_offset = 0; diff_type = 0; if (revision != Nullch) { free(revision); revision = Nullch; } reverse = FALSE; skip_rest_of_patch = FALSE; get_some_switches(); if (filec >= 2) fatal1("You may not change to a different patch file.\n");}/* Process switches and filenames up to next '+' or end of list. */voidget_some_switches(){ Reg1 char *s; rejname[0] = '\0'; Argc_last = Argc; Argv_last = Argv; if (!Argc) return; for (Argc--,Argv++; Argc; Argc--,Argv++) { s = Argv[0]; if (strEQ(s, "+")) { return; /* + will be skipped by for loop */ } if (*s != '-' || !s[1]) { if (filec == MAXFILEC) fatal1("Too many file arguments.\n"); filearg[filec++] = savestr(s); } else { switch (*++s) { case 'b': origext = savestr(Argv[1]); Argc--,Argv++; break; case 'B': origprae = savestr(Argv[1]); Argc--,Argv++; break; case 'c': diff_type = CONTEXT_DIFF; break; case 'd': if (!*++s) { Argc--,Argv++; s = Argv[0]; } if (chdir(s) < 0) fatal2("Can't cd to %s.\n", s); break; case 'D': do_defines = TRUE; if (!*++s) { Argc--,Argv++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -