00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "EXTERN.h"
00039 #include "common.h"
00040 #include "util.h"
00041 #include "INTERN.h"
00042 #include "pch.h"
00043
00044
00045
00046 static long p_filesize;
00047 static LINENUM p_first;
00048 static LINENUM p_newfirst;
00049 static LINENUM p_ptrn_lines;
00050 static LINENUM p_repl_lines;
00051 static LINENUM p_end = -1;
00052 static LINENUM p_max;
00053 static LINENUM p_context = 3;
00054 static LINENUM p_input_line = 0;
00055 #ifdef SMALL
00056 static long *p_line = Null(long *);
00057 #else
00058 static char **p_line = Null(char**);
00059 #endif
00060 static short *p_len = Null(short*);
00061 static char *p_char = Nullch;
00062 static int hunkmax = INITHUNKMAX;
00063 static int p_indent;
00064 static LINENUM p_base;
00065 static LINENUM p_bline;
00066 static LINENUM p_start;
00067 static LINENUM p_sline;
00068 static LINENUM p_hunk_beg;
00069 static LINENUM p_efake = -1;
00070 static LINENUM p_bfake = -1;
00071
00072
00073
00074 void
00075 re_patch()
00076 {
00077 p_first = Nulline;
00078 p_newfirst = Nulline;
00079 p_ptrn_lines = Nulline;
00080 p_repl_lines = Nulline;
00081 p_end = (LINENUM)-1;
00082 p_max = Nulline;
00083 p_indent = 0;
00084 }
00085
00086
00087
00088 void
00089 open_patch_file(filename)
00090 char *filename;
00091 {
00092 if (filename == Nullch || !*filename || strEQ(filename, "-")) {
00093 pfp = fopen(TMPPATNAME, "w");
00094 if (pfp == Nullfp)
00095 fatal2("patch: can't create %s.\n", TMPPATNAME);
00096 while (fgets(buf, sizeof buf, stdin) != Nullch)
00097 fputs(buf, pfp);
00098 Fclose(pfp);
00099 filename = TMPPATNAME;
00100 }
00101 pfp = fopen(filename, "r");
00102 if (pfp == Nullfp)
00103 fatal2("patch file %s not found\n", filename);
00104 Fstat(fileno(pfp), &filestat);
00105 p_filesize = filestat.st_size;
00106 next_intuit_at(0L,1L);
00107 set_hunkmax();
00108 }
00109
00110
00111
00112 void
00113 set_hunkmax()
00114 {
00115 #ifndef lint
00116 #ifdef SMALL
00117 if (p_line == Null(long*))
00118 #else
00119 if (p_line == Null(char**))
00120 #endif
00121 #ifdef SMALL
00122 p_line = (long *) malloc((MEM)hunkmax * sizeof(long));
00123 #else
00124 p_line = (char**) malloc((MEM)hunkmax * sizeof(char *));
00125 #endif
00126 if (p_len == Null(short*))
00127 p_len = (short*) malloc((MEM)hunkmax * sizeof(short));
00128 #endif
00129 if (p_char == Nullch)
00130 p_char = (char*) malloc((MEM)hunkmax * sizeof(char));
00131 }
00132
00133
00134
00135 void
00136 grow_hunkmax()
00137 {
00138 hunkmax *= 2;
00139
00140
00141
00142
00143
00144 #ifdef SMALL
00145 assert(p_line != Null(long*) && p_len != Null(short*) && p_char != Nullch);
00146 #else
00147 assert(p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch);
00148 #endif
00149 #ifndef lint
00150 #ifdef SMALL
00151 p_line = (long*) realloc((char*)p_line, (MEM)hunkmax * sizeof(long));
00152 #else
00153 p_line = (char**) realloc((char*)p_line, (MEM)hunkmax * sizeof(char *));
00154 #endif
00155 p_len = (short*) realloc((char*)p_len, (MEM)hunkmax * sizeof(short));
00156 p_char = (char*) realloc((char*)p_char, (MEM)hunkmax * sizeof(char));
00157 #endif
00158 #ifdef SMALL
00159 if (p_line != Null(long*) && p_len != Null(short*) && p_char != Nullch)
00160 #else
00161 if (p_line != Null(char**) && p_len != Null(short*) && p_char != Nullch)
00162 #endif
00163 return;
00164 if (!using_plan_a)
00165 fatal1("patch: out of memory (grow_hunkmax)\n");
00166 out_of_mem = TRUE;
00167
00168 }
00169
00170
00171
00172 bool
00173 there_is_another_patch()
00174 {
00175 if (p_base != 0L && p_base >= p_filesize) {
00176 if (verbose)
00177 say1("done\n");
00178 return FALSE;
00179 }
00180 if (verbose)
00181 say1("Hmm...");
00182 diff_type = intuit_diff_type();
00183 if (!diff_type) {
00184 if (p_base != 0L) {
00185 if (verbose)
00186 say1(" Ignoring the trailing garbage.\ndone\n");
00187 }
00188 else
00189 say1(" I can't seem to find a patch in there anywhere.\n");
00190 return FALSE;
00191 }
00192 if (verbose)
00193 say3(" %sooks like %s to me...\n",
00194 (p_base == 0L ? "L" : "The next patch l"),
00195 diff_type == CONTEXT_DIFF ? "a context diff" :
00196 diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
00197 diff_type == NORMAL_DIFF ? "a normal diff" :
00198 "an ed script" );
00199 if (p_indent && verbose)
00200 say3("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
00201 skip_to(p_start,p_sline);
00202 while (filearg[0] == Nullch) {
00203 if (force) {
00204 say1("No file to patch. Skipping...\n");
00205 filearg[0] = savestr(bestguess);
00206 return TRUE;
00207 }
00208 ask1("File to patch: ");
00209 if (*buf != '\n') {
00210 if (bestguess)
00211 free(bestguess);
00212 bestguess = savestr(buf);
00213 filearg[0] = fetchname(buf, 0, FALSE);
00214 }
00215 if (filearg[0] == Nullch) {
00216 ask1("No file found--skip this patch? [n] ");
00217 if (*buf != 'y') {
00218 continue;
00219 }
00220 if (verbose)
00221 say1("Skipping patch...\n");
00222 filearg[0] = fetchname(bestguess, 0, TRUE);
00223 skip_rest_of_patch = TRUE;
00224 return TRUE;
00225 }
00226 }
00227 return TRUE;
00228 }
00229
00230
00231
00232 int
00233 intuit_diff_type()
00234 {
00235 Reg4 long this_line = 0;
00236 Reg5 long previous_line;
00237 Reg6 long first_command_line = -1;
00238 long fcl_line;
00239 Reg7 bool last_line_was_command = FALSE;
00240 Reg8 bool this_is_a_command = FALSE;
00241 Reg9 bool stars_last_line = FALSE;
00242 Reg10 bool stars_this_line = FALSE;
00243 Reg3 int indent;
00244 Reg1 char *s;
00245 Reg2 char *t;
00246 char *indtmp = Nullch;
00247 char *oldtmp = Nullch;
00248 char *newtmp = Nullch;
00249 char *indname = Nullch;
00250 char *oldname = Nullch;
00251 char *newname = Nullch;
00252 Reg11 int retval;
00253 bool no_filearg = (filearg[0] == Nullch);
00254
00255 ok_to_create_file = FALSE;
00256 Fseek(pfp, p_base, 0);
00257 p_input_line = p_bline - 1;
00258 for (;;) {
00259 previous_line = this_line;
00260 last_line_was_command = this_is_a_command;
00261 stars_last_line = stars_this_line;
00262 this_line = ftell(pfp);
00263 indent = 0;
00264 p_input_line++;
00265 if (fgets(buf, sizeof buf, pfp) == Nullch) {
00266 if (first_command_line >= 0L) {
00267
00268 p_start = first_command_line;
00269 p_sline = fcl_line;
00270 retval = ED_DIFF;
00271 goto scan_exit;
00272 }
00273 else {
00274 p_start = this_line;
00275 p_sline = p_input_line;
00276 retval = 0;
00277 goto scan_exit;
00278 }
00279 }
00280 for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
00281 if (*s == '\t')
00282 indent += 8 - (indent % 8);
00283 else
00284 indent++;
00285 }
00286 for (t=s; isdigit(*t) || *t == ','; t++) ;
00287 this_is_a_command = (isdigit(*s) &&
00288 (*t == 'd' || *t == 'c' || *t == 'a') );
00289 if (first_command_line < 0L && this_is_a_command) {
00290 first_command_line = this_line;
00291 fcl_line = p_input_line;
00292 p_indent = indent;
00293 }
00294 if (!stars_last_line && strnEQ(s, "*** ", 4))
00295 oldtmp = savestr(s+4);
00296 else if (strnEQ(s, "--- ", 4))
00297 newtmp = savestr(s+4);
00298 else if (strnEQ(s, "Index:", 6))
00299 indtmp = savestr(s+6);
00300 else if (strnEQ(s, "Prereq:", 7)) {
00301 for (t=s+7; isspace(*t); t++) ;
00302 revision = savestr(t);
00303 for (t=revision; *t && !isspace(*t); t++) ;
00304 *t = '\0';
00305 if (!*revision) {
00306 free(revision);
00307 revision = Nullch;
00308 }
00309 }
00310 if ((!diff_type || diff_type == ED_DIFF) &&
00311 first_command_line >= 0L &&
00312 strEQ(s, ".\n") ) {
00313 p_indent = indent;
00314 p_start = first_command_line;
00315 p_sline = fcl_line;
00316 retval = ED_DIFF;
00317 goto scan_exit;
00318 }
00319 stars_this_line = strnEQ(s, "********", 8);
00320 if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line &&
00321 strnEQ(s, "*** ", 4)) {
00322 if (!atol(s+4))
00323 ok_to_create_file = TRUE;
00324
00325
00326 while (*s != '\n')
00327 s++;
00328 p_indent = indent;
00329 p_start = previous_line;
00330 p_sline = p_input_line - 1;
00331 retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
00332 goto scan_exit;
00333 }
00334 if ((!diff_type || diff_type == NORMAL_DIFF) &&
00335 last_line_was_command &&
00336 (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2)) ) {
00337 p_start = previous_line;
00338 p_sline = p_input_line - 1;
00339 p_indent = indent;
00340 retval = NORMAL_DIFF;
00341 goto scan_exit;
00342 }
00343 }
00344 scan_exit:
00345 if (no_filearg) {
00346 if (indtmp != Nullch)
00347 indname = fetchname(indtmp, strippath, ok_to_create_file);
00348 if (oldtmp != Nullch)
00349 oldname = fetchname(oldtmp, strippath, ok_to_create_file);
00350 if (newtmp != Nullch)
00351 newname = fetchname(newtmp, strippath, ok_to_create_file);
00352 if (oldname && newname) {
00353 if (strlen(oldname) < strlen(newname))
00354 filearg[0] = savestr(oldname);
00355 else
00356 filearg[0] = savestr(newname);
00357 }
00358 else if (oldname)
00359 filearg[0] = savestr(oldname);
00360 else if (newname)
00361 filearg[0] = savestr(newname);
00362 else if (indname)
00363 filearg[0] = savestr(indname);
00364 }
00365 if (bestguess) {
00366 free(bestguess);
00367 bestguess = Nullch;
00368 }
00369 if (filearg[0] != Nullch)
00370 bestguess = savestr(filearg[0]);
00371 else if (indtmp != Nullch)
00372 bestguess = fetchname(indtmp, strippath, TRUE);
00373 else {
00374 if (oldtmp != Nullch)
00375 oldname = fetchname(oldtmp, strippath, TRUE);
00376 if (newtmp != Nullch)
00377 newname = fetchname(newtmp, strippath, TRUE);
00378 if (oldname && newname) {
00379 if (strlen(oldname) < strlen(newname))
00380 bestguess = savestr(oldname);
00381 else
00382 bestguess = savestr(newname);
00383 }
00384 else if (oldname)
00385 bestguess = savestr(oldname);
00386 else if (newname)
00387 bestguess = savestr(newname);
00388 }
00389 if (indtmp != Nullch)
00390 free(indtmp);
00391 if (oldtmp != Nullch)
00392 free(oldtmp);
00393 if (newtmp != Nullch)
00394 free(newtmp);
00395 if (indname != Nullch)
00396 free(indname);
00397 if (oldname != Nullch)
00398 free(oldname);
00399 if (newname != Nullch)
00400 free(newname);
00401 return retval;
00402 }
00403
00404
00405
00406 void
00407 next_intuit_at(file_pos,file_line)
00408 long file_pos;
00409 long file_line;
00410 {
00411 p_base = file_pos;
00412 p_bline = file_line;
00413 }
00414
00415
00416
00417 void
00418 skip_to(file_pos,file_line)
00419 long file_pos;
00420 long file_line;
00421 {
00422 char *ret;
00423
00424 assert(p_base <= file_pos);
00425 if (verbose && p_base < file_pos) {
00426 Fseek(pfp, p_base, 0);
00427 say1("The text leading up to this was:\n--------------------------\n");
00428 while (ftell(pfp) < file_pos) {
00429 ret = fgets(buf, sizeof buf, pfp);
00430 assert(ret != Nullch);
00431 say2("|%s", buf);
00432 }
00433 say1("--------------------------\n");
00434 }
00435 else
00436 Fseek(pfp, file_pos, 0);
00437 p_input_line = file_line - 1;
00438 }
00439
00440
00441
00442 bool
00443 another_hunk()
00444 {
00445 Reg1 char *s;
00446 Reg8 char *ret;
00447 Reg2 int context = 0;
00448
00449 while (p_end >= 0) {
00450 if (p_end == p_efake)
00451 p_end = p_bfake;
00452 #ifndef SMALL
00453 else
00454 free(p_line[p_end]);
00455 #endif
00456 p_end--;
00457 }
00458 assert(p_end == -1);
00459 p_efake = -1;
00460 #ifdef SMALL
00461 if (sfp != Nullfp)
00462 Fclose(sfp);
00463 sfp = fopen(TMPSTRNAME, "w");
00464 if (sfp == Nullfp)
00465 fatal2("patch: can't create %s.\n", TMPSTRNAME);
00466 #endif
00467
00468 p_max = hunkmax;
00469 if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) {
00470 long line_beginning = ftell(pfp);
00471
00472 LINENUM repl_beginning = 0;
00473 Reg4 LINENUM fillcnt = 0;
00474 Reg5 LINENUM fillsrc;
00475 Reg6 LINENUM filldst;
00476 bool ptrn_spaces_eaten = FALSE;
00477 Reg9 bool repl_could_be_missing = TRUE;
00478
00479 bool repl_missing = FALSE;
00480 long repl_backtrack_position = 0;
00481
00482 LINENUM repl_patch_line;
00483 Reg7 LINENUM ptrn_copiable = 0;
00484
00485
00486 ret = pgets(buf, sizeof buf, pfp);
00487 p_input_line++;
00488 if (ret == Nullch || strnNE(buf, "********", 8)) {
00489 next_intuit_at(line_beginning,p_input_line);
00490 return FALSE;
00491 }
00492 p_context = 100;
00493 p_hunk_beg = p_input_line + 1;
00494 while (p_end < p_max) {
00495 line_beginning = ftell(pfp);
00496 ret = pgets(buf, sizeof buf, pfp);
00497 p_input_line++;
00498 if (ret == Nullch) {
00499 if (p_max - p_end < 4)
00500 Strcpy(buf, " \n");
00501 else {
00502 if (repl_beginning && repl_could_be_missing) {
00503 repl_missing = TRUE;
00504 goto hunk_done;
00505 }
00506 fatal1("Unexpected end of file in patch.\n");
00507 }
00508 }
00509 p_end++;
00510 assert(p_end < hunkmax);
00511 p_char[p_end] = *buf;
00512 #ifdef zilog
00513 p_line[(short)p_end] = Nullch;
00514 #else
00515 #ifdef SMALL
00516 p_line[p_end] = -1L;
00517 p_len[p_end] = 0;
00518 #else
00519 p_line[p_end] = Nullch;
00520 #endif
00521 #endif
00522 switch (*buf) {
00523 case '*':
00524 if (strnEQ(buf, "********", 8)) {
00525 if (repl_beginning && repl_could_be_missing) {
00526 repl_missing = TRUE;
00527 goto hunk_done;
00528 }
00529 else
00530 fatal2("Unexpected end of hunk at line %ld.\n",
00531 p_input_line);
00532 }
00533 if (p_end != 0) {
00534 if (repl_beginning && repl_could_be_missing) {
00535 repl_missing = TRUE;
00536 goto hunk_done;
00537 }
00538 fatal3("Unexpected *** at line %ld: %s", p_input_line, buf);
00539 }
00540 context = 0;
00541 #ifdef SMALL
00542 p_line[p_end] = saveStr(buf, p_len+p_end);
00543 #else
00544 p_line[p_end] = savestr(buf);
00545 if (out_of_mem) {
00546 p_end--;
00547 return FALSE;
00548 }
00549 #endif
00550 for (s=buf; *s && !isdigit(*s); s++) ;
00551 if (!*s)
00552 goto malformed;
00553 if (strnEQ(s,"0,0",3))
00554 strcpy(s,s+2);
00555 p_first = (LINENUM) atol(s);
00556 while (isdigit(*s)) s++;
00557 if (*s == ',') {
00558 for (; *s && !isdigit(*s); s++) ;
00559 if (!*s)
00560 goto malformed;
00561 p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
00562 }
00563 else if (p_first)
00564 p_ptrn_lines = 1;
00565 else {
00566 p_ptrn_lines = 0;
00567 p_first = 1;
00568 }
00569 p_max = p_ptrn_lines + 6;
00570 while (p_max >= hunkmax)
00571 grow_hunkmax();
00572 p_max = hunkmax;
00573 break;
00574 case '-':
00575 if (buf[1] == '-') {
00576 if (repl_beginning ||
00577 (p_end != p_ptrn_lines + 1 + (p_char[p_end-1] == '\n')))
00578 {
00579 if (p_end == 1) {
00580
00581
00582 p_end = p_ptrn_lines + 1;
00583 fillsrc = p_end + 1;
00584 filldst = 1;
00585 fillcnt = p_ptrn_lines;
00586 }
00587 else {
00588 if (repl_beginning) {
00589 if (repl_could_be_missing){
00590 repl_missing = TRUE;
00591 goto hunk_done;
00592 }
00593 fatal3(
00594 "Duplicate \"---\" at line %ld--check line numbers at line %ld.\n",
00595 p_input_line, p_hunk_beg + repl_beginning);
00596 }
00597 else {
00598 fatal4(
00599 "%s \"---\" at line %ld--check line numbers at line %ld.\n",
00600 (p_end <= p_ptrn_lines
00601 ? "Premature"
00602 : "Overdue" ),
00603 p_input_line, p_hunk_beg);
00604 }
00605 }
00606 }
00607 repl_beginning = p_end;
00608 repl_backtrack_position = ftell(pfp);
00609 repl_patch_line = p_input_line;
00610 #ifdef SMALL
00611 p_line[p_end] = saveStr(buf, p_len+p_end);
00612 #else
00613 p_line[p_end] = savestr(buf);
00614 if (out_of_mem) {
00615 p_end--;
00616 return FALSE;
00617 }
00618 #endif
00619 p_char[p_end] = '=';
00620 for (s=buf; *s && !isdigit(*s); s++) ;
00621 if (!*s)
00622 goto malformed;
00623 p_newfirst = (LINENUM) atol(s);
00624 while (isdigit(*s)) s++;
00625 if (*s == ',') {
00626 for (; *s && !isdigit(*s); s++) ;
00627 if (!*s)
00628 goto malformed;
00629 p_repl_lines = ((LINENUM)atol(s)) - p_newfirst + 1;
00630 }
00631 else if (p_newfirst)
00632 p_repl_lines = 1;
00633 else {
00634 p_repl_lines = 0;
00635 p_newfirst = 1;
00636 }
00637 p_max = p_repl_lines + p_end;
00638 if (p_max > MAXHUNKSIZE)
00639 fatal4("Hunk too large (%ld lines) at line %ld: %s",
00640 p_max, p_input_line, buf);
00641 while (p_max >= hunkmax)
00642 grow_hunkmax();
00643 if (p_repl_lines != ptrn_copiable)
00644 repl_could_be_missing = FALSE;
00645 break;
00646 }
00647 goto change_line;
00648 case '+': case '!':
00649 repl_could_be_missing = FALSE;
00650 change_line:
00651 if (buf[1] == '\n' && canonicalize)
00652 strcpy(buf+1," \n");
00653 if (!isspace(buf[1]) && buf[1] != '>' && buf[1] != '<' &&
00654 repl_beginning && repl_could_be_missing) {
00655 repl_missing = TRUE;
00656 goto hunk_done;
00657 }
00658 if (context > 0) {
00659 if (context < p_context)
00660 p_context = context;
00661 context = -1000;
00662 }
00663 #ifdef SMALL
00664 p_line[p_end] = saveStr(buf+2, p_len+p_end);
00665 #else
00666 p_line[p_end] = savestr(buf+2);
00667 if (out_of_mem) {
00668 p_end--;
00669 return FALSE;
00670 }
00671 #endif
00672 break;
00673 case '\t': case '\n':
00674 if (repl_beginning && repl_could_be_missing &&
00675 (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF) ) {
00676 repl_missing = TRUE;
00677 goto hunk_done;
00678 }
00679 #ifdef SMALL
00680 p_line[p_end] = saveStr(buf, p_len+p_end);
00681 #else
00682 p_line[p_end] = savestr(buf);
00683 if (out_of_mem) {
00684 p_end--;
00685 return FALSE;
00686 }
00687 #endif
00688 if (p_end != p_ptrn_lines + 1) {
00689 ptrn_spaces_eaten |= (repl_beginning != 0);
00690 context++;
00691 if (!repl_beginning)
00692 ptrn_copiable++;
00693 p_char[p_end] = ' ';
00694 }
00695 break;
00696 case ' ':
00697 if (!isspace(buf[1]) &&
00698 repl_beginning && repl_could_be_missing) {
00699 repl_missing = TRUE;
00700 goto hunk_done;
00701 }
00702 context++;
00703 if (!repl_beginning)
00704 ptrn_copiable++;
00705 #ifdef SMALL
00706 p_line[p_end] = saveStr(buf+2, p_len+p_end);
00707 #else
00708 p_line[p_end] = savestr(buf+2);
00709 if (out_of_mem) {
00710 p_end--;
00711 return FALSE;
00712 }
00713 #endif
00714 break;
00715 default:
00716 if (repl_beginning && repl_could_be_missing) {
00717 repl_missing = TRUE;
00718 goto hunk_done;
00719 }
00720 goto malformed;
00721 }
00722
00723
00724 #ifndef SMALL
00725 if (p_line[p_end])
00726 p_len[p_end] = strlen(p_line[p_end]);
00727 else
00728 p_len[p_end] = 0;
00729 #endif
00730 }
00731
00732 hunk_done:
00733 if (p_end >=0 && !repl_beginning)
00734 fatal2("No --- found in patch at line %ld\n", pch_hunk_beg());
00735
00736 if (repl_missing) {
00737
00738
00739 p_input_line = repl_patch_line;
00740 #ifndef SMALL
00741 for (p_end--; p_end > repl_beginning; p_end--)
00742 free(p_line[p_end]);
00743 #endif
00744 Fseek(pfp, repl_backtrack_position, 0);
00745
00746
00747
00748 fillsrc = 1;
00749 filldst = repl_beginning+1;
00750 fillcnt = p_repl_lines;
00751 p_end = p_max;
00752 }
00753
00754 if (diff_type == CONTEXT_DIFF &&
00755 (fillcnt || (p_first > 1 && ptrn_copiable > 2*p_context)) ) {
00756 if (verbose)
00757 say4("%s\n%s\n%s\n",
00758 "(Fascinating--this is really a new-style context diff but without",
00759 "the telltale extra asterisks on the *** line that usually indicate",
00760 "the new style...)");
00761 diff_type = NEW_CONTEXT_DIFF;
00762 }
00763
00764
00765 if (fillcnt) {
00766 p_bfake = filldst;
00767 p_efake = filldst + fillcnt - 1;
00768 while (fillcnt-- > 0) {
00769 while (fillsrc <= p_end && p_char[fillsrc] != ' ')
00770 fillsrc++;
00771 if (fillsrc > p_end)
00772 fatal2("Replacement text or line numbers mangled in hunk at line %ld\n",
00773 p_hunk_beg);
00774 p_line[filldst] = p_line[fillsrc];
00775 p_char[filldst] = p_char[fillsrc];
00776 p_len[filldst] = p_len[fillsrc];
00777 fillsrc++; filldst++;
00778 }
00779 while (fillsrc <= p_end && fillsrc != repl_beginning &&
00780 p_char[fillsrc] != ' ')
00781 fillsrc++;
00782 #ifdef DEBUGGING
00783 if (debug & 64)
00784 printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
00785 fillsrc,filldst,repl_beginning,p_end+1);
00786 #endif
00787 assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
00788 assert(filldst==p_end+1 || filldst==repl_beginning);
00789 }
00790 }
00791 else {
00792 char hunk_type;
00793 Reg3 int i;
00794 LINENUM min, max;
00795 long line_beginning = ftell(pfp);
00796
00797 p_context = 0;
00798 ret = pgets(buf, sizeof buf, pfp);
00799 p_input_line++;
00800 if (ret == Nullch || !isdigit(*buf)) {
00801 next_intuit_at(line_beginning,p_input_line);
00802 return FALSE;
00803 }
00804 p_first = (LINENUM)atol(buf);
00805 for (s=buf; isdigit(*s); s++) ;
00806 if (*s == ',') {
00807 p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
00808 while (isdigit(*s)) s++;
00809 }
00810 else
00811 p_ptrn_lines = (*s != 'a');
00812 hunk_type = *s;
00813 if (hunk_type == 'a')
00814 p_first++;
00815 min = (LINENUM)atol(++s);
00816 for (; isdigit(*s); s++) ;
00817 if (*s == ',')
00818 max = (LINENUM)atol(++s);
00819 else
00820 max = min;
00821 if (hunk_type == 'd')
00822 min++;
00823 p_end = p_ptrn_lines + 1 + max - min + 1;
00824 if (p_end > MAXHUNKSIZE)
00825 fatal4("Hunk too large (%ld lines) at line %ld: %s",
00826 p_end, p_input_line, buf);
00827 while (p_end >= hunkmax)
00828 grow_hunkmax();
00829 p_newfirst = min;
00830 p_repl_lines = max - min + 1;
00831 Sprintf(buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
00832 #ifdef SMALL
00833 p_line[0] = saveStr(buf, p_len);
00834 #else
00835 p_line[0] = savestr(buf);
00836 if (out_of_mem) {
00837 p_end = -1;
00838 return FALSE;
00839 }
00840 #endif
00841 p_char[0] = '*';
00842 for (i=1; i<=p_ptrn_lines; i++) {
00843 ret = pgets(buf, sizeof buf, pfp);
00844 p_input_line++;
00845 if (ret == Nullch)
00846 fatal2("Unexpected end of file in patch at line %ld.\n",
00847 p_input_line);
00848 if (*buf != '<')
00849 fatal2("< expected at line %ld of patch.\n", p_input_line);
00850 #ifdef SMALL
00851 p_line[i] = saveStr(buf+2, p_len+i);
00852 #else
00853 p_line[i] = savestr(buf+2);
00854 if (out_of_mem) {
00855 p_end = i-1;
00856 return FALSE;
00857 }
00858 #endif
00859 #ifndef SMALL
00860 p_len[i] = strlen(p_line[i]);
00861 #endif
00862 p_char[i] = '-';
00863 }
00864 if (hunk_type == 'c') {
00865 ret = pgets(buf, sizeof buf, pfp);
00866 p_input_line++;
00867 if (ret == Nullch)
00868 fatal2("Unexpected end of file in patch at line %ld.\n",
00869 p_input_line);
00870 if (*buf != '-')
00871 fatal2("--- expected at line %ld of patch.\n", p_input_line);
00872 }
00873 Sprintf(buf, "--- %ld,%ld\n", min, max);
00874 #ifdef SMALL
00875 p_line[i] = saveStr(buf, p_len+i);
00876 #else
00877 p_line[i] = savestr(buf);
00878 if (out_of_mem) {
00879 p_end = i-1;
00880 return FALSE;
00881 }
00882 #endif
00883 p_char[i] = '=';
00884 for (i++; i<=p_end; i++) {
00885 ret = pgets(buf, sizeof buf, pfp);
00886 p_input_line++;
00887 if (ret == Nullch)
00888 fatal2("Unexpected end of file in patch at line %ld.\n",
00889 p_input_line);
00890 if (*buf != '>')
00891 fatal2("> expected at line %ld of patch.\n", p_input_line);
00892 #ifdef SMALL
00893 p_line[i] = saveStr(buf+2, p_len+i);
00894 #else
00895 p_line[i] = savestr(buf+2);
00896 if (out_of_mem) {
00897 p_end = i-1;
00898 return FALSE;
00899 }
00900 #endif
00901 #ifndef SMALL
00902 p_len[i] = strlen(p_line[i]);
00903 #endif
00904 p_char[i] = '+';
00905 }
00906 }
00907 if (reverse)
00908 if (!pch_swap())
00909 say1("Not enough memory to swap next hunk!\n");
00910 #ifdef SMALL
00911 Fclose(sfp);
00912 sfp = fopen(TMPSTRNAME, "r");
00913 #endif
00914 #ifdef DEBUGGING
00915 if (debug & 2) {
00916 int i;
00917 char special;
00918
00919 for (i=0; i <= p_end; i++) {
00920 if (i == p_ptrn_lines)
00921 special = '^';
00922 else
00923 special = ' ';
00924 #ifdef SMALL
00925 fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, pfetch(i));
00926 #else
00927 fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]);
00928 #endif
00929 Fflush(stderr);
00930 }
00931 }
00932 #endif
00933 if (p_end+1 < hunkmax)
00934 p_char[p_end+1] = '^';
00935 return TRUE;
00936
00937 malformed:
00938 #ifdef SMALL
00939 Fclose(sfp);
00940 sfp = Nullfp;
00941 #endif
00942 fatal3("Malformed patch at line %ld: %s", p_input_line, buf);
00943
00944 return FALSE;
00945 }
00946
00947
00948
00949 char *
00950 pgets(bf,sz,fp)
00951 char *bf;
00952 int sz;
00953 FILE *fp;
00954 {
00955 char *ret = fgets(bf, sz, fp);
00956 Reg1 char *s;
00957 Reg2 int indent = 0;
00958
00959 if (p_indent && ret != Nullch) {
00960 for (s=buf;
00961 indent < p_indent && (*s == ' ' || *s == '\t' || *s == 'X'); s++) {
00962 if (*s == '\t')
00963 indent += 8 - (indent % 7);
00964 else
00965 indent++;
00966 }
00967 if (buf != s)
00968 Strcpy(buf, s);
00969 }
00970 return ret;
00971 }
00972
00973
00974
00975 bool
00976 pch_swap()
00977 {
00978 #ifdef SMALL
00979 long *tp_line;
00980 #else
00981 char **tp_line;
00982 #endif
00983 short *tp_len;
00984 char *tp_char;
00985 Reg1 LINENUM i;
00986 Reg2 LINENUM n;
00987 bool blankline = FALSE;
00988 Reg3 char *s;
00989
00990 i = p_first;
00991 p_first = p_newfirst;
00992 p_newfirst = i;
00993
00994
00995
00996 tp_line = p_line;
00997 tp_len = p_len;
00998 tp_char = p_char;
00999 #ifdef SMALL
01000 p_line = Null(long*);
01001 #else
01002 p_line = Null(char**);
01003 #endif
01004 p_len = Null(short*);
01005 p_char = Nullch;
01006 set_hunkmax();
01007 #ifdef SMALL
01008 if (p_line == Null(long*) || p_len == Null(short*) || p_char == Nullch) {
01009 #else
01010 if (p_line == Null(char**) || p_len == Null(short*) || p_char == Nullch) {
01011 #endif
01012 #ifndef lint
01013 #ifdef SMALL
01014 if (p_line == Null(long*))
01015 #else
01016 if (p_line == Null(char**))
01017 #endif
01018 free((char*)p_line);
01019 p_line = tp_line;
01020 if (p_len == Null(short*))
01021 free((char*)p_len);
01022 p_len = tp_len;
01023 #endif
01024 if (p_char == Nullch)
01025 free((char*)p_char);
01026 p_char = tp_char;
01027 return FALSE;
01028 }
01029
01030
01031
01032 i = p_ptrn_lines + 1;
01033 if (tp_char[i] == '\n') {
01034 blankline = TRUE;
01035 i++;
01036 }
01037 if (p_efake >= 0) {
01038 if (p_efake <= i)
01039 n = p_end - i + 1;
01040 else
01041 n = -i;
01042 p_efake += n;
01043 p_bfake += n;
01044 }
01045 for (n=0; i <= p_end; i++,n++) {
01046 p_line[n] = tp_line[i];
01047 p_char[n] = tp_char[i];
01048 if (p_char[n] == '+')
01049 p_char[n] = '-';
01050 p_len[n] = tp_len[i];
01051 }
01052 if (blankline) {
01053 i = p_ptrn_lines + 1;
01054 p_line[n] = tp_line[i];
01055 p_char[n] = tp_char[i];
01056 p_len[n] = tp_len[i];
01057 n++;
01058 }
01059 assert(p_char[0] == '=');
01060 p_char[0] = '*';
01061 #ifdef SMALL
01062 strEdit(p_line[0], '*', '-');
01063 #else
01064 for (s=p_line[0]; *s; s++)
01065 if (*s == '-')
01066 *s = '*';
01067 #endif
01068
01069
01070
01071 assert(tp_char[0] == '*');
01072 tp_char[0] = '=';
01073 #ifdef SMALL
01074 strEdit(tp_line[0], '-', '*');
01075 #else
01076 for (s=tp_line[0]; *s; s++)
01077 if (*s == '*')
01078 *s = '-';
01079 #endif
01080 for (i=0; n <= p_end; i++,n++) {
01081 p_line[n] = tp_line[i];
01082 p_char[n] = tp_char[i];
01083 if (p_char[n] == '-')
01084 p_char[n] = '+';
01085 p_len[n] = tp_len[i];
01086 }
01087 assert(i == p_ptrn_lines + 1);
01088 i = p_ptrn_lines;
01089 p_ptrn_lines = p_repl_lines;
01090 p_repl_lines = i;
01091 #ifndef lint
01092 #ifdef SMALL
01093 if (tp_line == Null(long*))
01094 #else
01095 if (tp_line == Null(char**))
01096 #endif
01097 free((char*)tp_line);
01098 if (tp_len == Null(short*))
01099 free((char*)tp_len);
01100 #endif
01101 if (tp_char == Nullch)
01102 free((char*)tp_char);
01103 return TRUE;
01104 }
01105
01106
01107
01108 LINENUM
01109 pch_first()
01110 {
01111 return p_first;
01112 }
01113
01114
01115
01116 LINENUM
01117 pch_ptrn_lines()
01118 {
01119 return p_ptrn_lines;
01120 }
01121
01122
01123
01124 LINENUM
01125 pch_newfirst()
01126 {
01127 return p_newfirst;
01128 }
01129
01130
01131
01132 LINENUM
01133 pch_repl_lines()
01134 {
01135 return p_repl_lines;
01136 }
01137
01138
01139
01140 LINENUM
01141 pch_end()
01142 {
01143 return p_end;
01144 }
01145
01146
01147
01148 LINENUM
01149 pch_context()
01150 {
01151 return p_context;
01152 }
01153
01154
01155
01156 short
01157 pch_line_len(line)
01158 LINENUM line;
01159 {
01160 return p_len[line];
01161 }
01162
01163
01164
01165 char
01166 pch_char(line)
01167 LINENUM line;
01168 {
01169 return p_char[line];
01170 }
01171
01172
01173
01174 #ifdef SMALL
01175 long
01176 saveStr(str, plen)
01177 char *str;
01178 short *plen;
01179 {
01180 long pos, ftell();
01181 int len;
01182
01183 pos = ftell(sfp);
01184 len = strlen(str);
01185 fwrite(str, sizeof(char), len+1, sfp);
01186 *plen = len;
01187 return pos;
01188 }
01189
01190 char *
01191 pfetch(line)
01192 LINENUM line;
01193 {
01194 static char *s, strbuf[BUFSIZ];
01195 int i, c;
01196
01197 if (p_line[line] == -1L)
01198 return Nullch;
01199 else {
01200 Fseek(sfp, p_line[line], 0);
01201 for (i = 0, s = strbuf;
01202 i < BUFSIZ && (c = fgetc(sfp)) != EOF && c; i++)
01203 *s++ = c;
01204 if (i == BUFSIZ)
01205 fatal2("too long line (%.40s ..\n", strbuf);
01206 }
01207 *s = '\0';
01208 return strbuf;
01209 }
01210
01211 void
01212 strEdit(pos, to, from)
01213 long pos;
01214 int to, from;
01215 {
01216 static char *s, strbuf[BUFSIZ];
01217 int i, c;
01218
01219 if (pos != -1L) {
01220 for (i = 0, s = strbuf;
01221 i < BUFSIZ && (c = fgetc(sfp)) != EOF && c; i++)
01222 *s++ = c;
01223 for (s = strbuf; *s; s++)
01224 if (*s == from)
01225 *s = to;
01226 fwrite(strbuf, sizeof(char), i+1, sfp);
01227 }
01228 }
01229 #else
01230 char *
01231 pfetch(line)
01232 LINENUM line;
01233 {
01234 return p_line[line];
01235 }
01236 #endif
01237
01238
01239
01240 LINENUM
01241 pch_hunk_beg()
01242 {
01243 return p_hunk_beg;
01244 }
01245
01246
01247
01248 void
01249 do_ed_script()
01250 {
01251 Reg1 char *t;
01252 Reg2 long beginning_of_this_line;
01253 Reg3 bool this_line_is_command = FALSE;
01254 Reg4 FILE *pipefp;
01255
01256 if (!skip_rest_of_patch) {
01257 Unlink(TMPOUTNAME);
01258 copy_file(filearg[0], TMPOUTNAME);
01259 if (verbose)
01260 Sprintf(buf, "/bin/ed %s", TMPOUTNAME);
01261 else
01262 Sprintf(buf, "/bin/ed - %s", TMPOUTNAME);
01263 pipefp = popen(buf, "w");
01264 }
01265 for (;;) {
01266 beginning_of_this_line = ftell(pfp);
01267 if (pgets(buf, sizeof buf, pfp) == Nullch) {
01268 next_intuit_at(beginning_of_this_line,p_input_line);
01269 break;
01270 }
01271 p_input_line++;
01272 for (t=buf; isdigit(*t) || *t == ','; t++) ;
01273 this_line_is_command = (isdigit(*buf) &&
01274 (*t == 'd' || *t == 'c' || *t == 'a') );
01275 if (this_line_is_command) {
01276 if (!skip_rest_of_patch)
01277 fputs(buf, pipefp);
01278 if (*t != 'd') {
01279 while (pgets(buf, sizeof buf, pfp) != Nullch) {
01280 p_input_line++;
01281 if (!skip_rest_of_patch)
01282 fputs(buf, pipefp);
01283 if (strEQ(buf, ".\n"))
01284 break;
01285 }
01286 }
01287 }
01288 else {
01289 next_intuit_at(beginning_of_this_line,p_input_line);
01290 break;
01291 }
01292 }
01293 if (skip_rest_of_patch)
01294 return;
01295 fprintf(pipefp, "w\n");
01296 fprintf(pipefp, "q\n");
01297 Fflush(pipefp);
01298 Pclose(pipefp);
01299 ignore_signals();
01300 if (move_file(TMPOUTNAME, outname) < 0) {
01301 toutkeep = TRUE;
01302 chmod(TMPOUTNAME, filemode);
01303 }
01304 else
01305 chmod(outname, filemode);
01306 set_signals(1);
01307 }