patch.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. /* patch - a program to apply diffs to original files */
  2. /* $Id: patch.c,v 1.23 1997/07/05 10:32:23 eggert Exp $ */
  3. /*
  4. Copyright 1984, 1985, 1986, 1987, 1988 Larry Wall
  5. Copyright 1989, 1990, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; see the file COPYING.
  16. If not, write to the Free Software Foundation,
  17. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. */
  19. #define XTERN
  20. #include <common.h>
  21. #undef XTERN
  22. #define XTERN extern
  23. #include <argmatch.h>
  24. #include <backupfile.h>
  25. #include <getopt.h>
  26. #include <inp.h>
  27. #include <pch.h>
  28. #include <util.h>
  29. #include <version.h>
  30. #if HAVE_UTIME_H
  31. # include <utime.h>
  32. #endif
  33. /* Some nonstandard hosts don't declare this structure even in <utime.h>. */
  34. #if ! HAVE_STRUCT_UTIMBUF
  35. struct utimbuf
  36. {
  37. time_t actime;
  38. time_t modtime;
  39. };
  40. #endif
  41. /* Output stream state. */
  42. struct outstate
  43. {
  44. FILE *ofp;
  45. int after_newline;
  46. int zero_output;
  47. };
  48. /* procedures */
  49. static FILE *create_output_file PARAMS ((char const *));
  50. static LINENUM locate_hunk PARAMS ((LINENUM));
  51. static bool apply_hunk PARAMS ((struct outstate *, LINENUM));
  52. static bool copy_till PARAMS ((struct outstate *, LINENUM));
  53. static bool patch_match PARAMS ((LINENUM, LINENUM, LINENUM, LINENUM));
  54. static bool similar PARAMS ((char const *, size_t, char const *, size_t));
  55. static bool spew_output PARAMS ((struct outstate *));
  56. static char const *make_temp PARAMS ((int));
  57. static int numeric_string PARAMS ((char const *, int, char const *));
  58. static void abort_hunk PARAMS ((void));
  59. static void cleanup PARAMS ((void));
  60. static void get_some_switches PARAMS ((void));
  61. static void init_output PARAMS ((char const *, struct outstate *));
  62. static void init_reject PARAMS ((char const *));
  63. static void reinitialize_almost_everything PARAMS ((void));
  64. static void usage PARAMS ((FILE *, int)) __attribute__((noreturn));
  65. static int make_backups;
  66. static int backup_if_mismatch;
  67. static char const *version_control;
  68. static int remove_empty_files;
  69. /* TRUE if -R was specified on command line. */
  70. static int reverse_flag_specified;
  71. /* how many input lines have been irretractably output */
  72. static LINENUM last_frozen_line;
  73. static char const *do_defines; /* symbol to patch using ifdef, ifndef, etc. */
  74. static char const if_defined[] = "\n#ifdef %s\n";
  75. static char const not_defined[] = "#ifndef %s\n";
  76. static char const else_defined[] = "\n#else\n";
  77. static char const end_defined[] = "\n#endif /* %s */\n";
  78. static int Argc;
  79. static char * const *Argv;
  80. static FILE *rejfp; /* reject file pointer */
  81. static char const *patchname;
  82. static char *rejname;
  83. static char const * volatile TMPREJNAME;
  84. static LINENUM last_offset;
  85. static LINENUM maxfuzz = 2;
  86. static char serrbuf[BUFSIZ];
  87. char const program_name[] = "patch";
  88. /* Apply a set of diffs as appropriate. */
  89. int main PARAMS ((int, char **));
  90. int
  91. main(argc,argv)
  92. int argc;
  93. char **argv;
  94. {
  95. char const *val;
  96. bool somefailed = FALSE;
  97. struct outstate outstate;
  98. init_time ();
  99. setbuf(stderr, serrbuf);
  100. bufsize = 8 * 1024;
  101. buf = xmalloc (bufsize);
  102. strippath = INT_MAX;
  103. posixly_correct = getenv ("POSIXLY_CORRECT") != 0;
  104. backup_if_mismatch = ! posixly_correct;
  105. patch_get = ((val = getenv ("PATCH_GET"))
  106. ? numeric_string (val, 1, "PATCH_GET value")
  107. : posixly_correct - 1);
  108. {
  109. char const *v = getenv ("SIMPLE_BACKUP_SUFFIX");
  110. if (v && *v)
  111. simple_backup_suffix = v;
  112. }
  113. version_control = getenv ("PATCH_VERSION_CONTROL");
  114. if (! version_control)
  115. version_control = getenv ("VERSION_CONTROL");
  116. /* Cons up the names of the global temporary files.
  117. Do this before `cleanup' can possibly be called (e.g. by `pfatal'). */
  118. TMPOUTNAME = make_temp ('o');
  119. TMPINNAME = make_temp ('i');
  120. TMPREJNAME = make_temp ('r');
  121. TMPPATNAME = make_temp ('p');
  122. /* parse switches */
  123. Argc = argc;
  124. Argv = argv;
  125. get_some_switches();
  126. if (make_backups | backup_if_mismatch)
  127. backup_type = get_version (version_control);
  128. init_output (outfile, &outstate);
  129. /* Make sure we clean up in case of disaster. */
  130. set_signals(0);
  131. for (
  132. open_patch_file (patchname);
  133. there_is_another_patch();
  134. reinitialize_almost_everything()
  135. ) { /* for each patch in patch file */
  136. int hunk = 0;
  137. int failed = 0;
  138. int mismatch = 0;
  139. char *outname = outfile ? outfile : inname;
  140. if (!skip_rest_of_patch)
  141. get_input_file (inname, outname);
  142. if (diff_type == ED_DIFF) {
  143. outstate.zero_output = 0;
  144. if (! dry_run)
  145. {
  146. do_ed_script (outstate.ofp);
  147. if (! outfile)
  148. {
  149. struct stat statbuf;
  150. if (stat (TMPOUTNAME, &statbuf) != 0)
  151. pfatal ("%s", TMPOUTNAME);
  152. outstate.zero_output = statbuf.st_size == 0;
  153. }
  154. }
  155. } else {
  156. int got_hunk;
  157. int apply_anyway = 0;
  158. /* initialize the patched file */
  159. if (! skip_rest_of_patch && ! outfile)
  160. init_output (TMPOUTNAME, &outstate);
  161. /* initialize reject file */
  162. init_reject(TMPREJNAME);
  163. /* find out where all the lines are */
  164. if (!skip_rest_of_patch)
  165. scan_input (inname);
  166. /* from here on, open no standard i/o files, because malloc */
  167. /* might misfire and we can't catch it easily */
  168. /* apply each hunk of patch */
  169. while (0 < (got_hunk = another_hunk (diff_type, reverse))) {
  170. LINENUM where = 0; /* Pacify `gcc -Wall'. */
  171. LINENUM newwhere;
  172. LINENUM fuzz = 0;
  173. LINENUM prefix_context = pch_prefix_context ();
  174. LINENUM suffix_context = pch_suffix_context ();
  175. LINENUM context = (prefix_context < suffix_context
  176. ? suffix_context : prefix_context);
  177. LINENUM mymaxfuzz = (maxfuzz < context ? maxfuzz : context);
  178. hunk++;
  179. if (!skip_rest_of_patch) {
  180. do {
  181. where = locate_hunk(fuzz);
  182. if (! where || fuzz || last_offset)
  183. mismatch = 1;
  184. if (hunk == 1 && ! where && ! (force | apply_anyway)
  185. && reverse == reverse_flag_specified) {
  186. /* dwim for reversed patch? */
  187. if (!pch_swap()) {
  188. say (
  189. "Not enough memory to try swapped hunk! Assuming unswapped.\n");
  190. continue;
  191. }
  192. /* Try again. */
  193. where = locate_hunk (fuzz);
  194. if (where
  195. && (ok_to_reverse
  196. ("%s patch detected!",
  197. (reverse
  198. ? "Unreversed"
  199. : "Reversed (or previously applied)"))))
  200. reverse ^= 1;
  201. else
  202. {
  203. /* Put it back to normal. */
  204. if (! pch_swap ())
  205. fatal ("lost hunk on alloc error!");
  206. if (where)
  207. {
  208. apply_anyway = 1;
  209. fuzz--; /* Undo `++fuzz' below. */
  210. where = 0;
  211. }
  212. }
  213. }
  214. } while (!skip_rest_of_patch && !where
  215. && ++fuzz <= mymaxfuzz);
  216. if (skip_rest_of_patch) { /* just got decided */
  217. if (outstate.ofp && ! outfile)
  218. {
  219. fclose (outstate.ofp);
  220. outstate.ofp = 0;
  221. }
  222. }
  223. }
  224. newwhere = pch_newfirst() + last_offset;
  225. if (skip_rest_of_patch) {
  226. abort_hunk();
  227. failed++;
  228. if (verbosity == VERBOSE)
  229. say ("Hunk #%d ignored at %ld.\n", hunk, newwhere);
  230. }
  231. else if (!where
  232. || (where == 1 && pch_says_nonexistent (reverse)
  233. && instat.st_size)) {
  234. if (where)
  235. say ("Patch attempted to create file `%s', which already exists.\n", inname);
  236. abort_hunk();
  237. failed++;
  238. if (verbosity != SILENT)
  239. say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
  240. }
  241. else if (! apply_hunk (&outstate, where)) {
  242. abort_hunk ();
  243. failed++;
  244. if (verbosity != SILENT)
  245. say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
  246. } else {
  247. if (verbosity == VERBOSE
  248. || (verbosity != SILENT && (fuzz || last_offset))) {
  249. say ("Hunk #%d succeeded at %ld", hunk, newwhere);
  250. if (fuzz)
  251. say (" with fuzz %ld", fuzz);
  252. if (last_offset)
  253. say (" (offset %ld line%s)",
  254. last_offset, last_offset==1?"":"s");
  255. say (".\n");
  256. }
  257. }
  258. }
  259. if (got_hunk < 0 && using_plan_a) {
  260. if (outfile)
  261. fatal ("out of memory using Plan A");
  262. say ("\n\nRan out of memory using Plan A -- trying again...\n\n");
  263. if (outstate.ofp)
  264. {
  265. fclose (outstate.ofp);
  266. outstate.ofp = 0;
  267. }
  268. fclose (rejfp);
  269. continue;
  270. }
  271. /* finish spewing out the new file */
  272. if (!skip_rest_of_patch)
  273. {
  274. assert (hunk);
  275. if (! spew_output (&outstate))
  276. {
  277. say ("Skipping patch.\n");
  278. skip_rest_of_patch = TRUE;
  279. }
  280. }
  281. }
  282. /* and put the output where desired */
  283. ignore_signals ();
  284. if (! skip_rest_of_patch && ! outfile) {
  285. if (outstate.zero_output
  286. && (remove_empty_files
  287. || (pch_says_nonexistent (reverse ^ 1) == 2
  288. && ! posixly_correct)))
  289. {
  290. if (verbosity == VERBOSE)
  291. say ("Removing file `%s'%s.\n", outname,
  292. dry_run ? " and any empty ancestor directories" : "");
  293. if (! dry_run)
  294. {
  295. move_file ((char *) 0, outname, (mode_t) 0,
  296. (make_backups
  297. || (backup_if_mismatch && (mismatch | failed))));
  298. removedirs (outname);
  299. }
  300. }
  301. else
  302. {
  303. if (! outstate.zero_output
  304. && pch_says_nonexistent (reverse ^ 1))
  305. {
  306. mismatch = 1;
  307. if (verbosity != SILENT)
  308. say ("File `%s' is not empty after patch, as expected.\n",
  309. outname);
  310. }
  311. if (! dry_run)
  312. {
  313. time_t t;
  314. move_file (TMPOUTNAME, outname, instat.st_mode,
  315. (make_backups
  316. || (backup_if_mismatch && (mismatch | failed))));
  317. if ((set_time | set_utc)
  318. && (t = pch_timestamp (reverse ^ 1)) != (time_t) -1)
  319. {
  320. struct utimbuf utimbuf;
  321. utimbuf.actime = utimbuf.modtime = t;
  322. if (! force && ! inerrno
  323. && ! pch_says_nonexistent (reverse)
  324. && (t = pch_timestamp (reverse)) != (time_t) -1
  325. && t != instat.st_mtime)
  326. say ("not setting time of file `%s' (time mismatch)\n",
  327. outname);
  328. else if (! force && (mismatch | failed))
  329. say ("not setting time of file `%s' (contents mismatch)\n",
  330. outname);
  331. else if (utime (outname, &utimbuf) != 0)
  332. pfatal ("can't set timestamp on file `%s'", outname);
  333. }
  334. if (! inerrno && chmod (outname, instat.st_mode) != 0)
  335. pfatal ("can't set permissions on file `%s'", outname);
  336. }
  337. }
  338. }
  339. if (diff_type != ED_DIFF) {
  340. if (fclose (rejfp) != 0)
  341. write_fatal ();
  342. if (failed) {
  343. somefailed = TRUE;
  344. say ("%d out of %d hunk%s %s", failed, hunk, "s" + (hunk == 1),
  345. skip_rest_of_patch ? "ignored" : "FAILED");
  346. if (outname) {
  347. char *rej = rejname;
  348. if (!rejname) {
  349. rej = xmalloc (strlen (outname) + 5);
  350. strcpy (rej, outname);
  351. addext (rej, ".rej", '#');
  352. }
  353. say (" -- saving rejects to %s", rej);
  354. if (! dry_run)
  355. {
  356. move_file (TMPREJNAME, rej, instat.st_mode, FALSE);
  357. if (! inerrno
  358. && (chmod (rej, (instat.st_mode
  359. & ~(S_IXUSR|S_IXGRP|S_IXOTH)))
  360. != 0))
  361. pfatal ("can't set permissions on file `%s'", rej);
  362. }
  363. if (!rejname)
  364. free (rej);
  365. }
  366. say ("\n");
  367. }
  368. }
  369. set_signals (1);
  370. }
  371. if (outstate.ofp && (ferror (outstate.ofp) || fclose (outstate.ofp) != 0))
  372. write_fatal ();
  373. cleanup ();
  374. if (somefailed)
  375. exit (1);
  376. return 0;
  377. }
  378. /* Prepare to find the next patch to do in the patch file. */
  379. static void
  380. reinitialize_almost_everything()
  381. {
  382. re_patch();
  383. re_input();
  384. input_lines = 0;
  385. last_frozen_line = 0;
  386. if (inname) {
  387. free (inname);
  388. inname = 0;
  389. }
  390. last_offset = 0;
  391. diff_type = NO_DIFF;
  392. if (revision) {
  393. free(revision);
  394. revision = 0;
  395. }
  396. reverse = reverse_flag_specified;
  397. skip_rest_of_patch = FALSE;
  398. }
  399. static char const shortopts[] = "bB:cd:D:eEfF:g:i:lnNo:p:r:RstTuvV:x:Y:z:Z";
  400. static struct option const longopts[] =
  401. {
  402. {"backup", no_argument, NULL, 'b'},
  403. {"prefix", required_argument, NULL, 'B'},
  404. {"context", no_argument, NULL, 'c'},
  405. {"directory", required_argument, NULL, 'd'},
  406. {"ifdef", required_argument, NULL, 'D'},
  407. {"ed", no_argument, NULL, 'e'},
  408. {"remove-empty-files", no_argument, NULL, 'E'},
  409. {"force", no_argument, NULL, 'f'},
  410. {"fuzz", required_argument, NULL, 'F'},
  411. {"get", no_argument, NULL, 'g'},
  412. {"input", required_argument, NULL, 'i'},
  413. {"ignore-whitespace", no_argument, NULL, 'l'},
  414. {"normal", no_argument, NULL, 'n'},
  415. {"forward", no_argument, NULL, 'N'},
  416. {"output", required_argument, NULL, 'o'},
  417. {"strip", required_argument, NULL, 'p'},
  418. {"reject-file", required_argument, NULL, 'r'},
  419. {"reverse", no_argument, NULL, 'R'},
  420. {"quiet", no_argument, NULL, 's'},
  421. {"silent", no_argument, NULL, 's'},
  422. {"batch", no_argument, NULL, 't'},
  423. {"set-time", no_argument, NULL, 'T'},
  424. {"unified", no_argument, NULL, 'u'},
  425. {"version", no_argument, NULL, 'v'},
  426. {"version-control", required_argument, NULL, 'V'},
  427. {"debug", required_argument, NULL, 'x'},
  428. {"basename-prefix", required_argument, NULL, 'Y'},
  429. {"suffix", required_argument, NULL, 'z'},
  430. {"set-utc", no_argument, NULL, 'Z'},
  431. {"dry-run", no_argument, NULL, 129},
  432. {"verbose", no_argument, NULL, 130},
  433. {"binary", no_argument, NULL, 131},
  434. {"help", no_argument, NULL, 132},
  435. {"backup-if-mismatch", no_argument, NULL, 133},
  436. {"no-backup-if-mismatch", no_argument, NULL, 134},
  437. {NULL, no_argument, NULL, 0}
  438. };
  439. static char const *const option_help[] =
  440. {
  441. "Input options:",
  442. "",
  443. " -p NUM --strip=NUM Strip NUM leading components from file names.",
  444. " -F LINES --fuzz LINES Set the fuzz factor to LINES for inexact matching.",
  445. " -l --ignore-whitespace Ignore white space changes between patch and input.",
  446. "",
  447. " -c --context Interpret the patch as a context difference.",
  448. " -e --ed Interpret the patch as an ed script.",
  449. " -n --normal Interpret the patch as a normal difference.",
  450. " -u --unified Interpret the patch as a unified difference.",
  451. "",
  452. " -N --forward Ignore patches that appear to be reversed or already applied.",
  453. " -R --reverse Assume patches were created with old and new files swapped.",
  454. "",
  455. " -i PATCHFILE --input=PATCHFILE Read patch from PATCHFILE instead of stdin.",
  456. "",
  457. "Output options:",
  458. "",
  459. " -o FILE --output=FILE Output patched files to FILE.",
  460. " -r FILE --reject-file=FILE Output rejects to FILE.",
  461. "",
  462. " -D NAME --ifdef=NAME Make merged if-then-else output using NAME.",
  463. " -E --remove-empty-files Remove output files that are empty after patching.",
  464. "",
  465. " -Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).",
  466. " -T --set-time Likewise, assuming local time.",
  467. "",
  468. "Backup and version control options:",
  469. "",
  470. " -b --backup Back up the original contents of each file.",
  471. " --backup-if-mismatch Back up if the patch does not match exactly.",
  472. " --no-backup-if-mismatch Back up mismatches only if otherwise requested.",
  473. "",
  474. " -V STYLE --version-control=STYLE Use STYLE version control.",
  475. " STYLE is either 'simple', 'numbered', or 'existing'.",
  476. " -B PREFIX --prefix=PREFIX Prepend PREFIX to backup file names.",
  477. " -Y PREFIX --basename-prefix=PREFIX Prepend PREFIX to backup file basenames.",
  478. " -z SUFFIX --suffix=SUFFIX Append SUFFIX to backup file names.",
  479. "",
  480. " -g NUM --get=NUM Get files from RCS or SCCS if positive; ask if negative.",
  481. "",
  482. "Miscellaneous options:",
  483. "",
  484. " -t --batch Ask no questions; skip bad-Prereq patches; assume reversed.",
  485. " -f --force Like -t, but ignore bad-Prereq patches, and assume unreversed.",
  486. " -s --quiet --silent Work silently unless an error occurs.",
  487. " --verbose Output extra information about the work being done.",
  488. " --dry-run Do not actually change any files; just print what would happen.",
  489. "",
  490. " -d DIR --directory=DIR Change the working directory to DIR first.",
  491. #if HAVE_SETMODE
  492. " --binary Read and write data in binary mode.",
  493. #else
  494. " --binary Read and write data in binary mode (no effect on this platform).",
  495. #endif
  496. "",
  497. " -v --version Output version info.",
  498. " --help Output this help.",
  499. "",
  500. "Report bugs to <bug-gnu-utils@prep.ai.mit.edu>.",
  501. 0
  502. };
  503. static void
  504. usage (stream, status)
  505. FILE *stream;
  506. int status;
  507. {
  508. char const * const *p;
  509. if (status != 0)
  510. {
  511. fprintf (stream, "%s: Try `%s --help' for more information.\n",
  512. program_name, Argv[0]);
  513. }
  514. else
  515. {
  516. fprintf (stream, "Usage: %s [OPTION]... [ORIGFILE [PATCHFILE]]\n\n",
  517. Argv[0]);
  518. for (p = option_help; *p; p++)
  519. fprintf (stream, "%s\n", *p);
  520. }
  521. exit (status);
  522. }
  523. /* Process switches and filenames. */
  524. static void
  525. get_some_switches()
  526. {
  527. register int optc;
  528. if (rejname)
  529. free (rejname);
  530. rejname = 0;
  531. if (optind == Argc)
  532. return;
  533. while ((optc = getopt_long (Argc, Argv, shortopts, longopts, (int *) 0))
  534. != -1) {
  535. switch (optc) {
  536. case 'b':
  537. make_backups = 1;
  538. /* Special hack for backward compatibility with CVS 1.9.
  539. If the last 4 args are `-b SUFFIX ORIGFILE PATCHFILE',
  540. treat `-b' as if it were `-b -z'. */
  541. if (Argc - optind == 3
  542. && strcmp (Argv[optind - 1], "-b") == 0
  543. && ! (Argv[optind + 0][0] == '-' && Argv[optind + 0][1])
  544. && ! (Argv[optind + 1][0] == '-' && Argv[optind + 1][1])
  545. && ! (Argv[optind + 2][0] == '-' && Argv[optind + 2][1]))
  546. {
  547. optarg = Argv[optind++];
  548. if (verbosity != SILENT)
  549. say ("warning: the `-b %s' option is obsolete; use `-b -z %s' instead\n",
  550. optarg, optarg);
  551. goto case_z;
  552. }
  553. break;
  554. case 'B':
  555. if (!*optarg)
  556. fatal ("backup prefix is empty");
  557. origprae = savestr (optarg);
  558. break;
  559. case 'c':
  560. diff_type = CONTEXT_DIFF;
  561. break;
  562. case 'd':
  563. if (chdir(optarg) < 0)
  564. pfatal ("can't change directory to `%s'", optarg);
  565. break;
  566. case 'D':
  567. do_defines = savestr (optarg);
  568. break;
  569. case 'e':
  570. diff_type = ED_DIFF;
  571. break;
  572. case 'E':
  573. remove_empty_files = TRUE;
  574. break;
  575. case 'f':
  576. force = TRUE;
  577. break;
  578. case 'F':
  579. maxfuzz = numeric_string (optarg, 0, "fuzz factor");
  580. break;
  581. case 'g':
  582. patch_get = numeric_string (optarg, 1, "get option value");
  583. break;
  584. case 'i':
  585. patchname = savestr (optarg);
  586. break;
  587. case 'l':
  588. canonicalize = TRUE;
  589. break;
  590. case 'n':
  591. diff_type = NORMAL_DIFF;
  592. break;
  593. case 'N':
  594. noreverse = TRUE;
  595. break;
  596. case 'o':
  597. if (strcmp (optarg, "-") == 0)
  598. fatal ("can't output patches to standard output");
  599. outfile = savestr (optarg);
  600. break;
  601. case 'p':
  602. strippath = numeric_string (optarg, 0, "strip count");
  603. break;
  604. case 'r':
  605. rejname = savestr (optarg);
  606. break;
  607. case 'R':
  608. reverse = 1;
  609. reverse_flag_specified = 1;
  610. break;
  611. case 's':
  612. verbosity = SILENT;
  613. break;
  614. case 't':
  615. batch = TRUE;
  616. break;
  617. case 'T':
  618. set_time = 1;
  619. break;
  620. case 'u':
  621. diff_type = UNI_DIFF;
  622. break;
  623. case 'v':
  624. version();
  625. exit (0);
  626. break;
  627. case 'V':
  628. version_control = optarg;
  629. break;
  630. #if DEBUGGING
  631. case 'x':
  632. debug = numeric_string (optarg, 1, "debugging option");
  633. break;
  634. #endif
  635. case 'Y':
  636. if (!*optarg)
  637. fatal ("backup basename prefix is empty");
  638. origbase = savestr (optarg);
  639. break;
  640. case 'z':
  641. case_z:
  642. if (!*optarg)
  643. fatal ("backup suffix is empty");
  644. simple_backup_suffix = savestr (optarg);
  645. break;
  646. case 'Z':
  647. set_utc = 1;
  648. break;
  649. case 129:
  650. dry_run = TRUE;
  651. break;
  652. case 130:
  653. verbosity = VERBOSE;
  654. break;
  655. case 131:
  656. #if HAVE_SETMODE
  657. binary_transput = O_BINARY;
  658. #endif
  659. break;
  660. case 132:
  661. usage (stdout, 0);
  662. case 133:
  663. backup_if_mismatch = 1;
  664. break;
  665. case 134:
  666. backup_if_mismatch = 0;
  667. break;
  668. default:
  669. usage (stderr, 2);
  670. }
  671. }
  672. /* Process any filename args. */
  673. if (optind < Argc)
  674. {
  675. inname = savestr (Argv[optind++]);
  676. invc = -1;
  677. if (optind < Argc)
  678. {
  679. patchname = savestr (Argv[optind++]);
  680. if (optind < Argc)
  681. {
  682. fprintf (stderr, "%s: extra operand `%s'\n",
  683. program_name, Argv[optind]);
  684. usage (stderr, 2);
  685. }
  686. }
  687. }
  688. }
  689. /* Handle STRING (possibly negative if NEGATIVE_ALLOWED is nonzero)
  690. of type ARGTYPE_MSGID by converting it to an integer,
  691. returning the result. */
  692. static int
  693. numeric_string (string, negative_allowed, argtype_msgid)
  694. char const *string;
  695. int negative_allowed;
  696. char const *argtype_msgid;
  697. {
  698. int value = 0;
  699. char const *p = string;
  700. int sign = *p == '-' ? -1 : 1;
  701. p += *p == '-' || *p == '+';
  702. do
  703. {
  704. int v10 = value * 10;
  705. int digit = *p - '0';
  706. int signed_digit = sign * digit;
  707. int next_value = v10 + signed_digit;
  708. if (9 < (unsigned) digit)
  709. fatal ("%s `%s' is not a number", argtype_msgid, string);
  710. if (v10 / 10 != value || (next_value < v10) != (signed_digit < 0))
  711. fatal ("%s `%s' is too large", argtype_msgid, string);
  712. value = next_value;
  713. }
  714. while (*++p);
  715. if (value < 0 && ! negative_allowed)
  716. fatal ("%s `%s' is negative", argtype_msgid, string);
  717. return value;
  718. }
  719. /* Attempt to find the right place to apply this hunk of patch. */
  720. static LINENUM
  721. locate_hunk(fuzz)
  722. LINENUM fuzz;
  723. {
  724. register LINENUM first_guess = pch_first () + last_offset;
  725. register LINENUM offset;
  726. LINENUM pat_lines = pch_ptrn_lines();
  727. LINENUM prefix_context = pch_prefix_context ();
  728. LINENUM suffix_context = pch_suffix_context ();
  729. LINENUM context = (prefix_context < suffix_context
  730. ? suffix_context : prefix_context);
  731. LINENUM prefix_fuzz = fuzz + prefix_context - context;
  732. LINENUM suffix_fuzz = fuzz + suffix_context - context;
  733. LINENUM max_where = input_lines - (pat_lines - suffix_fuzz) + 1;
  734. LINENUM min_where = last_frozen_line + 1 - (prefix_context - prefix_fuzz);
  735. LINENUM max_pos_offset = max_where - first_guess;
  736. LINENUM max_neg_offset = first_guess - min_where;
  737. LINENUM max_offset = (max_pos_offset < max_neg_offset
  738. ? max_neg_offset : max_pos_offset);
  739. if (!pat_lines) /* null range matches always */
  740. return first_guess;
  741. /* Do not try lines <= 0. */
  742. if (first_guess <= max_neg_offset)
  743. max_neg_offset = first_guess - 1;
  744. if (prefix_fuzz < 0)
  745. {
  746. /* Can only match start of file. */
  747. if (suffix_fuzz < 0)
  748. /* Can only match entire file. */
  749. if (pat_lines != input_lines || prefix_context < last_frozen_line)
  750. return 0;
  751. offset = 1 - first_guess;
  752. if (last_frozen_line <= prefix_context
  753. && offset <= max_pos_offset
  754. && patch_match (first_guess, offset, (LINENUM) 0, suffix_fuzz))
  755. {
  756. last_offset = offset;
  757. return first_guess + offset;
  758. }
  759. else
  760. return 0;
  761. }
  762. if (suffix_fuzz < 0)
  763. {
  764. /* Can only match end of file. */
  765. offset = first_guess - (input_lines - pat_lines + 1);
  766. if (offset <= max_neg_offset
  767. && patch_match (first_guess, -offset, prefix_fuzz, (LINENUM) 0))
  768. {
  769. last_offset = - offset;
  770. return first_guess - offset;
  771. }
  772. else
  773. return 0;
  774. }
  775. for (offset = 0; offset <= max_offset; offset++) {
  776. if (offset <= max_pos_offset
  777. && patch_match (first_guess, offset, prefix_fuzz, suffix_fuzz)) {
  778. if (debug & 1)
  779. say ("Offset changing from %ld to %ld\n", last_offset, offset);
  780. last_offset = offset;
  781. return first_guess+offset;
  782. }
  783. if (0 < offset && offset <= max_neg_offset
  784. && patch_match (first_guess, -offset, prefix_fuzz, suffix_fuzz)) {
  785. if (debug & 1)
  786. say ("Offset changing from %ld to %ld\n", last_offset, -offset);
  787. last_offset = -offset;
  788. return first_guess-offset;
  789. }
  790. }
  791. return 0;
  792. }
  793. /* We did not find the pattern, dump out the hunk so they can handle it. */
  794. static void
  795. abort_hunk()
  796. {
  797. register LINENUM i;
  798. register LINENUM pat_end = pch_end ();
  799. /* add in last_offset to guess the same as the previous successful hunk */
  800. LINENUM oldfirst = pch_first() + last_offset;
  801. LINENUM newfirst = pch_newfirst() + last_offset;
  802. LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1;
  803. LINENUM newlast = newfirst + pch_repl_lines() - 1;
  804. char const *stars =
  805. (int) NEW_CONTEXT_DIFF <= (int) diff_type ? " ****" : "";
  806. char const *minuses =
  807. (int) NEW_CONTEXT_DIFF <= (int) diff_type ? " ----" : " -----";
  808. fprintf(rejfp, "***************\n");
  809. for (i=0; i<=pat_end; i++) {
  810. switch (pch_char(i)) {
  811. case '*':
  812. if (oldlast < oldfirst)
  813. fprintf(rejfp, "*** 0%s\n", stars);
  814. else if (oldlast == oldfirst)
  815. fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
  816. else
  817. fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
  818. break;
  819. case '=':
  820. if (newlast < newfirst)
  821. fprintf(rejfp, "--- 0%s\n", minuses);
  822. else if (newlast == newfirst)
  823. fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
  824. else
  825. fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
  826. break;
  827. case ' ': case '-': case '+': case '!':
  828. fprintf (rejfp, "%c ", pch_char (i));
  829. /* fall into */
  830. case '\n':
  831. pch_write_line (i, rejfp);
  832. break;
  833. default:
  834. fatal ("fatal internal error in abort_hunk");
  835. }
  836. if (ferror (rejfp))
  837. write_fatal ();
  838. }
  839. }
  840. /* We found where to apply it (we hope), so do it. */
  841. static bool
  842. apply_hunk (outstate, where)
  843. struct outstate *outstate;
  844. LINENUM where;
  845. {
  846. register LINENUM old = 1;
  847. register LINENUM lastline = pch_ptrn_lines ();
  848. register LINENUM new = lastline+1;
  849. register enum {OUTSIDE, IN_IFNDEF, IN_IFDEF, IN_ELSE} def_state = OUTSIDE;
  850. register char const *R_do_defines = do_defines;
  851. register LINENUM pat_end = pch_end ();
  852. register FILE *fp = outstate->ofp;
  853. where--;
  854. while (pch_char(new) == '=' || pch_char(new) == '\n')
  855. new++;
  856. while (old <= lastline) {
  857. if (pch_char(old) == '-') {
  858. assert (outstate->after_newline);
  859. if (! copy_till (outstate, where + old - 1))
  860. return FALSE;
  861. if (R_do_defines) {
  862. if (def_state == OUTSIDE) {
  863. fprintf (fp, outstate->after_newline + if_defined,
  864. R_do_defines);
  865. def_state = IN_IFNDEF;
  866. }
  867. else if (def_state == IN_IFDEF) {
  868. fprintf (fp, outstate->after_newline + else_defined);
  869. def_state = IN_ELSE;
  870. }
  871. if (ferror (fp))
  872. write_fatal ();
  873. outstate->after_newline = pch_write_line (old, fp);
  874. outstate->zero_output = 0;
  875. }
  876. last_frozen_line++;
  877. old++;
  878. }
  879. else if (new > pat_end) {
  880. break;
  881. }
  882. else if (pch_char(new) == '+') {
  883. if (! copy_till (outstate, where + old - 1))
  884. return FALSE;
  885. if (R_do_defines) {
  886. if (def_state == IN_IFNDEF) {
  887. fprintf (fp, outstate->after_newline + else_defined);
  888. def_state = IN_ELSE;
  889. }
  890. else if (def_state == OUTSIDE) {
  891. fprintf (fp, outstate->after_newline + if_defined,
  892. R_do_defines);
  893. def_state = IN_IFDEF;
  894. }
  895. if (ferror (fp))
  896. write_fatal ();
  897. }
  898. outstate->after_newline = pch_write_line (new, fp);
  899. outstate->zero_output = 0;
  900. new++;
  901. }
  902. else if (pch_char(new) != pch_char(old)) {
  903. if (debug & 1)
  904. say ("oldchar = '%c', newchar = '%c'\n",
  905. pch_char (old), pch_char (new));
  906. fatal ("Out-of-sync patch, lines %ld,%ld -- mangled text or line numbers, maybe?",
  907. pch_hunk_beg() + old,
  908. pch_hunk_beg() + new);
  909. }
  910. else if (pch_char(new) == '!') {
  911. assert (outstate->after_newline);
  912. if (! copy_till (outstate, where + old - 1))
  913. return FALSE;
  914. assert (outstate->after_newline);
  915. if (R_do_defines) {
  916. fprintf (fp, not_defined, R_do_defines);
  917. if (ferror (fp))
  918. write_fatal ();
  919. def_state = IN_IFNDEF;
  920. }
  921. do
  922. {
  923. if (R_do_defines) {
  924. outstate->after_newline = pch_write_line (old, fp);
  925. }
  926. last_frozen_line++;
  927. old++;
  928. }
  929. while (pch_char (old) == '!');
  930. if (R_do_defines) {
  931. fprintf (fp, outstate->after_newline + else_defined);
  932. if (ferror (fp))
  933. write_fatal ();
  934. def_state = IN_ELSE;
  935. }
  936. do
  937. {
  938. outstate->after_newline = pch_write_line (new, fp);
  939. new++;
  940. }
  941. while (pch_char (new) == '!');
  942. outstate->zero_output = 0;
  943. }
  944. else {
  945. assert(pch_char(new) == ' ');
  946. old++;
  947. new++;
  948. if (R_do_defines && def_state != OUTSIDE) {
  949. fprintf (fp, outstate->after_newline + end_defined,
  950. R_do_defines);
  951. if (ferror (fp))
  952. write_fatal ();
  953. outstate->after_newline = 1;
  954. def_state = OUTSIDE;
  955. }
  956. }
  957. }
  958. if (new <= pat_end && pch_char(new) == '+') {
  959. if (! copy_till (outstate, where + old - 1))
  960. return FALSE;
  961. if (R_do_defines) {
  962. if (def_state == OUTSIDE) {
  963. fprintf (fp, outstate->after_newline + if_defined,
  964. R_do_defines);
  965. def_state = IN_IFDEF;
  966. }
  967. else if (def_state == IN_IFNDEF) {
  968. fprintf (fp, outstate->after_newline + else_defined);
  969. def_state = IN_ELSE;
  970. }
  971. if (ferror (fp))
  972. write_fatal ();
  973. outstate->zero_output = 0;
  974. }
  975. do
  976. {
  977. if (! outstate->after_newline && putc ('\n', fp) == EOF)
  978. write_fatal ();
  979. outstate->after_newline = pch_write_line (new, fp);
  980. outstate->zero_output = 0;
  981. new++;
  982. }
  983. while (new <= pat_end && pch_char (new) == '+');
  984. }
  985. if (R_do_defines && def_state != OUTSIDE) {
  986. fprintf (fp, outstate->after_newline + end_defined, R_do_defines);
  987. if (ferror (fp))
  988. write_fatal ();
  989. outstate->after_newline = 1;
  990. }
  991. return TRUE;
  992. }
  993. /* Create an output file. */
  994. static FILE *
  995. create_output_file (name)
  996. char const *name;
  997. {
  998. int fd = create_file (name, O_WRONLY | binary_transput, instat.st_mode);
  999. FILE *f = fdopen (fd, binary_transput ? "wb" : "w");
  1000. if (! f)
  1001. pfatal ("can't create `%s'", name);
  1002. return f;
  1003. }
  1004. /* Open the new file. */
  1005. static void
  1006. init_output (name, outstate)
  1007. char const *name;
  1008. struct outstate *outstate;
  1009. {
  1010. outstate->ofp = name ? create_output_file (name) : (FILE *) 0;
  1011. outstate->after_newline = 1;
  1012. outstate->zero_output = 1;
  1013. }
  1014. /* Open a file to put hunks we can't locate. */
  1015. static void
  1016. init_reject(name)
  1017. char const *name;
  1018. {
  1019. rejfp = create_output_file (name);
  1020. }
  1021. /* Copy input file to output, up to wherever hunk is to be applied. */
  1022. static bool
  1023. copy_till (outstate, lastline)
  1024. register struct outstate *outstate;
  1025. register LINENUM lastline;
  1026. {
  1027. register LINENUM R_last_frozen_line = last_frozen_line;
  1028. register FILE *fp = outstate->ofp;
  1029. register char const *s;
  1030. size_t size;
  1031. if (R_last_frozen_line > lastline)
  1032. {
  1033. say ("misordered hunks! output would be garbled\n");
  1034. return FALSE;
  1035. }
  1036. while (R_last_frozen_line < lastline)
  1037. {
  1038. s = ifetch (++R_last_frozen_line, 0, &size);
  1039. if (size)
  1040. {
  1041. if ((! outstate->after_newline && putc ('\n', fp) == EOF)
  1042. || ! fwrite (s, sizeof *s, size, fp))
  1043. write_fatal ();
  1044. outstate->after_newline = s[size - 1] == '\n';
  1045. outstate->zero_output = 0;
  1046. }
  1047. }
  1048. last_frozen_line = R_last_frozen_line;
  1049. return TRUE;
  1050. }
  1051. /* Finish copying the input file to the output file. */
  1052. static bool
  1053. spew_output (outstate)
  1054. struct outstate *outstate;
  1055. {
  1056. if (debug & 256)
  1057. say ("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
  1058. if (last_frozen_line < input_lines)
  1059. if (! copy_till (outstate, input_lines))
  1060. return FALSE;
  1061. if (outstate->ofp && ! outfile)
  1062. {
  1063. if (fclose (outstate->ofp) != 0)
  1064. write_fatal ();
  1065. outstate->ofp = 0;
  1066. }
  1067. return TRUE;
  1068. }
  1069. /* Does the patch pattern match at line base+offset? */
  1070. static bool
  1071. patch_match (base, offset, prefix_fuzz, suffix_fuzz)
  1072. LINENUM base;
  1073. LINENUM offset;
  1074. LINENUM prefix_fuzz;
  1075. LINENUM suffix_fuzz;
  1076. {
  1077. register LINENUM pline = 1 + prefix_fuzz;
  1078. register LINENUM iline;
  1079. register LINENUM pat_lines = pch_ptrn_lines () - suffix_fuzz;
  1080. size_t size;
  1081. register char const *p;
  1082. for (iline=base+offset+prefix_fuzz; pline <= pat_lines; pline++,iline++) {
  1083. p = ifetch (iline, offset >= 0, &size);
  1084. if (canonicalize) {
  1085. if (!similar(p, size,
  1086. pfetch(pline),
  1087. pch_line_len(pline) ))
  1088. return FALSE;
  1089. }
  1090. else if (size != pch_line_len (pline)
  1091. || memcmp (p, pfetch (pline), size) != 0)
  1092. return FALSE;
  1093. }
  1094. return TRUE;
  1095. }
  1096. /* Do two lines match with canonicalized white space? */
  1097. static bool
  1098. similar (a, alen, b, blen)
  1099. register char const *a;
  1100. register size_t alen;
  1101. register char const *b;
  1102. register size_t blen;
  1103. {
  1104. /* Ignore presence or absence of trailing newlines. */
  1105. alen -= alen && a[alen - 1] == '\n';
  1106. blen -= blen && b[blen - 1] == '\n';
  1107. for (;;)
  1108. {
  1109. if (!blen || (*b == ' ' || *b == '\t'))
  1110. {
  1111. while (blen && (*b == ' ' || *b == '\t'))
  1112. b++, blen--;
  1113. if (alen)
  1114. {
  1115. if (!(*a == ' ' || *a == '\t'))
  1116. return FALSE;
  1117. do a++, alen--;
  1118. while (alen && (*a == ' ' || *a == '\t'));
  1119. }
  1120. if (!alen || !blen)
  1121. return alen == blen;
  1122. }
  1123. else if (!alen || *a++ != *b++)
  1124. return FALSE;
  1125. else
  1126. alen--, blen--;
  1127. }
  1128. }
  1129. /* Make a temporary file. */
  1130. #if HAVE_MKTEMP
  1131. char *mktemp PARAMS ((char *));
  1132. #endif
  1133. #ifndef TMPDIR
  1134. #define TMPDIR "/tmp"
  1135. #endif
  1136. static char const *
  1137. make_temp (letter)
  1138. int letter;
  1139. {
  1140. char *r;
  1141. #if HAVE_MKTEMP
  1142. char const *tmpdir = getenv ("TMPDIR"); /* Unix tradition */
  1143. if (!tmpdir) tmpdir = getenv ("TMP"); /* DOS tradition */
  1144. if (!tmpdir) tmpdir = getenv ("TEMP"); /* another DOS tradition */
  1145. if (!tmpdir) tmpdir = TMPDIR;
  1146. r = xmalloc (strlen (tmpdir) + 10);
  1147. sprintf (r, "%s/p%cXXXXXX", tmpdir, letter);
  1148. mktemp (r);
  1149. if (!*r)
  1150. pfatal ("mktemp");
  1151. #else
  1152. r = xmalloc (L_tmpnam);
  1153. if (! (tmpnam (r) == r && *r))
  1154. pfatal ("tmpnam");
  1155. #endif
  1156. return r;
  1157. }
  1158. /* Fatal exit with cleanup. */
  1159. void
  1160. fatal_exit (sig)
  1161. int sig;
  1162. {
  1163. cleanup ();
  1164. if (sig)
  1165. exit_with_signal (sig);
  1166. exit (2);
  1167. }
  1168. static void
  1169. cleanup ()
  1170. {
  1171. unlink (TMPINNAME);
  1172. unlink (TMPOUTNAME);
  1173. unlink (TMPPATNAME);
  1174. unlink (TMPREJNAME);
  1175. }