|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)patch.c 5.9 (Berkeley) 2/18/88"; ! 3: #endif not lint ! 4: ! 5: char rcsid[] = ! 6: "$Header: patch.c,v 2.0.1.4 87/02/16 14:00:04 lwall Exp $"; ! 7: ! 8: /* patch - a program to apply diffs to original files ! 9: * ! 10: * Copyright 1986, Larry Wall ! 11: * ! 12: * This program may be copied as long as you don't try to make any ! 13: * money off of it, or pretend that you wrote it. ! 14: * ! 15: * $Log: patch.c,v $ ! 16: * Revision 2.0.1.4 87/02/16 14:00:04 lwall ! 17: * Short replacement caused spurious "Out of sync" message. ! 18: * ! 19: * Revision 2.0.1.3 87/01/30 22:45:50 lwall ! 20: * Improved diagnostic on sync error. ! 21: * Moved do_ed_script() to pch.c. ! 22: * ! 23: * Revision 2.0.1.2 86/11/21 09:39:15 lwall ! 24: * Fuzz factor caused offset of installed lines. ! 25: * ! 26: * Revision 2.0.1.1 86/10/29 13:10:22 lwall ! 27: * Backwards search could terminate prematurely. ! 28: * ! 29: * Revision 2.0 86/09/17 15:37:32 lwall ! 30: * Baseline for netwide release. ! 31: * ! 32: * Revision 1.5 86/08/01 20:53:24 lwall ! 33: * Changed some %d's to %ld's. ! 34: * Linted. ! 35: * ! 36: * Revision 1.4 86/08/01 19:17:29 lwall ! 37: * Fixes for machines that can't vararg. ! 38: * Added fuzz factor. ! 39: * Generalized -p. ! 40: * General cleanup. ! 41: * ! 42: * 85/08/15 van%ucbmonet@berkeley ! 43: * Changes for 4.3bsd diff -c. ! 44: * ! 45: * Revision 1.3 85/03/26 15:07:43 lwall ! 46: * Frozen. ! 47: * ! 48: * Revision 1.2.1.9 85/03/12 17:03:35 lwall ! 49: * Changed pfp->_file to fileno(pfp). ! 50: * ! 51: * Revision 1.2.1.8 85/03/12 16:30:43 lwall ! 52: * Check i_ptr and i_womp to make sure they aren't null before freeing. ! 53: * Also allow ed output to be suppressed. ! 54: * ! 55: * Revision 1.2.1.7 85/03/12 15:56:13 lwall ! 56: * Added -p option from jromine@uci-750a. ! 57: * ! 58: * Revision 1.2.1.6 85/03/12 12:12:51 lwall ! 59: * Now checks for normalness of file to patch. ! 60: * ! 61: * Revision 1.2.1.5 85/03/12 11:52:12 lwall ! 62: * Added -D (#ifdef) option from joe@fluke. ! 63: * ! 64: * Revision 1.2.1.4 84/12/06 11:14:15 lwall ! 65: * Made smarter about SCCS subdirectories. ! 66: * ! 67: * Revision 1.2.1.3 84/12/05 11:18:43 lwall ! 68: * Added -l switch to do loose string comparison. ! 69: * ! 70: * Revision 1.2.1.2 84/12/04 09:47:13 lwall ! 71: * Failed hunk count not reset on multiple patch file. ! 72: * ! 73: * Revision 1.2.1.1 84/12/04 09:42:37 lwall ! 74: * Branch for sdcrdcf changes. ! 75: * ! 76: * Revision 1.2 84/11/29 13:29:51 lwall ! 77: * Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed ! 78: * multiple calls to mktemp(). Will now work on machines that can only ! 79: * read 32767 chars. Added -R option for diffs with new and old swapped. ! 80: * Various cosmetic changes. ! 81: * ! 82: * Revision 1.1 84/11/09 17:03:58 lwall ! 83: * Initial revision ! 84: * ! 85: */ ! 86: ! 87: #include "INTERN.h" ! 88: #include "common.h" ! 89: #include "EXTERN.h" ! 90: #include "version.h" ! 91: #include "util.h" ! 92: #include "pch.h" ! 93: #include "inp.h" ! 94: ! 95: /* procedures */ ! 96: ! 97: void reinitialize_almost_everything(); ! 98: void get_some_switches(); ! 99: LINENUM locate_hunk(); ! 100: void abort_hunk(); ! 101: void apply_hunk(); ! 102: void init_output(); ! 103: void init_reject(); ! 104: void copy_till(); ! 105: void spew_output(); ! 106: void dump_line(); ! 107: bool patch_match(); ! 108: bool similar(); ! 109: void re_input(); ! 110: void my_exit(); ! 111: ! 112: /* Apply a set of diffs as appropriate. */ ! 113: ! 114: main(argc,argv) ! 115: int argc; ! 116: char **argv; ! 117: { ! 118: LINENUM where; ! 119: LINENUM newwhere; ! 120: LINENUM fuzz; ! 121: LINENUM mymaxfuzz; ! 122: int hunk = 0; ! 123: int failed = 0; ! 124: int i; ! 125: ! 126: setbuf(stderr, serrbuf); ! 127: for (i = 0; i<MAXFILEC; i++) ! 128: filearg[i] = Nullch; ! 129: Mktemp(TMPOUTNAME); ! 130: Mktemp(TMPINNAME); ! 131: Mktemp(TMPREJNAME); ! 132: Mktemp(TMPPATNAME); ! 133: ! 134: /* parse switches */ ! 135: Argc = argc; ! 136: Argv = argv; ! 137: get_some_switches(); ! 138: ! 139: /* make sure we clean up /tmp in case of disaster */ ! 140: set_signals(); ! 141: ! 142: for ( ! 143: open_patch_file(filearg[1]); ! 144: there_is_another_patch(); ! 145: reinitialize_almost_everything() ! 146: ) { /* for each patch in patch file */ ! 147: ! 148: if (outname == Nullch) ! 149: outname = savestr(filearg[0]); ! 150: ! 151: /* initialize the patched file */ ! 152: if (!skip_rest_of_patch) ! 153: init_output(TMPOUTNAME); ! 154: ! 155: /* for ed script just up and do it and exit */ ! 156: if (diff_type == ED_DIFF) { ! 157: do_ed_script(); ! 158: continue; ! 159: } ! 160: ! 161: /* initialize reject file */ ! 162: init_reject(TMPREJNAME); ! 163: ! 164: /* find out where all the lines are */ ! 165: if (!skip_rest_of_patch) ! 166: scan_input(filearg[0]); ! 167: ! 168: /* from here on, open no standard i/o files, because malloc */ ! 169: /* might misfire and we can't catch it easily */ ! 170: ! 171: /* apply each hunk of patch */ ! 172: hunk = 0; ! 173: failed = 0; ! 174: out_of_mem = FALSE; ! 175: while (another_hunk()) { ! 176: hunk++; ! 177: fuzz = Nulline; ! 178: mymaxfuzz = pch_context(); ! 179: if (maxfuzz < mymaxfuzz) ! 180: mymaxfuzz = maxfuzz; ! 181: if (!skip_rest_of_patch) { ! 182: do { ! 183: where = locate_hunk(fuzz); ! 184: if (hunk == 1 && where == Nulline && !force) { ! 185: /* dwim for reversed patch? */ ! 186: if (!pch_swap()) { ! 187: if (fuzz == Nulline) ! 188: say1("\ ! 189: Not enough memory to try swapped hunk! Assuming unswapped.\n"); ! 190: continue; ! 191: } ! 192: reverse = !reverse; ! 193: where = locate_hunk(fuzz); /* try again */ ! 194: if (where == Nulline) { /* didn't find it swapped */ ! 195: if (!pch_swap()) /* put it back to normal */ ! 196: fatal1("Lost hunk on alloc error!\n"); ! 197: reverse = !reverse; ! 198: } ! 199: else if (noreverse) { ! 200: if (!pch_swap()) /* put it back to normal */ ! 201: fatal1("Lost hunk on alloc error!\n"); ! 202: reverse = !reverse; ! 203: say1("\ ! 204: Ignoring previously applied (or reversed) patch.\n"); ! 205: skip_rest_of_patch = TRUE; ! 206: } ! 207: else { ! 208: ask3("\ ! 209: %seversed (or previously applied) patch detected! %s -R? [y] ", ! 210: reverse ? "R" : "Unr", ! 211: reverse ? "Assume" : "Ignore"); ! 212: if (*buf == 'n') { ! 213: ask1("Apply anyway? [n] "); ! 214: if (*buf != 'y') ! 215: skip_rest_of_patch = TRUE; ! 216: where = Nulline; ! 217: reverse = !reverse; ! 218: if (!pch_swap()) /* put it back to normal */ ! 219: fatal1("Lost hunk on alloc error!\n"); ! 220: } ! 221: } ! 222: } ! 223: } while (!skip_rest_of_patch && where == Nulline && ! 224: ++fuzz <= mymaxfuzz); ! 225: ! 226: if (skip_rest_of_patch) { /* just got decided */ ! 227: Fclose(ofp); ! 228: ofp = Nullfp; ! 229: } ! 230: } ! 231: ! 232: newwhere = pch_newfirst() + last_offset; ! 233: if (skip_rest_of_patch) { ! 234: abort_hunk(); ! 235: failed++; ! 236: if (verbose) ! 237: say3("Hunk #%d ignored at %ld.\n", hunk, newwhere); ! 238: } ! 239: else if (where == Nulline) { ! 240: abort_hunk(); ! 241: failed++; ! 242: if (verbose) ! 243: say3("Hunk #%d failed at %ld.\n", hunk, newwhere); ! 244: } ! 245: else { ! 246: apply_hunk(where); ! 247: if (verbose) { ! 248: say3("Hunk #%d succeeded at %ld", hunk, newwhere); ! 249: if (fuzz) ! 250: say2(" with fuzz %ld", fuzz); ! 251: if (last_offset) ! 252: say3(" (offset %ld line%s)", ! 253: last_offset, last_offset==1L?"":"s"); ! 254: say1(".\n"); ! 255: } ! 256: } ! 257: } ! 258: ! 259: if (out_of_mem && using_plan_a) { ! 260: Argc = Argc_last; ! 261: Argv = Argv_last; ! 262: say1("\n\nRan out of memory using Plan A--trying again...\n\n"); ! 263: continue; ! 264: } ! 265: ! 266: assert(hunk); ! 267: ! 268: /* finish spewing out the new file */ ! 269: if (!skip_rest_of_patch) ! 270: spew_output(); ! 271: ! 272: /* and put the output where desired */ ! 273: ignore_signals(); ! 274: if (!skip_rest_of_patch) { ! 275: if (move_file(TMPOUTNAME, outname) < 0) { ! 276: toutkeep = TRUE; ! 277: chmod(TMPOUTNAME, filemode); ! 278: } ! 279: else ! 280: chmod(outname, filemode); ! 281: } ! 282: Fclose(rejfp); ! 283: rejfp = Nullfp; ! 284: if (failed) { ! 285: if (!*rejname) { ! 286: Strcpy(rejname, outname); ! 287: Strcat(rejname, ".rej"); ! 288: } ! 289: if (skip_rest_of_patch) { ! 290: say4("%d out of %d hunks ignored--saving rejects to %s\n", ! 291: failed, hunk, rejname); ! 292: } ! 293: else { ! 294: say4("%d out of %d hunks failed--saving rejects to %s\n", ! 295: failed, hunk, rejname); ! 296: } ! 297: if (move_file(TMPREJNAME, rejname) < 0) ! 298: trejkeep = TRUE; ! 299: } ! 300: set_signals(); ! 301: } ! 302: my_exit(0); ! 303: } ! 304: ! 305: /* Prepare to find the next patch to do in the patch file. */ ! 306: ! 307: void ! 308: reinitialize_almost_everything() ! 309: { ! 310: re_patch(); ! 311: re_input(); ! 312: ! 313: input_lines = 0; ! 314: last_frozen_line = 0; ! 315: ! 316: filec = 0; ! 317: if (filearg[0] != Nullch && !out_of_mem) { ! 318: free(filearg[0]); ! 319: filearg[0] = Nullch; ! 320: } ! 321: ! 322: if (outname != Nullch) { ! 323: free(outname); ! 324: outname = Nullch; ! 325: } ! 326: ! 327: last_offset = 0; ! 328: ! 329: diff_type = 0; ! 330: ! 331: if (revision != Nullch) { ! 332: free(revision); ! 333: revision = Nullch; ! 334: } ! 335: ! 336: reverse = FALSE; ! 337: skip_rest_of_patch = FALSE; ! 338: ! 339: get_some_switches(); ! 340: ! 341: if (filec >= 2) ! 342: fatal1("You may not change to a different patch file.\n"); ! 343: } ! 344: ! 345: /* Process switches and filenames up to next '+' or end of list. */ ! 346: ! 347: void ! 348: get_some_switches() ! 349: { ! 350: Reg1 char *s; ! 351: ! 352: rejname[0] = '\0'; ! 353: Argc_last = Argc; ! 354: Argv_last = Argv; ! 355: if (!Argc) ! 356: return; ! 357: for (Argc--,Argv++; Argc; Argc--,Argv++) { ! 358: s = Argv[0]; ! 359: if (strEQ(s, "+")) { ! 360: return; /* + will be skipped by for loop */ ! 361: } ! 362: if (*s != '-' || !s[1]) { ! 363: if (filec == MAXFILEC) ! 364: fatal1("Too many file arguments.\n"); ! 365: filearg[filec++] = savestr(s); ! 366: } ! 367: else { ! 368: switch (*++s) { ! 369: case 'b': ! 370: origext = savestr(Argv[1]); ! 371: Argc--,Argv++; ! 372: break; ! 373: case 'c': ! 374: diff_type = CONTEXT_DIFF; ! 375: break; ! 376: case 'd': ! 377: if (!*++s) { ! 378: Argc--,Argv++; ! 379: s = Argv[0]; ! 380: } ! 381: if (chdir(s) < 0) ! 382: fatal2("Can't cd to %s.\n", s); ! 383: break; ! 384: case 'D': ! 385: do_defines = TRUE; ! 386: if (!*++s) { ! 387: Argc--,Argv++; ! 388: s = Argv[0]; ! 389: } ! 390: Sprintf(if_defined, "#ifdef %s\n", s); ! 391: Sprintf(not_defined, "#ifndef %s\n", s); ! 392: Sprintf(end_defined, "#endif /* %s */\n", s); ! 393: break; ! 394: case 'e': ! 395: diff_type = ED_DIFF; ! 396: break; ! 397: case 'f': ! 398: force = TRUE; ! 399: break; ! 400: case 'F': ! 401: if (*++s == '=') ! 402: s++; ! 403: maxfuzz = atoi(s); ! 404: break; ! 405: case 'l': ! 406: canonicalize = TRUE; ! 407: break; ! 408: case 'n': ! 409: diff_type = NORMAL_DIFF; ! 410: break; ! 411: case 'N': ! 412: noreverse = TRUE; ! 413: break; ! 414: case 'o': ! 415: outname = savestr(Argv[1]); ! 416: Argc--,Argv++; ! 417: break; ! 418: case 'p': ! 419: if (*++s == '=') ! 420: s++; ! 421: strippath = atoi(s); ! 422: break; ! 423: case 'r': ! 424: Strcpy(rejname, Argv[1]); ! 425: Argc--,Argv++; ! 426: break; ! 427: case 'R': ! 428: reverse = TRUE; ! 429: break; ! 430: case 's': ! 431: verbose = FALSE; ! 432: break; ! 433: case 'S': ! 434: skip_rest_of_patch = TRUE; ! 435: break; ! 436: case 'v': ! 437: version(); ! 438: break; ! 439: #ifdef DEBUGGING ! 440: case 'x': ! 441: debug = atoi(s+1); ! 442: break; ! 443: #endif ! 444: default: ! 445: fatal2("Unrecognized switch: %s\n", Argv[0]); ! 446: } ! 447: } ! 448: } ! 449: } ! 450: ! 451: /* Attempt to find the right place to apply this hunk of patch. */ ! 452: ! 453: LINENUM ! 454: locate_hunk(fuzz) ! 455: LINENUM fuzz; ! 456: { ! 457: Reg1 LINENUM first_guess = pch_first() + last_offset; ! 458: Reg2 LINENUM offset; ! 459: LINENUM pat_lines = pch_ptrn_lines(); ! 460: Reg3 LINENUM max_pos_offset = input_lines - first_guess ! 461: - pat_lines + 1; ! 462: Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1 ! 463: + pch_context(); ! 464: ! 465: if (!pat_lines) /* null range matches always */ ! 466: return first_guess; ! 467: if (max_neg_offset >= first_guess) /* do not try lines < 0 */ ! 468: max_neg_offset = first_guess - 1; ! 469: if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz)) ! 470: return first_guess; ! 471: for (offset = 1; ; offset++) { ! 472: Reg5 bool check_after = (offset <= max_pos_offset); ! 473: Reg6 bool check_before = (offset <= max_neg_offset); ! 474: ! 475: if (check_after && patch_match(first_guess, offset, fuzz)) { ! 476: #ifdef DEBUGGING ! 477: if (debug & 1) ! 478: say3("Offset changing from %ld to %ld\n", last_offset, offset); ! 479: #endif ! 480: last_offset = offset; ! 481: return first_guess+offset; ! 482: } ! 483: else if (check_before && patch_match(first_guess, -offset, fuzz)) { ! 484: #ifdef DEBUGGING ! 485: if (debug & 1) ! 486: say3("Offset changing from %ld to %ld\n", last_offset, -offset); ! 487: #endif ! 488: last_offset = -offset; ! 489: return first_guess-offset; ! 490: } ! 491: else if (!check_before && !check_after) ! 492: return Nulline; ! 493: } ! 494: } ! 495: ! 496: /* We did not find the pattern, dump out the hunk so they can handle it. */ ! 497: ! 498: void ! 499: abort_hunk() ! 500: { ! 501: Reg1 LINENUM i; ! 502: Reg2 LINENUM pat_end = pch_end(); ! 503: /* add in last_offset to guess the same as the previous successful hunk */ ! 504: LINENUM oldfirst = pch_first() + last_offset; ! 505: LINENUM newfirst = pch_newfirst() + last_offset; ! 506: LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1; ! 507: LINENUM newlast = newfirst + pch_repl_lines() - 1; ! 508: char *stars = (diff_type == NEW_CONTEXT_DIFF ? " ****" : ""); ! 509: char *minuses = (diff_type == NEW_CONTEXT_DIFF ? " ----" : " -----"); ! 510: ! 511: fprintf(rejfp, "***************\n"); ! 512: for (i=0; i<=pat_end; i++) { ! 513: switch (pch_char(i)) { ! 514: case '*': ! 515: if (oldlast < oldfirst) ! 516: fprintf(rejfp, "*** 0%s\n", stars); ! 517: else if (oldlast == oldfirst) ! 518: fprintf(rejfp, "*** %ld%s\n", oldfirst, stars); ! 519: else ! 520: fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars); ! 521: break; ! 522: case '=': ! 523: if (newlast < newfirst) ! 524: fprintf(rejfp, "--- 0%s\n", minuses); ! 525: else if (newlast == newfirst) ! 526: fprintf(rejfp, "--- %ld%s\n", newfirst, minuses); ! 527: else ! 528: fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses); ! 529: break; ! 530: case '\n': ! 531: fprintf(rejfp, "%s", pfetch(i)); ! 532: break; ! 533: case ' ': case '-': case '+': case '!': ! 534: fprintf(rejfp, "%c %s", pch_char(i), pfetch(i)); ! 535: break; ! 536: default: ! 537: say1("Fatal internal error in abort_hunk().\n"); ! 538: abort(); ! 539: } ! 540: } ! 541: } ! 542: ! 543: /* We found where to apply it (we hope), so do it. */ ! 544: ! 545: void ! 546: apply_hunk(where) ! 547: LINENUM where; ! 548: { ! 549: Reg1 LINENUM old = 1; ! 550: Reg2 LINENUM lastline = pch_ptrn_lines(); ! 551: Reg3 LINENUM new = lastline+1; ! 552: #define OUTSIDE 0 ! 553: #define IN_IFNDEF 1 ! 554: #define IN_IFDEF 2 ! 555: #define IN_ELSE 3 ! 556: Reg4 int def_state = OUTSIDE; ! 557: Reg5 bool R_do_defines = do_defines; ! 558: Reg6 LINENUM pat_end = pch_end(); ! 559: ! 560: where--; ! 561: while (pch_char(new) == '=' || pch_char(new) == '\n') ! 562: new++; ! 563: ! 564: while (old <= lastline) { ! 565: if (pch_char(old) == '-') { ! 566: copy_till(where + old - 1); ! 567: if (R_do_defines) { ! 568: if (def_state == OUTSIDE) { ! 569: fputs(not_defined, ofp); ! 570: def_state = IN_IFNDEF; ! 571: } ! 572: else if (def_state == IN_IFDEF) { ! 573: fputs(else_defined, ofp); ! 574: def_state = IN_ELSE; ! 575: } ! 576: fputs(pfetch(old), ofp); ! 577: } ! 578: last_frozen_line++; ! 579: old++; ! 580: } ! 581: else if (new > pat_end) ! 582: break; ! 583: else if (pch_char(new) == '+') { ! 584: copy_till(where + old - 1); ! 585: if (R_do_defines) { ! 586: if (def_state == IN_IFNDEF) { ! 587: fputs(else_defined, ofp); ! 588: def_state = IN_ELSE; ! 589: } ! 590: else if (def_state == OUTSIDE) { ! 591: fputs(if_defined, ofp); ! 592: def_state = IN_IFDEF; ! 593: } ! 594: } ! 595: fputs(pfetch(new), ofp); ! 596: new++; ! 597: } ! 598: else { ! 599: if (pch_char(new) != pch_char(old)) { ! 600: say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n", ! 601: pch_hunk_beg() + old, ! 602: pch_hunk_beg() + new); ! 603: #ifdef DEBUGGING ! 604: say3("oldchar = '%c', newchar = '%c'\n", ! 605: pch_char(old), pch_char(new)); ! 606: #endif ! 607: my_exit(1); ! 608: } ! 609: if (pch_char(new) == '!') { ! 610: copy_till(where + old - 1); ! 611: if (R_do_defines) { ! 612: fputs(not_defined, ofp); ! 613: def_state = IN_IFNDEF; ! 614: } ! 615: while (pch_char(old) == '!') { ! 616: if (R_do_defines) { ! 617: fputs(pfetch(old), ofp); ! 618: } ! 619: last_frozen_line++; ! 620: old++; ! 621: } ! 622: if (R_do_defines) { ! 623: fputs(else_defined, ofp); ! 624: def_state = IN_ELSE; ! 625: } ! 626: while (pch_char(new) == '!') { ! 627: fputs(pfetch(new), ofp); ! 628: new++; ! 629: } ! 630: if (R_do_defines) { ! 631: fputs(end_defined, ofp); ! 632: def_state = OUTSIDE; ! 633: } ! 634: } ! 635: else { ! 636: assert(pch_char(new) == ' '); ! 637: old++; ! 638: new++; ! 639: } ! 640: } ! 641: } ! 642: if (new <= pat_end && pch_char(new) == '+') { ! 643: copy_till(where + old - 1); ! 644: if (R_do_defines) { ! 645: if (def_state == OUTSIDE) { ! 646: fputs(if_defined, ofp); ! 647: def_state = IN_IFDEF; ! 648: } ! 649: else if (def_state == IN_IFNDEF) { ! 650: fputs(else_defined, ofp); ! 651: def_state = IN_ELSE; ! 652: } ! 653: } ! 654: while (new <= pat_end && pch_char(new) == '+') { ! 655: fputs(pfetch(new), ofp); ! 656: new++; ! 657: } ! 658: } ! 659: if (R_do_defines && def_state != OUTSIDE) { ! 660: fputs(end_defined, ofp); ! 661: } ! 662: } ! 663: ! 664: /* Open the new file. */ ! 665: ! 666: void ! 667: init_output(name) ! 668: char *name; ! 669: { ! 670: ofp = fopen(name, "w"); ! 671: if (ofp == Nullfp) ! 672: fatal2("patch: can't create %s.\n", name); ! 673: } ! 674: ! 675: /* Open a file to put hunks we can't locate. */ ! 676: ! 677: void ! 678: init_reject(name) ! 679: char *name; ! 680: { ! 681: rejfp = fopen(name, "w"); ! 682: if (rejfp == Nullfp) ! 683: fatal2("patch: can't create %s.\n", name); ! 684: } ! 685: ! 686: /* Copy input file to output, up to wherever hunk is to be applied. */ ! 687: ! 688: void ! 689: copy_till(lastline) ! 690: Reg1 LINENUM lastline; ! 691: { ! 692: Reg2 LINENUM R_last_frozen_line = last_frozen_line; ! 693: ! 694: if (R_last_frozen_line > lastline) ! 695: say1("patch: misordered hunks! output will be garbled.\n"); ! 696: while (R_last_frozen_line < lastline) { ! 697: dump_line(++R_last_frozen_line); ! 698: } ! 699: last_frozen_line = R_last_frozen_line; ! 700: } ! 701: ! 702: /* Finish copying the input file to the output file. */ ! 703: ! 704: void ! 705: spew_output() ! 706: { ! 707: #ifdef DEBUGGING ! 708: if (debug & 256) ! 709: say3("il=%ld lfl=%ld\n",input_lines,last_frozen_line); ! 710: #endif ! 711: if (input_lines) ! 712: copy_till(input_lines); /* dump remainder of file */ ! 713: Fclose(ofp); ! 714: ofp = Nullfp; ! 715: } ! 716: ! 717: /* Copy one line from input to output. */ ! 718: ! 719: void ! 720: dump_line(line) ! 721: LINENUM line; ! 722: { ! 723: Reg1 char *s; ! 724: Reg2 char R_newline = '\n'; ! 725: ! 726: /* Note: string is not null terminated. */ ! 727: for (s=ifetch(line, 0); putc(*s, ofp) != R_newline; s++) ; ! 728: } ! 729: ! 730: /* Does the patch pattern match at line base+offset? */ ! 731: ! 732: bool ! 733: patch_match(base, offset, fuzz) ! 734: LINENUM base; ! 735: LINENUM offset; ! 736: LINENUM fuzz; ! 737: { ! 738: Reg1 LINENUM pline = 1 + fuzz; ! 739: Reg2 LINENUM iline; ! 740: Reg3 LINENUM pat_lines = pch_ptrn_lines() - fuzz; ! 741: ! 742: for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) { ! 743: if (canonicalize) { ! 744: if (!similar(ifetch(iline, (offset >= 0)), ! 745: pfetch(pline), ! 746: pch_line_len(pline) )) ! 747: return FALSE; ! 748: } ! 749: else if (strnNE(ifetch(iline, (offset >= 0)), ! 750: pfetch(pline), ! 751: pch_line_len(pline) )) ! 752: return FALSE; ! 753: } ! 754: return TRUE; ! 755: } ! 756: ! 757: /* Do two lines match with canonicalized white space? */ ! 758: ! 759: bool ! 760: similar(a,b,len) ! 761: Reg1 char *a; ! 762: Reg2 char *b; ! 763: Reg3 int len; ! 764: { ! 765: while (len) { ! 766: if (isspace(*b)) { /* whitespace (or \n) to match? */ ! 767: if (!isspace(*a)) /* no corresponding whitespace? */ ! 768: return FALSE; ! 769: while (len && isspace(*b) && *b != '\n') ! 770: b++,len--; /* skip pattern whitespace */ ! 771: while (isspace(*a) && *a != '\n') ! 772: a++; /* skip target whitespace */ ! 773: if (*a == '\n' || *b == '\n') ! 774: return (*a == *b); /* should end in sync */ ! 775: } ! 776: else if (*a++ != *b++) /* match non-whitespace chars */ ! 777: return FALSE; ! 778: else ! 779: len--; /* probably not necessary */ ! 780: } ! 781: return TRUE; /* actually, this is not reached */ ! 782: /* since there is always a \n */ ! 783: } ! 784: ! 785: /* Exit with cleanup. */ ! 786: ! 787: void ! 788: my_exit(status) ! 789: int status; ! 790: { ! 791: Unlink(TMPINNAME); ! 792: if (!toutkeep) { ! 793: Unlink(TMPOUTNAME); ! 794: } ! 795: if (!trejkeep) { ! 796: Unlink(TMPREJNAME); ! 797: } ! 798: Unlink(TMPPATNAME); ! 799: exit(status); ! 800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.