+-+-+-+ Beginning of part 5 +-+-+-+ X * Revision 1.2.1.6 85/03/12 12:12:51 lwall X * Now checks for normalness of file to patch. X * X * Revision 1.2.1.5 85/03/12 11:52:12 lwall X * Added -D (#ifdef) option from joe@fluke. X * X * Revision 1.2.1.4 84/12/06 11:14:15 lwall X * Made smarter about SCCS subdirectories. X * X * Revision 1.2.1.3 84/12/05 11:18:43 lwall X * Added -l switch to do loose string comparison. X * X * Revision 1.2.1.2 84/12/04 09:47:13 lwall X * Failed hunk count not reset on multiple patch file. X * X * Revision 1.2.1.1 84/12/04 09:42:37 lwall X * Branch for sdcrdcf changes. X * X * Revision 1.2 84/11/29 13:29:51 lwall X * Linted. Identifiers uniqified. Fixed i_ptr malloc() bug. Fixed X * multiple calls to mktemp(). Will now work on machines that can only X * read 32767 chars. Added -R option for diffs with new and old swapped. X * Various cosmetic changes. X * X * Revision 1.1 84/11/09 17:03:58 lwall X * Initial revision X * X */ X X#include "INTERN.h" X#include "common.h" X#include "EXTERN.h" X#include "version.h" X#include "util.h" X#include "pch.h" X#include "inp.h" X X/* procedures */ X Xvoid reinitialize_almost_everything(); Xvoid get_some_switches(); XLINENUM locate_hunk(); Xvoid abort_hunk(); Xvoid apply_hunk(); Xvoid init_output(); Xvoid init_reject(); Xvoid copy_till(); Xvoid spew_output(); Xvoid dump_line(); Xbool patch_match(); Xbool similar(); Xvoid re_input(); Xvoid my_exit(); X X/* Apply a set of diffs as appropriate. */ X Xmain(argc,argv) Xint argc; Xchar **argv; X`123 X LINENUM where; X LINENUM newwhere; X LINENUM fuzz; X LINENUM mymaxfuzz; X int hunk = 0; X int failed = 0; X int failtotal = 0; X int i; X X setbuf(stderr, serrbuf); X for (i = 0; i 13) X`009`009`009if (s[12] == '.')`009/* try to preserve difference */ X`009`009`009 s[12] = s[13];`009/* between .h, .c, .y, etc. */ X`009`009`009s[13] = '\0'; X`009`009`125 X#endif X`009`009Strcat(rejname, REJEXT); X`009 `125 X`009 if (skip_rest_of_patch) `123 X`009`009say4("%d out of %d hunks ignored--saving rejects to %s\n", X`009`009 failed, hunk, rejname); X`009 `125 X`009 else `123 X`009`009say4("%d out of %d hunks failed--saving rejects to %s\n", X`009`009 failed, hunk, rejname); X`009 `125 X`009 if (move_file(TMPREJNAME, rejname) < 0) X`009`009trejkeep = TRUE; X`009`125 X`009set_signals(1); X `125 X my_exit(failtotal); X`125 X X/* Prepare to find the next patch to do in the patch file. */ X Xvoid Xreinitialize_almost_everything() X`123 X re_patch(); X re_input(); X X input_lines = 0; X last_frozen_line = 0; X X filec = 0; X if (filearg[0] != Nullch && !out_of_mem) `123 X`009free(filearg[0]); X`009filearg[0] = Nullch; X `125 X X if (outname != Nullch) `123 X`009free(outname); X`009outname = Nullch; X `125 X X last_offset = 0; X X diff_type = 0; X X if (revision != Nullch) `123 X`009free(revision); X`009revision = Nullch; X `125 X X reverse = FALSE; X skip_rest_of_patch = FALSE; X X get_some_switches(); X X if (filec >= 2) X`009fatal1("You may not change to a different patch file.\n"); X`125 X X/* Process switches and filenames up to next '+' or end of list. */ X Xvoid Xget_some_switches() X`123 X Reg1 char *s; X X rejname[0] = '\0'; X Argc_last = Argc; X Argv_last = Argv; X if (!Argc) X`009return; X for (Argc--,Argv++; Argc; Argc--,Argv++) `123 X`009s = Argv[0]; X`009if (strEQ(s, "+")) `123 X`009 return;`009`009`009/* + will be skipped by for loop */ X`009`125 X`009if (*s != '-' `124`124 !s[1]) `123 X`009 if (filec == MAXFILEC) X`009`009fatal1("Too many file arguments.\n"); X`009 filearg[filec++] = savestr(s); X`009`125 X`009else `123 X`009 switch (*++s) `123 X`009 case 'b': X`009`009origext = savestr(Argv[1]); X`009`009Argc--,Argv++; X`009`009break; X`009 case 'B': X`009`009origprae = savestr(Argv[1]); X`009`009Argc--,Argv++; X`009`009break; X`009 case 'c': X`009`009diff_type = CONTEXT_DIFF; X`009`009break; X`009 case 'd': X`009`009if (!*++s) `123 X`009`009 Argc--,Argv++; X`009`009 s = Argv[0]; X`009`009`125 X`009`009if (chdir(s) < 0) X`009`009 fatal2("Can't cd to %s.\n", s); X`009`009break; X`009 case 'D': X`009 `009do_defines = TRUE; X`009`009if (!*++s) `123 X`009`009 Argc--,Argv++; X`009`009 s = Argv[0]; X`009`009`125 X`009`009if (!isalpha(*s)) X`009`009 fatal1("Argument to -D not an identifier.\n"); X`009`009Sprintf(if_defined, "#ifdef %s\n", s); X`009`009Sprintf(not_defined, "#ifndef %s\n", s); X`009`009Sprintf(end_defined, "#endif /* %s */\n", s); X`009`009break; X`009 case 'e': X`009`009diff_type = ED_DIFF; X`009`009break; X`009 case 'f': X`009`009force = TRUE; X`009`009break; X`009 case 'F': X`009`009if (*++s == '=') X`009`009 s++; X`009`009maxfuzz = atoi(s); X`009`009break; X`009 case 'l': X`009`009canonicalize = TRUE; X`009`009break; X`009 case 'n': X`009`009diff_type = NORMAL_DIFF; X`009`009break; X`009 case 'N': X`009`009noreverse = TRUE; X`009`009break; X`009 case 'o': X`009`009outname = savestr(Argv[1]); X`009`009Argc--,Argv++; X`009`009break; X`009 case 'p': X`009`009if (*++s == '=') X`009`009 s++; X`009`009strippath = atoi(s); X`009`009break; X`009 case 'r': X`009`009Strcpy(rejname, Argv[1]); X`009`009Argc--,Argv++; X`009`009break; X`009 case 'R': X`009`009reverse = TRUE; X`009`009break; X`009 case 's': X`009`009verbose = FALSE; X`009`009break; X`009 case 'S': X`009`009skip_rest_of_patch = TRUE; X`009`009break; X`009 case 'v': X`009`009version(); X`009`009break; X#ifdef DEBUGGING X`009 case 'x': X`009`009debug = atoi(s+1); X`009`009break; X#endif X`009 default: X`009`009fatal2("Unrecognized switch: %s\n", Argv[0]); X`009 `125 X`009`125 X `125 X`125 X X/* Attempt to find the right place to apply this hunk of patch. */ X XLINENUM Xlocate_hunk(fuzz) XLINENUM fuzz; X`123 X Reg1 LINENUM first_guess = pch_first() + last_offset; X Reg2 LINENUM offset; X LINENUM pat_lines = pch_ptrn_lines(); X Reg3 LINENUM max_pos_offset = input_lines - first_guess X`009`009`009`009- pat_lines + 1; X Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1 X`009`009`009`009+ pch_context(); X X if (!pat_lines)`009`009`009/* null range matches always */ X`009return first_guess; X if (max_neg_offset >= first_guess)`009/* do not try lines < 0 */ X`009max_neg_offset = first_guess - 1; V if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz) X) X`009return first_guess; X for (offset = 1; ; offset++) `123 X`009Reg5 bool check_after = (offset <= max_pos_offset); X`009Reg6 bool check_before = (offset <= max_neg_offset); X X`009if (check_after && patch_match(first_guess, offset, fuzz)) `123 X#ifdef DEBUGGING X`009 if (debug & 1) X`009`009say3("Offset changing from %ld to %ld\n", last_offset, offset); X#endif X`009 last_offset = offset; X`009 return first_guess+offset; X`009`125 X`009else if (check_before && patch_match(first_guess, -offset, fuzz)) `123 X#ifdef DEBUGGING X`009 if (debug & 1) X`009`009say3("Offset changing from %ld to %ld\n", last_offset, -offset); X#endif X`009 last_offset = -offset; X`009 return first_guess-offset; X`009`125 X`009else if (!check_before && !check_after) X`009 return Nulline; X `125 X`125 X X/* We did not find the pattern, dump out the hunk so they can handle it. */ X Xvoid Xabort_hunk() X`123 X Reg1 LINENUM i; X Reg2 LINENUM pat_end = pch_end(); V /* add in last_offset to guess the same as the previous successful hunk * X/ X LINENUM oldfirst = pch_first() + last_offset; X LINENUM newfirst = pch_newfirst() + last_offset; X LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1; X LINENUM newlast = newfirst + pch_repl_lines() - 1; X char *stars = (diff_type == NEW_CONTEXT_DIFF ? " ****" : ""); X char *minuses = (diff_type == NEW_CONTEXT_DIFF ? " ----" : " -----"); X X fprintf(rejfp, "***************\n"); X for (i=0; i<=pat_end; i++) `123 X`009switch (pch_char(i)) `123 X`009case '*': X`009 if (oldlast < oldfirst) X`009`009fprintf(rejfp, "*** 0%s\n", stars); X`009 else if (oldlast == oldfirst) X`009`009fprintf(rejfp, "*** %ld%s\n", oldfirst, stars); X`009 else X`009`009fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars); X`009 break; X`009case '=': X`009 if (newlast < newfirst) X`009`009fprintf(rejfp, "--- 0%s\n", minuses); X`009 else if (newlast == newfirst) X`009`009fprintf(rejfp, "--- %ld%s\n", newfirst, minuses); X`009 else X`009`009fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses); X`009 break; X`009case '\n': X`009 fprintf(rejfp, "%s", pfetch(i)); X`009 break; X`009case ' ': case '-': case '+': case '!': X`009 fprintf(rejfp, "%c %s", pch_char(i), pfetch(i)); X`009 break; X`009default: X`009 say1("Fatal internal error in abort_hunk().\n"); X`009 abort(); X`009`125 X `125 X`125 X X/* We found where to apply it (we hope), so do it. */ X Xvoid Xapply_hunk(where) XLINENUM where; X`123 X Reg1 LINENUM old = 1; X Reg2 LINENUM lastline = pch_ptrn_lines(); X Reg3 LINENUM new = lastline+1; X#define OUTSIDE 0 X#define IN_IFNDEF 1 X#define IN_IFDEF 2 X#define IN_ELSE 3 X Reg4 int def_state = OUTSIDE; X Reg5 bool R_do_defines = do_defines; X Reg6 LINENUM pat_end = pch_end(); X X where--; X while (pch_char(new) == '=' `124`124 pch_char(new) == '\n') X`009new++; X X while (old <= lastline) `123 X`009if (pch_char(old) == '-') `123 X`009 copy_till(where + old - 1); X`009 if (R_do_defines) `123 X`009`009if (def_state == OUTSIDE) `123 X`009`009 fputs(not_defined, ofp); X`009`009 def_state = IN_IFNDEF; X`009`009`125 -+-+-+-+-+ End of part 5 +-+-+-+-+-