-+-+-+-+-+-+-+-+ START OF PART 4 -+-+-+-+-+-+-+-+ X`09 p_start = previous_line; X`09 p_sline = p_input_line - 1; X`09 retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF); X`09 goto scan_exit; X`09`7D X`09if ((!diff_type `7C`7C diff_type == NORMAL_DIFF) &&`20 X`09 last_line_was_command && X`09 (strnEQ(s, "< ", 2) `7C`7C strnEQ(s, "> ", 2)) ) `7B X`09 p_start = previous_line; X`09 p_sline = p_input_line - 1; X`09 p_indent = indent; X`09 retval = NORMAL_DIFF; X`09 goto scan_exit; X`09`7D X `7D X scan_exit: X if (no_filearg) `7B X`09if (indtmp != Nullch) X`09 indname = fetchname(indtmp, strippath, ok_to_create_file); X`09if (oldtmp != Nullch) X`09 oldname = fetchname(oldtmp, strippath, ok_to_create_file); X`09if (newtmp != Nullch) X`09 newname = fetchname(newtmp, strippath, ok_to_create_file); X`09if (oldname && newname) `7B X`09 if (strlen(oldname) < strlen(newname)) X`09`09filearg`5B0`5D = savestr(oldname); X`09 else X`09`09filearg`5B0`5D = savestr(newname); X`09`7D X`09else if (oldname) X`09 filearg`5B0`5D = savestr(oldname); X`09else if (newname) X`09 filearg`5B0`5D = savestr(newname); X`09else if (indname) X`09 filearg`5B0`5D = savestr(indname); X `7D X if (bestguess) `7B X`09free(bestguess); X`09bestguess = Nullch; X `7D X if (filearg`5B0`5D != Nullch) X`09bestguess = savestr(filearg`5B0`5D); X else if (indtmp != Nullch) X`09bestguess = fetchname(indtmp, strippath, TRUE); X else `7B X`09if (oldtmp != Nullch) X`09 oldname = fetchname(oldtmp, strippath, TRUE); X`09if (newtmp != Nullch) X`09 newname = fetchname(newtmp, strippath, TRUE); X`09if (oldname && newname) `7B X`09 if (strlen(oldname) < strlen(newname)) X`09`09bestguess = savestr(oldname); X`09 else X`09`09bestguess = savestr(newname); X`09`7D X`09else if (oldname) X`09 bestguess = savestr(oldname); X`09else if (newname) X`09 bestguess = savestr(newname); X `7D X if (indtmp != Nullch) X`09free(indtmp); X if (oldtmp != Nullch) X`09free(oldtmp); X if (newtmp != Nullch) X`09free(newtmp); X if (indname != Nullch) X`09free(indname); X if (oldname != Nullch) X`09free(oldname); X if (newname != Nullch) X`09free(newname); X return retval; X`7D X X/* Remember where this patch ends so we know where to start up again. */ X Xvoid Xnext_intuit_at(file_pos,file_line) Xlong file_pos; Xlong file_line; X`7B X p_base = file_pos; X p_bline = file_line; X`7D X X/* Basically a verbose fseek() to the actual diff listing. */ X Xvoid Xskip_to(file_pos,file_line) Xlong file_pos; Xlong file_line; X`7B X char *ret; X X assert(p_base <= file_pos); X if (verbose && p_base < file_pos) `7B X`09Fseek(pfp, p_base, 0); X`09say1("The text leading up to this was:\n--------------------------\n"); X`09while (ftell(pfp) < file_pos) `7B X`09 ret = fgets(buf, sizeof buf, pfp); X`09 assert(ret != Nullch); X`09 say2("`7C%s", buf); X`09`7D X`09say1("--------------------------\n"); X `7D X else X`09Fseek(pfp, file_pos, 0); X p_input_line = file_line - 1; X`7D X X/* True if there is more of the current diff listing to process. */ X Xbool Xanother_hunk() X`7B X Reg1 char *s; X Reg8 char *ret; X Reg2 int context = 0; X X while (p_end >= 0) `7B X`09if (p_end == p_efake) X`09 p_end = p_bfake;`09`09/* don't free twice */ X`09else X`09 free(p_line`5Bp_end`5D); X`09p_end--; X `7D X assert(p_end == -1); X p_efake = -1; X X p_max = hunkmax;`09`09`09/* gets reduced when --- found */ X if (diff_type == CONTEXT_DIFF `7C`7C diff_type == NEW_CONTEXT_DIFF) `7B X`09long line_beginning = ftell(pfp); X`09`09`09`09`09/* file pos of the current line */ X`09LINENUM repl_beginning = 0;`09/* index of --- line */ X`09Reg4 LINENUM fillcnt = 0;`09/* #lines of missing ptrn or repl */ X`09Reg5 LINENUM fillsrc;`09`09/* index of first line to copy */ X`09Reg6 LINENUM filldst;`09`09/* index of first missing line */ X`09bool ptrn_spaces_eaten = FALSE;`09/* ptrn was slightly misformed */ X`09Reg9 bool repl_could_be_missing = TRUE; X`09`09`09`09`09/* no + or ! lines in this hunk */ X`09bool repl_missing = FALSE;`09/* we are now backtracking */ X`09long repl_backtrack_position = 0; X`09`09`09`09`09/* file pos of first repl line */ X`09LINENUM repl_patch_line;`09/* input line number for same */ X`09Reg7 LINENUM ptrn_copiable = 0; X`09`09`09`09`09/* # of copiable lines in ptrn */ X X`09ret = pgets(buf, sizeof buf, pfp); X`09p_input_line++; X`09if (ret == Nullch `7C`7C strnNE(buf, "********", 8)) `7B X`09 next_intuit_at(line_beginning,p_input_line); X`09 return FALSE; X`09`7D X`09p_context = 100; X`09p_hunk_beg = p_input_line + 1; X`09while (p_end < p_max) `7B X`09 line_beginning = ftell(pfp); X`09 ret = pgets(buf, sizeof buf, pfp); X`09 p_input_line++; X`09 if (ret == Nullch) `7B X`09`09if (p_max - p_end < 4) X`09`09 Strcpy(buf, " \n"); /* assume blank lines got chopped */ X`09`09else `7B X`09`09 if (repl_beginning && repl_could_be_missing) `7B X`09`09`09repl_missing = TRUE; X`09`09`09goto hunk_done; X`09`09 `7D X`09`09 fatal1("Unexpected end of file in patch.\n"); X`09`09`7D X`09 `7D X`09 p_end++; X`09 assert(p_end < hunkmax); X`09 p_char`5Bp_end`5D = *buf; X`09 p_line`5Bp_end`5D = Nullch; X`09 switch (*buf) `7B X`09 case '*': X`09`09if (strnEQ(buf, "********", 8)) `7B X`09`09 if (repl_beginning && repl_could_be_missing) `7B X`09`09`09repl_missing = TRUE; X`09`09`09goto hunk_done; X`09`09 `7D X`09`09 else X`09`09`09fatal2("Unexpected end of hunk at line %ld.\n", X`09`09`09 p_input_line); X`09`09`7D X`09`09if (p_end != 0) `7B X`09`09 if (repl_beginning && repl_could_be_missing) `7B X`09`09`09repl_missing = TRUE; X`09`09`09goto hunk_done; X`09`09 `7D X`09`09 fatal3("Unexpected *** at line %ld: %s", p_input_line, buf); X`09`09`7D X`09`09context = 0; X`09`09p_line`5Bp_end`5D = savestr(buf); X`09`09if (out_of_mem) `7B X`09`09 p_end--; X`09`09 return FALSE; X`09`09`7D X`09`09for (s=buf; *s && !isdigit(*s); s++) ; X`09`09if (!*s) X`09`09 goto malformed; X`09`09p_first = (LINENUM) atol(s); X`09`09while (isdigit(*s)) s++; X`09`09if (*s == ',') `7B X`09`09 for (; *s && !isdigit(*s); s++) ; X`09`09 if (!*s) X`09`09`09goto malformed; X`09`09 p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1; X`09`09`7D X`09`09else if (p_first) X`09`09 p_ptrn_lines = 1; X`09`09else `7B X`09`09 p_ptrn_lines = 0; X`09`09 p_first = 1; X`09`09`7D X`09`09p_max = p_ptrn_lines + 6;`09/* we need this much at least */ X`09`09while (p_max >= hunkmax) X`09`09 grow_hunkmax(); X`09`09p_max = hunkmax; X`09`09break; X`09 case '-': X`09`09if (buf`5B1`5D == '-') `7B X`09`09 if (repl_beginning `7C`7C X`09`09`09(p_end != p_ptrn_lines + 1 + (p_char`5Bp_end-1`5D == '\n'))) X`09`09 `7B X`09`09`09if (p_end == 1) `7B X`09`09`09 /* `60old' lines were omitted - set up to fill */ X`09`09`09 /* them in from 'new' context lines. */ X`09`09`09 p_end = p_ptrn_lines + 1; X`09`09`09 fillsrc = p_end + 1; X`09`09`09 filldst = 1; X`09`09`09 fillcnt = p_ptrn_lines; X`09`09`09`7D X`09`09`09else `7B X`09`09`09 if (repl_beginning) `7B X`09`09`09`09if (repl_could_be_missing)`7B X`09`09`09`09 repl_missing = TRUE; X`09`09`09`09 goto hunk_done; X`09`09`09`09`7D X`09`09`09`09fatal3( X"Duplicate \"---\" at line %ld--check line numbers at line %ld.\n", X`09`09`09`09 p_input_line, p_hunk_beg + repl_beginning); X`09`09`09 `7D X`09`09`09 else `7B X`09`09`09`09fatal4( X"%s \"---\" at line %ld--check line numbers at line %ld.\n", X`09`09`09`09 (p_end <= p_ptrn_lines X`09`09`09`09`09? "Premature" X`09`09`09`09`09: "Overdue" ), X`09`09`09`09 p_input_line, p_hunk_beg); X`09`09`09 `7D X`09`09`09`7D X`09`09 `7D X`09`09 repl_beginning = p_end; X`09`09 repl_backtrack_position = ftell(pfp); X`09`09 repl_patch_line = p_input_line; X`09`09 p_line`5Bp_end`5D = savestr(buf); X`09`09 if (out_of_mem) `7B X`09`09`09p_end--; X`09`09`09return FALSE; X`09`09 `7D X`09`09 p_char`5Bp_end`5D = '='; X`09`09 for (s=buf; *s && !isdigit(*s); s++) ; X`09`09 if (!*s) X`09`09`09goto malformed; X`09`09 p_newfirst = (LINENUM) atol(s); X`09`09 while (isdigit(*s)) s++; X`09`09 if (*s == ',') `7B X`09`09`09for (; *s && !isdigit(*s); s++) ; X`09`09`09if (!*s) X`09`09`09 goto malformed; X`09`09`09p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1; X`09`09 `7D X`09`09 else if (p_newfirst) X`09`09`09p_repl_lines = 1; X`09`09 else `7B X`09`09`09p_repl_lines = 0; X`09`09`09p_newfirst = 1; X`09`09 `7D X`09`09 p_max = p_repl_lines + p_end; X`09`09 if (p_max > MAXHUNKSIZE) X`09`09`09fatal4("Hunk too large (%ld lines) at line %ld: %s", X`09`09`09 p_max, p_input_line, buf); X`09`09 while (p_max >= hunkmax) X`09`09`09grow_hunkmax(); X`09`09 if (p_repl_lines != ptrn_copiable) X`09`09`09repl_could_be_missing = FALSE; X`09`09 break; X`09`09`7D X`09`09goto change_line; X`09 case '+': case '!': X`09`09repl_could_be_missing = FALSE; X`09 change_line: X`09`09if (!isspace(buf`5B1`5D) && buf`5B1`5D != '>' && buf`5B1`5D != '<' && X`09`09 repl_beginning && repl_could_be_missing) `7B X`09`09 repl_missing = TRUE; X`09`09 goto hunk_done; X`09`09`7D X`09`09if (context > 0) `7B X`09`09 if (context < p_context) X`09`09`09p_context = context; X`09`09 context = -1000; X`09`09`7D X`09`09p_line`5Bp_end`5D = savestr(buf+2); X`09`09if (out_of_mem) `7B X`09`09 p_end--; X`09`09 return FALSE; X`09`09`7D X`09`09break; X`09 case '\t': case '\n':`09/* assume the 2 spaces got eaten */ X`09`09if (repl_beginning && repl_could_be_missing && X`09`09 (!ptrn_spaces_eaten `7C`7C diff_type == NEW_CONTEXT_DIFF) ) `7B X`09`09 repl_missing = TRUE; X`09`09 goto hunk_done; X`09`09`7D X`09`09p_line`5Bp_end`5D = savestr(buf); X`09`09if (out_of_mem) `7B X`09`09 p_end--; X`09`09 return FALSE; X`09`09`7D X`09`09if (p_end != p_ptrn_lines + 1) `7B X`09`09 ptrn_spaces_eaten `7C= (repl_beginning != 0); X`09`09 context++; X`09`09 if (!repl_beginning) X`09`09`09ptrn_copiable++; X`09`09 p_char`5Bp_end`5D = ' '; X`09`09`7D X`09`09break; X`09 case ' ': X`09`09if (!isspace(buf`5B1`5D) && X`09`09 repl_beginning && repl_could_be_missing) `7B X`09`09 repl_missing = TRUE; X`09`09 goto hunk_done; X`09`09`7D X`09`09context++; X`09`09if (!repl_beginning) X`09`09 ptrn_copiable++; X`09`09p_line`5Bp_end`5D = savestr(buf+2); X`09`09if (out_of_mem) `7B X`09`09 p_end--; X`09`09 return FALSE; X`09`09`7D X`09`09break; X`09 default: X`09`09if (repl_beginning && repl_could_be_missing) `7B X`09`09 repl_missing = TRUE; X`09`09 goto hunk_done; X`09`09`7D X`09`09goto malformed; X`09 `7D X`09 /* set up p_len for strncmp() so we don't have to */ X`09 /* assume null termination */ X`09 if (p_line`5Bp_end`5D) X`09`09p_len`5Bp_end`5D = strlen(p_line`5Bp_end`5D); X`09 else X`09`09p_len`5Bp_end`5D = 0; X`09`7D X`09 X hunk_done: X`09if (p_end >=0 && !repl_beginning) X`09 fatal2("No --- found in patch at line %ld\n", pch_hunk_beg()); X X`09if (repl_missing) `7B X`09 `20 X`09 /* reset state back to just after --- */ X`09 p_input_line = repl_patch_line; X`09 for (p_end--; p_end > repl_beginning; p_end--) X`09`09free(p_line`5Bp_end`5D); X`09 Fseek(pfp, repl_backtrack_position, 0); X`09 `20 X`09 /* redundant 'new' context lines were omitted - set */ X`09 /* up to fill them in from the old file context */ X`09 fillsrc = 1; X`09 filldst = repl_beginning+1; X`09 fillcnt = p_repl_lines; X`09 p_end = p_max; X`09`7D X X`09if (diff_type == CONTEXT_DIFF && X`09 (fillcnt `7C`7C (p_first > 1 && ptrn_copiable > 2*p_context)) ) `7B X`09 if (verbose) X`09`09say1("\ X(Fascinating--this is really a new-style context diff but without the tellta Vle\n\ Xextra asterisks on the *** line that usually indicate the new style...)\n"); X`09 diff_type = NEW_CONTEXT_DIFF; X`09`7D X`09 X`09/* if there were omitted context lines, fill them in now */ X`09if (fillcnt) `7B X`09 p_bfake = filldst;`09`09/* remember where not to free() */ X`09 p_efake = filldst + fillcnt - 1; X`09 while (fillcnt-- > 0) `7B X`09`09while (fillsrc <= p_end && p_char`5Bfillsrc`5D != ' ') X`09`09 fillsrc++; X`09`09if (fillsrc > p_end) X`09`09 fatal2("Replacement text or line numbers mangled in hunk at line % Vld\n", X`09`09`09p_hunk_beg); X`09`09p_line`5Bfilldst`5D = p_line`5Bfillsrc`5D; X`09`09p_char`5Bfilldst`5D = p_char`5Bfillsrc`5D; X`09`09p_len`5Bfilldst`5D = p_len`5Bfillsrc`5D; X`09`09fillsrc++; filldst++; X`09 `7D X`09 while (fillsrc <= p_end && fillsrc != repl_beginning && X`09 p_char`5Bfillsrc`5D != ' ') X`09`09fillsrc++; X#ifdef DEBUGGING X`09 if (debug & 64) X`09`09printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n", X`09`09 fillsrc,filldst,repl_beginning,p_end+1); X#endif X`09 assert(fillsrc==p_end+1 `7C`7C fillsrc==repl_beginning); X`09 assert(filldst==p_end+1 `7C`7C filldst==repl_beginning); X`09`7D X `7D X else `7B`09`09`09`09/* normal diff--fake it up */ X`09char hunk_type; X`09Reg3 int i; X`09LINENUM min, max; X`09long line_beginning = ftell(pfp); X X`09p_context = 0; X`09ret = pgets(buf, sizeof buf, pfp); X`09p_input_line++; X`09if (ret == Nullch `7C`7C !isdigit(*buf)) `7B X`09 next_intuit_at(line_beginning,p_input_line); X`09 return FALSE; X`09`7D X`09p_first = (LINENUM)atol(buf); X`09for (s=buf; isdigit(*s); s++) ; X`09if (*s == ',') `7B X`09 p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1; X`09 while (isdigit(*s)) s++; X`09`7D X`09else X`09 p_ptrn_lines = (*s != 'a'); X`09hunk_type = *s; X`09if (hunk_type == 'a') X`09 p_first++;`09`09`09/* do append rather than insert */ X`09min = (LINENUM)atol(++s); X`09for (; isdigit(*s); s++) ; X`09if (*s == ',') X`09 max = (LINENUM)atol(++s); X`09else X`09 max = min; X`09if (hunk_type == 'd') X`09 min++; X`09p_end = p_ptrn_lines + 1 + max - min + 1; X`09if (p_end > MAXHUNKSIZE) X`09 fatal4("Hunk too large (%ld lines) at line %ld: %s", X`09`09 p_end, p_input_line, buf); X`09while (p_end >= hunkmax) X`09 grow_hunkmax(); X`09p_newfirst = min; X`09p_repl_lines = max - min + 1; X`09Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1); X`09p_line`5B0`5D = savestr(buf); X`09if (out_of_mem) `7B X`09 p_end = -1; X`09 return FALSE; X`09`7D X`09p_char`5B0`5D = '*'; X`09for (i=1; i<=p_ptrn_lines; i++) `7B X`09 ret = pgets(buf, sizeof buf, pfp); X`09 p_input_line++; X`09 if (ret == Nullch) X`09`09fatal2("Unexpected end of file in patch at line %ld.\n", X`09`09 p_input_line); X`09 if (*buf != '<') X`09`09fatal2("< expected at line %ld of patch.\n", p_input_line); X`09 p_line`5Bi`5D = savestr(buf+2); X`09 if (out_of_mem) `7B X`09`09p_end = i-1; X`09`09return FALSE; X`09 `7D X`09 p_len`5Bi`5D = strlen(p_line`5Bi`5D); X`09 p_char`5Bi`5D = '-'; X`09`7D X`09if (hunk_type == 'c') `7B X`09 ret = pgets(buf, sizeof buf, pfp); X`09 p_input_line++; X`09 if (ret == Nullch) X`09`09fatal2("Unexpected end of file in patch at line %ld.\n", X`09`09 p_input_line); X`09 if (*buf != '-') X`09`09fatal2("--- expected at line %ld of patch.\n", p_input_line); X`09`7D X`09Sprintf(buf, "--- %ld,%ld\n", min, max); X`09p_line`5Bi`5D = savestr(buf); X`09if (out_of_mem) `7B X`09 p_end = i-1; X`09 return FALSE; X`09`7D X`09p_char`5Bi`5D = '='; X`09for (i++; i<=p_end; i++) `7B X`09 ret = pgets(buf, sizeof buf, pfp); X`09 p_input_line++; X`09 if (ret == Nullch) X`09`09fatal2("Unexpected end of file in patch at line %ld.\n", X`09`09 p_input_line); X`09 if (*buf != '>') X`09`09fatal2("> expected at line %ld of patch.\n", p_input_line); X`09 p_line`5Bi`5D = savestr(buf+2); X`09 if (out_of_mem) `7B X`09`09p_end = i-1; X`09`09return FALSE; X`09 `7D X`09 p_len`5Bi`5D = strlen(p_line`5Bi`5D); X`09 p_char`5Bi`5D = '+'; X`09`7D X `7D X if (reverse)`09`09`09/* backwards patch? */ X`09if (!pch_swap()) X`09 say1("Not enough memory to swap next hunk!\n"); X#ifdef DEBUGGING X if (debug & 2) `7B X`09int i; X`09char special; X X`09for (i=0; i <= p_end; i++) `7B X`09 if (i == p_ptrn_lines) X`09`09special = '`5E'; X`09 else X`09`09special = ' '; X`09 fprintf(stderr, "%3d %c %c %s", i, p_char`5Bi`5D, special, p_line`5Bi V`5D); X`09 Fflush(stderr); X`09`7D X `7D X#endif X if (p_end+1 < hunkmax)`09/* paranoia reigns supreme... */ X`09p_char`5Bp_end+1`5D = '`5E'; /* add a stopper for apply_hunk */ X return TRUE; X Xmalformed: X fatal3("Malformed patch at line %ld: %s", p_input_line, buf); X`09`09/* about as informative as "Syntax error" in C */ X return FALSE;`09/* for lint */ X`7D 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`7B X char *ret = fgets(bf, sz, fp); X Reg1 char *s; X Reg2 int indent = 0; X X if (p_indent && ret != Nullch) `7B X`09for (s=buf; indent < p_indent && (*s == ' ' `7C`7C *s == '\t'); s++) `7B X`09 if (*s == '\t') X`09`09indent += 8 - (indent % 7); X`09 else X`09`09indent++; X`09`7D X`09if (buf != s) X`09 Strcpy(buf, s); X `7D X return ret; X`7D X X/* Reverse the old and new portions of the current hunk. */ X Xbool Xpch_swap() X`7B X char **tp_line;`09`09/* the text of the hunk */ X short *tp_len;`09`09/* length of each line */ X char *tp_char;`09`09/* +, -, 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 `20 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**);`09/* force set_hunkmax to allocate again */ X p_len = Null(short*); X p_char = Nullch; X set_hunkmax(); X if (p_line == Null(char**) `7C`7C p_len == Null(short*) `7C`7C p_char == V Nullch) `7B X#ifndef lint X`09if (p_line == Null(char**)) X`09 free((char*)p_line); X`09p_line = tp_line; X`09if (p_len == Null(short*)) X`09 free((char*)p_len); X`09p_len = tp_len; X#endif X`09if (p_char == Nullch) X`09 free((char*)p_char); X`09p_char = tp_char; X`09return FALSE;`09`09/* not enough memory to swap hunk! */ X `7D X X /* now turn the new into the old */ X X i = p_ptrn_lines + 1; X if (tp_char`5Bi`5D == '\n') `7B`09`09/* account for possible blank line V */ X`09blankline = TRUE; X`09i++; X `7D X if (p_efake >= 0) `7B`09`09`09/* fix non-freeable ptr range */ X`09n = p_end - i + 1; X`09if (p_efake > i) X`09 n = -n; X`09p_efake += n; X`09p_bfake += n; X `7D X for (n=0; i <= p_end; i++,n++) `7B X`09p_line`5Bn`5D = tp_line`5Bi`5D; X`09p_char`5Bn`5D = tp_char`5Bi`5D; X`09if (p_char`5Bn`5D == '+') X`09 p_char`5Bn`5D = '-'; X`09p_len`5Bn`5D = tp_len`5Bi`5D; X `7D X if (blankline) `7B X`09i = p_ptrn_lines + 1; X`09p_line`5Bn`5D = tp_line`5Bi`5D; X`09p_char`5Bn`5D = tp_char`5Bi`5D; X`09p_len`5Bn`5D = tp_len`5Bi`5D; X`09n++; X `7D X assert(p_char`5B0`5D == '='); X p_char`5B0`5D = '*'; X for (s=p_line`5B0`5D; *s; s++) X`09if (*s == '-') X`09 *s = '*'; X X /* now turn the old into the new */ X X assert(tp_char`5B0`5D == '*'); X tp_char`5B0`5D = '='; X for (s=tp_line`5B0`5D; *s; s++) X`09if (*s == '*') X`09 *s = '-'; X for (i=0; n <= p_end; i++,n++) `7B X`09p_line`5Bn`5D = tp_line`5Bi`5D; X`09p_char`5Bn`5D = tp_char`5Bi`5D; X`09if (p_char`5Bn`5D == '-') X`09 p_char`5Bn`5D = '+'; X`09p_len`5Bn`5D = tp_len`5Bi`5D; X `7D X assert(i == p_ptrn_lines + 1); X i = p_ptrn_lines; X p_ptrn_lines = p_repl_lines; X p_repl_lines = i; X#ifndef lint X if (tp_line == Null(char**)) X`09free((char*)tp_line); X if (tp_len == Null(short*)) X`09free((char*)tp_len); X#endif X if (tp_char == Nullch) X`09free((char*)tp_char); X return TRUE; X`7D X X/* Return the specified line position in the old file of the old context. */ X XLINENUM Xpch_first() X`7B X return p_first; X`7D X X/* Return the number of lines of old context. */ X XLINENUM Xpch_ptrn_lines() X`7B X return p_ptrn_lines; X`7D X X/* Return the probable line position in the new file of the first line. */ X XLINENUM Xpch_newfirst() X`7B X return p_newfirst; X`7D X X/* Return the number of lines in the replacement text including context. */ X XLINENUM Xpch_repl_lines() X`7B X return p_repl_lines; X`7D X X/* Return the number of lines in the whole hunk. */ X XLINENUM Xpch_end() X`7B X return p_end; X`7D X X/* Return the number of context lines before the first changed line. */ X XLINENUM Xpch_context() X`7B X return p_context; X`7D X X/* Return the length of a particular patch line. */ X Xshort Xpch_line_len(line) XLINENUM line; X`7B X return p_len`5Bline`5D; X`7D X X/* Return the control character (+, -, *, !, etc) for a patch line. */ X Xchar Xpch_char(line) XLINENUM line; X`7B X return p_char`5Bline`5D; X`7D X X/* Return a pointer to a particular patch line. */ X Xchar * Xpfetch(line) XLINENUM line; X`7B X return p_line`5Bline`5D; X`7D X X/* Return where in the patch file this hunk began, for error messages. */ X XLINENUM Xpch_hunk_beg() X`7B X return p_hunk_beg; X`7D X X/* Apply an ed script by feeding ed itself. */ X Xvoid Xdo_ed_script() X`7B X#ifdef VMS X printf ("Sorry, there's no ed on VMS.\n"); X exit(0); X#else X Reg1 char *t; X Reg2 long beginning_of_this_line; X Reg3 bool this_line_is_command = FALSE; X Reg4 FILE *pipefp; X FILE *popen(); X X if (!skip_rest_of_patch) `7B X`09while (unlink(TMPOUTNAME) >= 0); X`09copy_file(filearg`5B0`5D, TMPOUTNAME); X`09if (verbose) X`09 Sprintf(buf, "/bin/ed %s", TMPOUTNAME); X`09else X`09 Sprintf(buf, "/bin/ed - %s", TMPOUTNAME); X`09pipefp = popen(buf, "w"); X `7D X for (;;) `7B X`09beginning_of_this_line = ftell(pfp); X`09if (pgets(buf, sizeof buf, pfp) == Nullch) `7B X`09 next_intuit_at(beginning_of_this_line,p_input_line); X`09 break; X`09`7D X`09p_input_line++; X`09for (t=buf; isdigit(*t) `7C`7C *t == ','; t++) ; X`09this_line_is_command = (isdigit(*buf) && X`09 (*t == 'd' `7C`7C *t == 'c' `7C`7C *t == 'a') ); X`09if (this_line_is_command) `7B X`09 if (!skip_rest_of_patch) X`09`09fputs(buf, pipefp); X`09 if (*t != 'd') `7B X`09`09while (pgets(buf, sizeof buf, pfp) != Nullch) `7B X`09`09 p_input_line++; X`09`09 if (!skip_rest_of_patch) X`09`09`09fputs(buf, pipefp); X`09`09 if (strEQ(buf, ".\n")) X`09`09`09break; X`09`09`7D X`09 `7D X`09`7D X`09else `7B X`09 next_intuit_at(beginning_of_this_line,p_input_line); X`09 break; X`09`7D X `7D X if (skip_rest_of_patch) X`09return; X fprintf(pipefp, "w\n"); X fprintf(pipefp, "q\n"); X Fflush(pipefp); X Pclose(pipefp); X ignore_signals(); X if (move_file(TMPOUTNAME, outname) < 0) `7B X`09toutkeep = TRUE; X`09chmod(TMPOUTNAME, filemode); X `7D X else X`09chmod(outname, filemode); X set_signals(); X#endif /* VMS */ X`7D $ CALL UNPACK [.SRC]PCH.C;1 830158556 $ create 'f' X/* $Header: pch.h,v 2.0.1.1 87/01/30 22:47:16 lwall Exp $ X * X * $Log:`09pch.h,v $ X * Revision 2.0.1.1 87/01/30 22:47:16 lwall X * Added do_ed_script(). X *`20 X * Revision 2.0 86/09/17 15:39:57 lwall X * Baseline for netwide release. X *`20 X */ X XEXT FILE *pfp INIT(Nullfp);`09`09/* patch file pointer */ X Xvoid re_patch(); Xvoid open_patch_file(); Xvoid set_hunkmax(); Xvoid grow_hunkmax(); Xbool there_is_another_patch(); Xint intuit_diff_type(); Xvoid next_intuit_at(); Xvoid skip_to(); Xbool another_hunk(); Xbool pch_swap(); Xchar *pfetch(); Xshort pch_line_len(); XLINENUM pch_first(); XLINENUM pch_ptrn_lines(); XLINENUM pch_newfirst(); XLINENUM pch_repl_lines(); XLINENUM pch_end(); XLINENUM pch_context(); XLINENUM pch_hunk_beg(); Xchar pch_char(); Xchar *pfetch(); Xchar *pgets(); Xvoid do_ed_script(); $ CALL UNPACK [.SRC]PCH.H;1 1832979341 $ create 'f' X#include "EXTERN.h" X#include "common.h" X#include "INTERN.h" X#include "util.h" X X/* Rename a file, copying it if necessary. */ X Xint Xmove_file(from,to) Xchar *from, *to; X`7B X char bakname`5B512`5D; X Reg1 char *s; X Reg2 int i; X Reg3 int fromfd; X X /* to stdout? */ X X if (strEQ(to, "-")) `7B X#ifdef DEBUGGING X`09if (debug & 4) X`09 say2("Moving %s to stdout.\n", from); X#endif X#ifdef VMS X`09fromfd = open(from, 0, "mbc=64", "mbf=2"); X#else X `09fromfd = open(from, 0); X#endif X`09if (fromfd < 0) X`09 fatal2("patch: internal error, can't reopen %s\n", from); X`09while ((i=read(fromfd, buf, sizeof buf)) > 0) X`09 if (write(1, buf, i) != 1) X`09`09fatal1("patch: write failed\n"); X`09Close(fromfd); X`09return 0; X `7D X X#ifdef VMS X /* This is not robust -- we just rename the file, hoping for the best. * V/ X /* This is not efficient, but for simplicity sake, we simply copy`09*/ X /* the file, and remove the source.`09`09`09`09`09*/ X copy_file(from, to); X delete(from); X return 0; X#else X Strcpy(bakname, to); X Strcat(bakname, origext?origext:ORIGEXT); X if (stat(to, &filestat) >= 0) `7B`09/* output file exists */ X`09dev_t to_device = filestat.st_dev; X`09ino_t to_inode = filestat.st_ino; X`09char *simplename = bakname; X`09 X`09for (s=bakname; *s; s++) `7B X`09 if (*s == '/') X`09`09simplename = s+1; X`09`7D X`09/* find a backup name that is not the same file */ X`09while (stat(bakname, &filestat) >= 0 && X`09`09to_device == filestat.st_dev && to_inode == filestat.st_ino) `7B X`09 for (s=simplename; *s && !islower(*s); s++) ; X`09 if (*s) X`09`09*s = toupper(*s); X`09 else X`09`09Strcpy(simplename, simplename+1); X`09`7D X`09while (unlink(bakname) >= 0) ;`09/* while() is for benefit of Eunice */ X#ifdef DEBUGGING X`09if (debug & 4) X`09 say3("Moving %s to %s.\n", to, bakname); X#endif X`09if (link(to, bakname) < 0) `7B X`09 say3("patch: can't backup %s, output is in %s\n", X`09`09to, from); X`09 return -1; X`09`7D X`09while (unlink(to) >= 0) ; X `7D X#ifdef DEBUGGING X if (debug & 4) X`09say3("Moving %s to %s.\n", from, to); X#endif X if (link(from, to) < 0) `7B`09`09/* different file system? */ X`09Reg4 int tofd; X`09 X`09tofd = creat(to, 0666); X`09if (tofd < 0) `7B X`09 say3("patch: can't create %s, output is in %s.\n", X`09 to, from); X`09 return -1; X`09`7D X`09fromfd = open(from, 0); X`09if (fromfd < 0) X`09 fatal2("patch: internal error, can't reopen %s\n", from); X`09while ((i=read(fromfd, buf, sizeof buf)) > 0) X`09 if (write(tofd, buf, i) != i) X`09`09fatal1("patch: write failed\n"); X`09Close(fromfd); X`09Close(tofd); X `7D X Unlink(from); X#endif /* VMS */ X return 0; X`7D X X/* Copy a file. */ X Xvoid Xcopy_file(from,to) Xchar *from, *to; X`7B X Reg3 int tofd; X Reg2 int fromfd; X Reg1 int i; X `20 X tofd = creat(to, 0666 X#ifdef VMS X`09`09`09, "mbc=64", "mbf=2" X#endif X`09`09`09`09); X if (tofd < 0) X`09fatal2("patch: can't create %s.\n", to); X fromfd = open(from, 0 X#ifdef VMS X`09`09`09, "mbc=64", "mbf=2" X#endif X`09`09`09`09); X if (fromfd < 0) X`09fatal2("patch: internal error, can't reopen %s\n", from); X while ((i=read(fromfd, buf, sizeof buf)) > 0) X`09if (write(tofd, buf, i) != i) X`09 fatal2("patch: write (%s) failed\n", to); X Close(fromfd); X Close(tofd); X`7D X X/* Allocate a unique area for a string. */ X Xchar * Xsavestr(s) XReg1 char *s; X`7B X Reg3 char *rv; X Reg2 char *t; X X if (!s) X`09s = "Oops"; X t = s; X while (*t++); X rv = malloc((MEM) (t - s)); X if (rv == Nullch) `7B X`09if (using_plan_a) X`09 out_of_mem = TRUE; X`09else X`09 fatal1("patch: out of memory (savestr)\n"); X `7D X else `7B X`09t = rv; X`09while (*t++ = *s++); X `7D X return rv; X`7D X X#if defined(lint) && defined(CANVARARG) X X/*VARARGS ARGSUSED*/ Xsay(pat) char *pat; `7B ; `7D X/*VARARGS ARGSUSED*/ Xfatal(pat) char *pat; `7B ; `7D X/*VARARGS ARGSUSED*/ Xask(pat) char *pat; `7B ; `7D X X#else X X/* Vanilla terminal output (buffered). */ X Xvoid Xsay(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`7B X fprintf(stderr, pat, arg1, arg2, arg3); X Fflush(stderr); X`7D X X/* Terminal output, pun intended. */ X Xvoid`09`09`09`09/* very void */ Xfatal(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`7B X void my_exit(); X X say(pat, arg1, arg2, arg3); X my_exit(1); X`7D X X/* Get a response from the user, somehow or other. */ X Xvoid Xask(pat,arg1,arg2,arg3) Xchar *pat; Xint arg1,arg2,arg3; X`7B X int ttyfd; X int r; X bool tty2 = isatty(2); X X Sprintf(buf, pat, arg1, arg2, arg3); X Fflush(stderr); X write(2, buf, strlen(buf)); X if (tty2) `7B`09`09`09`09/* might be redirected to a file */ X`09r = read(2, buf, sizeof buf); X `7D X else if (isatty(1)) `7B`09`09/* this may be new file output */ X`09Fflush(stdout); X`09write(1, buf, strlen(buf)); X`09r = read(1, buf, sizeof buf); X `7D X else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) `7B X`09`09`09`09`09/* might be deleted or unwriteable */ X`09write(ttyfd, buf, strlen(buf)); X`09r = read(ttyfd, buf, sizeof buf); X`09Close(ttyfd); X `7D X else if (isatty(0)) `7B`09`09/* this is probably patch input */ X`09Fflush(stdin); X`09write(0, buf, strlen(buf)); X`09r = read(0, buf, sizeof buf); X `7D X else `7B`09`09`09`09/* no terminal at all--default it */ X`09buf`5B0`5D = '\n'; X`09r = 1; X `7D X if (r <= 0) X`09buf`5B0`5D = 0; X else X`09buf`5Br`5D = '\0'; X if (!tty2) X`09say1(buf); X`7D X#endif lint X X/* How to handle certain events when not in a critical region. */ X Xvoid Xset_signals() X`7B X void my_exit(); X X#ifndef lint X if (signal(SIGHUP, SIG_IGN) != SIG_IGN) X`09Signal(SIGHUP, my_exit); X if (signal(SIGINT, SIG_IGN) != SIG_IGN) X`09Signal(SIGINT, my_exit); X#endif X`7D X X/* How to handle certain events when in a critical region. */ X Xvoid Xignore_signals() X`7B X#ifndef lint X Signal(SIGHUP, SIG_IGN); X Signal(SIGINT, SIG_IGN); X#endif X`7D X X/* Make sure we'll have the directories to create a file. */ X Xvoid Xmakedirs(filename,striplast) XReg1 char *filename; Xbool striplast; X`7B X char tmpbuf`5B256`5D; X Reg2 char *s = tmpbuf; X char *dirv`5B20`5D; X Reg3 int i; X Reg4 int dirvp = 0; X X while (*filename) `7B X`09if (*filename == '/') `7B X`09 filename++; X`09 dirv`5Bdirvp++`5D = s; X`09 *s++ = '\0'; X`09`7D X`09else `7B X`09 *s++ = *filename++; X`09`7D X `7D X *s = '\0'; X dirv`5Bdirvp`5D = s; X if (striplast) X`09dirvp--; X if (dirvp < 0) X`09return; X strcpy(buf, "mkdir"); X s = buf; X for (i=0; i<=dirvp; i++) `7B X`09while (*s) s++; X`09*s++ = ' '; X`09strcpy(s, tmpbuf); X`09*dirv`5Bi`5D = '/'; X `7D X system(buf); X`7D X X/* Make filenames more reasonable. */ X Xchar * Xfetchname(at,strip_leading,assume_exists) Xchar *at; Xint strip_leading; Xint assume_exists; X`7B X char *s; X char *name; X Reg1 char *t; X char tmpbuf`5B200`5D; X X if (!at) X`09return Nullch; X s = savestr(at); X for (t=s; isspace(*t); t++) ; X name = t; X#ifdef DEBUGGING X if (debug & 128) X`09say4("fetchname %s %d %d\n",name,strip_leading,assume_exists); X#endif X if (strnEQ(name, "/dev/null", 9))`09/* so files can be created by diffin Vg */ X`09return Nullch;`09`09`09/* against /dev/null. */ X for (; *t && !isspace(*t); t++) X`09if (*t == '/') X`09 if (--strip_leading >= 0) X`09`09name = t+1; X *t = '\0'; X if (name != s && *s != '/') `7B X`09name`5B-1`5D = '\0'; X`09if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) `7B X`09 name`5B-1`5D = '/'; X`09 name=s; X`09`7D X `7D X name = savestr(name); X Sprintf(tmpbuf, "RCS/%s", name); X free(s); X if (stat(name, &filestat) < 0 && !assume_exists) `7B X#ifdef VMS X`09free(name); X`09name = Nullch; X `7D X#else X`09Strcat(tmpbuf, RCSSUFFIX); X`09if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) `7B X`09 Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name); X`09 if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) `7B X`09`09free(name); X`09`09name = Nullch; X`09 `7D X`09`7D X `7D X#endif /* VMS */ X return name; X`7D $ CALL UNPACK [.SRC]UTIL.C;1 1581668323 $ create 'f' X/* $Header: util.h,v 2.0 86/09/17 15:40:06 lwall Exp $ X * X * $Log:`09util.h,v $ X * Revision 2.0 86/09/17 15:40:06 lwall X * Baseline for netwide release. X *`20 X */ X X/* and for those machine that can't handle a variable argument list */ X X#ifdef CANVARARG X X#define say1 say X#define say2 say X#define say3 say X#define say4 say X#define ask1 ask X#define ask2 ask X#define ask3 ask X#define ask4 ask X#define fatal1 fatal X#define fatal2 fatal X#define fatal3 fatal X#define fatal4 fatal X X#else /* hope they allow multi-line macro actual arguments */ X X#ifdef lint X X#define say1(a) say(a, 0, 0, 0) X#define say2(a,b) say(a, (b)==(b), 0, 0) X#define say3(a,b,c) say(a, (b)==(b), (c)==(c), 0) X#define say4(a,b,c,d) say(a, (b)==(b), (c)==(c), (d)==(d)) X#define ask1(a) ask(a, 0, 0, 0) X#define ask2(a,b) ask(a, (b)==(b), 0, 0) X#define ask3(a,b,c) ask(a, (b)==(b), (c)==(c), 0) X#define ask4(a,b,c,d) ask(a, (b)==(b), (c)==(c), (d)==(d)) X#define fatal1(a) fatal(a, 0, 0, 0) X#define fatal2(a,b) fatal(a, (b)==(b), 0, 0) X#define fatal3(a,b,c) fatal(a, (b)==(b), (c)==(c), 0) X#define fatal4(a,b,c,d) fatal(a, (b)==(b), (c)==(c), (d)==(d)) X X#else /* lint */ X /* if this doesn't work, try defining CANVARARG above */ X#define say1(a) say(a, Nullch, Nullch, Nullch) X#define say2(a,b) say(a, b, Nullch, Nullch) X#define say3(a,b,c) say(a, b, c, Nullch) X#define say4 say X#define ask1(a) ask(a, Nullch, Nullch, Nullch) X#define ask2(a,b) ask(a, b, Nullch, Nullch) X#define ask3(a,b,c) ask(a, b, c, Nullch) X#define ask4 ask X#define fatal1(a) fatal(a, Nullch, Nullch, Nullch) X#define fatal2(a,b) fatal(a, b, Nullch, Nullch) X#define fatal3(a,b,c) fatal(a, b, c, Nullch) X#define fatal4 fatal X X#endif /* lint */ X X/* if neither of the above work, join all multi-line macro calls. */ X#endif X XEXT char serrbuf`5BBUFSIZ`5D;`09`09/* buffer for stderr */ X Xchar *fetchname(); Xint move_file(); Xvoid copy_file(); Xvoid say(); Xvoid fatal(); Xvoid ask(); Xchar *savestr(); Xvoid set_signals(); Xvoid ignore_signals(); Xvoid makedirs(); $ CALL UNPACK [.SRC]UTIL.H;1 1802118602 $ create 'f' X/* $Header: version.c,v 2.0 86/09/17 15:40:11 lwall Exp $ X * X * $Log:`09version.c,v $ X * Revision 2.0 86/09/17 15:40:11 lwall X * Baseline for netwide release. X *`20 X */ X X#include "EXTERN.h" X#include "common.h" X#include "util.h" X#include "INTERN.h" X#include "patchlevel.h" X#include "version.h" X X/* Print out the version number and die. */ X Xvoid Xversion() X`7B X extern char rcsid`5B`5D; X X#ifdef lint X rcsid`5B0`5D = rcsid`5B0`5D; X#else X fatal3("%s\nPatch level: %d\n", rcsid, PATCHLEVEL); X#endif X`7D $ CALL UNPACK [.SRC]VERSION.C;1 1661809282 $ create 'f' X/* $Header: version.h,v 2.0 86/09/17 15:40:14 lwall Exp $ X * X * $Log:`09version.h,v $ X * Revision 2.0 86/09/17 15:40:14 lwall X * Baseline for netwide release. X *`20 X */ X Xvoid version(); $ CALL UNPACK [.SRC]VERSION.H;1 122769530 $ v=f$verify(v) $ EXIT