+-+-+-+ Beginning of part 11 +-+-+-+ X`009Reg9 bool repl_could_be_missing = TRUE; X`009`009`009`009`009/* no + or ! lines in this hunk */ X`009bool repl_missing = FALSE;`009/* we are now backtracking */ X`009long repl_backtrack_position = 0; X`009`009`009`009`009/* file pos of first repl line */ X`009LINENUM repl_patch_line;`009/* input line number for same */ X`009Reg7 LINENUM ptrn_copiable = 0; X`009`009`009`009`009/* # of copiable lines in ptrn */ X X`009ret = pgets(buf, sizeof buf, pfp); X`009p_input_line++; X`009if (ret == Nullch `124`124 strnNE(buf, "********", 8)) `123 X`009 next_intuit_at(line_beginning,p_input_line); X`009 return FALSE; X`009`125 X`009p_context = 100; X`009p_hunk_beg = p_input_line + 1; X`009while (p_end < p_max) `123 X`009 line_beginning = ftell(pfp); X`009 ret = pgets(buf, sizeof buf, pfp); X`009 p_input_line++; X`009 if (ret == Nullch) `123 X`009`009if (p_max - p_end < 4) X`009`009 Strcpy(buf, " \n"); /* assume blank lines got chopped */ X`009`009else `123 X`009`009 if (repl_beginning && repl_could_be_missing) `123 X`009`009`009repl_missing = TRUE; X`009`009`009goto hunk_done; X`009`009 `125 X`009`009 fatal1("Unexpected end of file in patch.\n"); X`009`009`125 X`009 `125 X`009 p_end++; X`009 assert(p_end < hunkmax); X`009 p_char[p_end] = *buf; X#ifdef zilog X`009 p_line[(short)p_end] = Nullch; X#else X`009 p_line[p_end] = Nullch; X#endif X`009 switch (*buf) `123 X`009 case '*': X`009`009if (strnEQ(buf, "********", 8)) `123 X`009`009 if (repl_beginning && repl_could_be_missing) `123 X`009`009`009repl_missing = TRUE; X`009`009`009goto hunk_done; X`009`009 `125 X`009`009 else X`009`009`009fatal2("Unexpected end of hunk at line %ld.\n", X`009`009`009 p_input_line); X`009`009`125 X`009`009if (p_end != 0) `123 X`009`009 if (repl_beginning && repl_could_be_missing) `123 X`009`009`009repl_missing = TRUE; X`009`009`009goto hunk_done; X`009`009 `125 X`009`009 fatal3("Unexpected *** at line %ld: %s", p_input_line, buf); X`009`009`125 X`009`009context = 0; X`009`009p_line[p_end] = savestr(buf); X`009`009if (out_of_mem) `123 X`009`009 p_end--; X`009`009 return FALSE; X`009`009`125 X`009`009for (s=buf; *s && !isdigit(*s); s++) ; X`009`009if (!*s) X`009`009 goto malformed; X`009`009if (strnEQ(s,"0,0",3)) X`009`009 strcpy(s,s+2); X`009`009p_first = (LINENUM) atol(s); X`009`009while (isdigit(*s)) s++; X`009`009if (*s == ',') `123 X`009`009 for (; *s && !isdigit(*s); s++) ; X`009`009 if (!*s) X`009`009`009goto malformed; X`009`009 p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1; X`009`009`125 X`009`009else if (p_first) X`009`009 p_ptrn_lines = 1; X`009`009else `123 X`009`009 p_ptrn_lines = 0; X`009`009 p_first = 1; X`009`009`125 X`009`009p_max = p_ptrn_lines + 6;`009/* we need this much at least */ X`009`009while (p_max >= hunkmax) X`009`009 grow_hunkmax(); X`009`009p_max = hunkmax; X`009`009break; X`009 case '-': X`009`009if (buf[1] == '-') `123 X`009`009 if (repl_beginning `124`124 X`009`009`009(p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n'))) X`009`009 `123 X`009`009`009if (p_end == 1) `123 X`009`009`009 /* `096old' lines were omitted - set up to fill */ X`009`009`009 /* them in from 'new' context lines. */ X`009`009`009 p_end = p_ptrn_lines + 1; X`009`009`009 fillsrc = p_end + 1; X`009`009`009 filldst = 1; X`009`009`009 fillcnt = p_ptrn_lines; X`009`009`009`125 X`009`009`009else `123 X`009`009`009 if (repl_beginning) `123 X`009`009`009`009if (repl_could_be_missing)`123 X`009`009`009`009 repl_missing = TRUE; X`009`009`009`009 goto hunk_done; X`009`009`009`009`125 X`009`009`009`009fatal3( X"Duplicate \"---\" at line %ld--check line numbers at line %ld.\n", X`009`009`009`009 p_input_line, p_hunk_beg + repl_beginning); X`009`009`009 `125 X`009`009`009 else `123 X`009`009`009`009fatal4( X"%s \"---\" at line %ld--check line numbers at line %ld.\n", X`009`009`009`009 (p_end <= p_ptrn_lines X`009`009`009`009`009? "Premature" X`009`009`009`009`009: "Overdue" ), X`009`009`009`009 p_input_line, p_hunk_beg); X`009`009`009 `125 X`009`009`009`125 X`009`009 `125 X`009`009 repl_beginning = p_end; X`009`009 repl_backtrack_position = ftell(pfp); X`009`009 repl_patch_line = p_input_line; X`009`009 p_line[p_end] = savestr(buf); X`009`009 if (out_of_mem) `123 X`009`009`009p_end--; X`009`009`009return FALSE; X`009`009 `125 X`009`009 p_char[p_end] = '='; X`009`009 for (s=buf; *s && !isdigit(*s); s++) ; X`009`009 if (!*s) X`009`009`009goto malformed; X`009`009 p_newfirst = (LINENUM) atol(s); X`009`009 while (isdigit(*s)) s++; X`009`009 if (*s == ',') `123 X`009`009`009for (; *s && !isdigit(*s); s++) ; X`009`009`009if (!*s) X`009`009`009 goto malformed; X`009`009`009p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1; X`009`009 `125 X`009`009 else if (p_newfirst) X`009`009`009p_repl_lines = 1; X`009`009 else `123 X`009`009`009p_repl_lines = 0; X`009`009`009p_newfirst = 1; X`009`009 `125 X`009`009 p_max = p_repl_lines + p_end; X`009`009 if (p_max > MAXHUNKSIZE) X`009`009`009fatal4("Hunk too large (%ld lines) at line %ld: %s", X`009`009`009 p_max, p_input_line, buf); X`009`009 while (p_max >= hunkmax) X`009`009`009grow_hunkmax(); X`009`009 if (p_repl_lines != ptrn_copiable) X`009`009`009repl_could_be_missing = FALSE; X`009`009 break; X`009`009`125 X`009`009goto change_line; X`009 case '+': case '!': X`009`009repl_could_be_missing = FALSE; X`009 change_line: X`009`009if (buf[1] == '\n' && canonicalize) X`009`009 strcpy(buf+1," \n"); X`009`009if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' && X`009`009 repl_beginning && repl_could_be_missing) `123 X`009`009 repl_missing = TRUE; X`009`009 goto hunk_done; X`009`009`125 X`009`009if (context > 0) `123 X`009`009 if (context < p_context) X`009`009`009p_context = context; X`009`009 context = -1000; X`009`009`125 X`009`009p_line[p_end] = savestr(buf+2); X`009`009if (out_of_mem) `123 X`009`009 p_end--; X`009`009 return FALSE; X`009`009`125 X`009`009break; X`009 case '\t': case '\n':`009/* assume the 2 spaces got eaten */ X`009`009if (repl_beginning && repl_could_be_missing && X`009`009 (!ptrn_spaces_eaten `124`124 diff_type == NEW_CONTEXT_DIFF) ) `123 X`009`009 repl_missing = TRUE; X`009`009 goto hunk_done; X`009`009`125 X`009`009p_line[p_end] = savestr(buf); X`009`009if (out_of_mem) `123 X`009`009 p_end--; X`009`009 return FALSE; X`009`009`125 X`009`009if (p_end != p_ptrn_lines + 1) `123 X`009`009 ptrn_spaces_eaten `124= (repl_beginning != 0); X`009`009 context++; X`009`009 if (!repl_beginning) X`009`009`009ptrn_copiable++; X`009`009 p_char[p_end] = ' '; X`009`009`125 X`009`009break; X`009 case ' ': X`009`009if (!isspace(buf[1]) && X`009`009 repl_beginning && repl_could_be_missing) `123 X`009`009 repl_missing = TRUE; X`009`009 goto hunk_done; X`009`009`125 X`009`009context++; X`009`009if (!repl_beginning) X`009`009 ptrn_copiable++; X`009`009p_line[p_end] = savestr(buf+2); X`009`009if (out_of_mem) `123 X`009`009 p_end--; X`009`009 return FALSE; X`009`009`125 X`009`009break; X`009 default: X`009`009if (repl_beginning && repl_could_be_missing) `123 X`009`009 repl_missing = TRUE; X`009`009 goto hunk_done; X`009`009`125 X`009`009goto malformed; X`009 `125 X`009 /* set up p_len for strncmp() so we don't have to */ X`009 /* assume null termination */ X`009 if (p_line[p_end]) X`009`009p_len[p_end] = strlen(p_line[p_end]); X`009 else X`009`009p_len[p_end] = 0; X`009`125 X`009 X hunk_done: X`009if (p_end >=0 && !repl_beginning) X`009 fatal2("No --- found in patch at line %ld\n", pch_hunk_beg()); X X`009if (repl_missing) `123 X`009 X`009 /* reset state back to just after --- */ X`009 p_input_line = repl_patch_line; X`009 for (p_end--; p_end > repl_beginning; p_end--) X`009`009free(p_line[p_end]); X`009 Fseek(pfp, repl_backtrack_position, 0); X`009 X`009 /* redundant 'new' context lines were omitted - set */ X`009 /* up to fill them in from the old file context */ X`009 fillsrc = 1; X`009 filldst = repl_beginning+1; X`009 fillcnt = p_repl_lines; X`009 p_end = p_max; X`009`125 X X`009if (diff_type == CONTEXT_DIFF && X`009 (fillcnt `124`124 (p_first > 1 && ptrn_copiable > 2*p_context)) ) `123 X`009 if (verbose) X`009`009say4("%s\n%s\n%s\n", X"(Fascinating--this is really a new-style context diff but without", X"the telltale extra asterisks on the *** line that usually indicate", X"the new style...)"); X`009 diff_type = NEW_CONTEXT_DIFF; X`009`125 X`009 X`009/* if there were omitted context lines, fill them in now */ X`009if (fillcnt) `123 X`009 p_bfake = filldst;`009`009/* remember where not to free() */ X`009 p_efake = filldst + fillcnt - 1; X`009 while (fillcnt-- > 0) `123 X`009`009while (fillsrc <= p_end && p_char[fillsrc] != ' ') X`009`009 fillsrc++; X`009`009if (fillsrc > p_end) V`009`009 fatal2("Replacement text or line numbers mangled in hunk at line X %ld\n", X`009`009`009p_hunk_beg); X`009`009p_line[filldst] = p_line[fillsrc]; X`009`009p_char[filldst] = p_char[fillsrc]; X`009`009p_len[filldst] = p_len[fillsrc]; X`009`009fillsrc++; filldst++; X`009 `125 X`009 while (fillsrc <= p_end && fillsrc != repl_beginning && X`009 p_char[fillsrc] != ' ') X`009`009fillsrc++; X#ifdef DEBUGGING X`009 if (debug & 64) X`009`009printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n", X`009`009 fillsrc,filldst,repl_beginning,p_end+1); X#endif X`009 assert(fillsrc==p_end+1 `124`124 fillsrc==repl_beginning); X`009 assert(filldst==p_end+1 `124`124 filldst==repl_beginning); X`009`125 X `125 X else `123`009`009`009`009/* normal diff--fake it up */ X`009char hunk_type; X`009Reg3 int i; X`009LINENUM min, max; X`009long line_beginning = ftell(pfp); X X`009p_context = 0; X`009ret = pgets(buf, sizeof buf, pfp); X`009p_input_line++; X`009if (ret == Nullch `124`124 !isdigit(*buf)) `123 X`009 next_intuit_at(line_beginning,p_input_line); X`009 return FALSE; X`009`125 X`009p_first = (LINENUM)atol(buf); X`009for (s=buf; isdigit(*s); s++) ; X`009if (*s == ',') `123 X`009 p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1; X`009 while (isdigit(*s)) s++; X`009`125 X`009else X`009 p_ptrn_lines = (*s != 'a'); X`009hunk_type = *s; X`009if (hunk_type == 'a') X`009 p_first++;`009`009`009/* do append rather than insert */ X`009min = (LINENUM)atol(++s); X`009for (; isdigit(*s); s++) ; X`009if (*s == ',') X`009 max = (LINENUM)atol(++s); X`009else X`009 max = min; X`009if (hunk_type == 'd') X`009 min++; X`009p_end = p_ptrn_lines + 1 + max - min + 1; X`009if (p_end > MAXHUNKSIZE) X`009 fatal4("Hunk too large (%ld lines) at line %ld: %s", X`009`009 p_end, p_input_line, buf); X`009while (p_end >= hunkmax) X`009 grow_hunkmax(); X`009p_newfirst = min; X`009p_repl_lines = max - min + 1; X`009Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1); X`009p_line[0] = savestr(buf); X`009if (out_of_mem) `123 X`009 p_end = -1; X`009 return FALSE; X`009`125 X`009p_char[0] = '*'; X`009for (i=1; i<=p_ptrn_lines; i++) `123 X`009 ret = pgets(buf, sizeof buf, pfp); X`009 p_input_line++; X`009 if (ret == Nullch) X`009`009fatal2("Unexpected end of file in patch at line %ld.\n", X`009`009 p_input_line); X`009 if (*buf != '<') X`009`009fatal2("< expected at line %ld of patch.\n", p_input_line); X`009 p_line[i] = savestr(buf+2); X`009 if (out_of_mem) `123 X`009`009p_end = i-1; X`009`009return FALSE; X`009 `125 X`009 p_len[i] = strlen(p_line[i]); X`009 p_char[i] = '-'; X`009`125 X`009if (hunk_type == 'c') `123 X`009 ret = pgets(buf, sizeof buf, pfp); X`009 p_input_line++; X`009 if (ret == Nullch) X`009`009fatal2("Unexpected end of file in patch at line %ld.\n", X`009`009 p_input_line); X`009 if (*buf != '-') X`009`009fatal2("--- expected at line %ld of patch.\n", p_input_line); X`009`125 X`009Sprintf(buf, "--- %ld,%ld\n", min, max); X`009p_line[i] = savestr(buf); X`009if (out_of_mem) `123 X`009 p_end = i-1; X`009 return FALSE; X`009`125 X`009p_char[i] = '='; X`009for (i++; i<=p_end; i++) `123 X`009 ret = pgets(buf, sizeof buf, pfp); X`009 p_input_line++; X`009 if (ret == Nullch) X`009`009fatal2("Unexpected end of file in patch at line %ld.\n", X`009`009 p_input_line); X`009 if (*buf != '>') X`009`009fatal2("> expected at line %ld of patch.\n", p_input_line); X`009 p_line[i] = savestr(buf+2); X`009 if (out_of_mem) `123 X`009`009p_end = i-1; X`009`009return FALSE; X`009 `125 X`009 p_len[i] = strlen(p_line[i]); X`009 p_char[i] = '+'; X`009`125 X `125 X if (reverse)`009`009`009/* backwards patch? */ X`009if (!pch_swap()) X`009 say1("Not enough memory to swap next hunk!\n"); X#ifdef DEBUGGING X if (debug & 2) `123 X`009int i; X`009char special; X X`009for (i=0; i <= p_end; i++) `123 X`009 if (i == p_ptrn_lines) X`009`009special = '`094'; X`009 else X`009`009special = ' '; X`009 fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]); X`009 Fflush(stderr); X`009`125 X `125 X#endif X if (p_end+1 < hunkmax)`009/* paranoia reigns supreme... */ X`009p_char[p_end+1] = '`094'; /* add a stopper for apply_hunk */ X return TRUE; X Xmalformed: X fatal3("Malformed patch at line %ld: %s", p_input_line, buf); X`009`009/* about as informative as "Syntax error" in C */ X return FALSE;`009/* for lint */ X`125 X X/* Input a line from the patch file, worrying about indentation. */ X Xchar * Xpgets(bf,sz,fp) Xchar *bf; Xint sz; XFILE *fp; X`123 X char *ret = fgets(bf, sz, fp); X Reg1 char *s; X Reg2 int indent = 0; X X if (p_indent && ret != Nullch) `123 X`009for (s=buf; V`009 indent < p_indent && (*s == ' ' `124`124 *s == '\t' `124`124 *s == 'X') X; s++) `123 X`009 if (*s == '\t') X`009`009indent += 8 - (indent % 7); X`009 else X`009`009indent++; X`009`125 X`009if (buf != s) X`009 Strcpy(buf, s); X `125 X return ret; X`125 X X/* Reverse the old and new portions of the current hunk. */ X Xbool Xpch_swap() X`123 X char **tp_line;`009`009/* the text of the hunk */ X short *tp_len;`009`009/* length of each line */ X char *tp_char;`009`009/* +, -, and ! */ X Reg1 LINENUM i; X Reg2 LINENUM n; X bool blankline = FALSE; X Reg3 char *s; X X i = p_first; X p_first = p_newfirst; X p_newfirst = i; X X /* make a scratch copy */ X X tp_line = p_line; X tp_len = p_len; X tp_char = p_char; X p_line = Null(char**);`009/* force set_hunkmax to allocate again */ X p_len = Null(short*); X p_char = Nullch; X set_hunkmax(); V if (p_line == Null(char**) `124`124 p_len == Null(short*) `124`124 p_char X == Nullch) `123 X#ifndef lint X`009if (p_line == Null(char**)) X`009 free((char*)p_line); X`009p_line = tp_line; X`009if (p_len == Null(short*)) X`009 free((char*)p_len); -+-+-+-+-+ End of part 11 +-+-+-+-+-