📄 patch.c
字号:
s = Argv[0]; } if (!isalpha(*s)) fatal1("Argument to -D not an identifier.\n"); Sprintf(if_defined, "#ifdef %s\n", s); Sprintf(not_defined, "#ifndef %s\n", s); Sprintf(end_defined, "#endif /* %s */\n", s); break; case 'e': diff_type = ED_DIFF; break; case 'f': force = TRUE; break; case 'F': if (*++s == '=') s++; maxfuzz = atoi(s); break; case 'l': canonicalize = TRUE; break; case 'n': diff_type = NORMAL_DIFF; break; case 'N': noreverse = TRUE; break; case 'o': outname = savestr(Argv[1]); Argc--,Argv++; break; case 'p': if (*++s == '=') s++; strippath = atoi(s); break; case 'r': Strcpy(rejname, Argv[1]); Argc--,Argv++; break; case 'R': reverse = TRUE; break; case 's': verbose = FALSE; break; case 'S': skip_rest_of_patch = TRUE; break; case 'v': version(); break;#ifdef DEBUGGING case 'x': debug = atoi(s+1); break;#endif default: fatal2("Unrecognized switch: %s\n", Argv[0]); } } }}/* Attempt to find the right place to apply this hunk of patch. */LINENUMlocate_hunk(fuzz)LINENUM fuzz;{ Reg1 LINENUM first_guess = pch_first() + last_offset; Reg2 LINENUM offset; LINENUM pat_lines = pch_ptrn_lines(); Reg3 LINENUM max_pos_offset = input_lines - first_guess - pat_lines + 1; Reg4 LINENUM max_neg_offset = first_guess - last_frozen_line - 1 + pch_context(); if (!pat_lines) /* null range matches always */ return first_guess; if (max_neg_offset >= first_guess) /* do not try lines < 0 */ max_neg_offset = first_guess - 1; if (first_guess <= input_lines && patch_match(first_guess, Nulline, fuzz)) return first_guess; for (offset = 1; ; offset++) { Reg5 bool check_after = (offset <= max_pos_offset); Reg6 bool check_before = (offset <= max_neg_offset); if (check_after && patch_match(first_guess, offset, fuzz)) {#ifdef DEBUGGING if (debug & 1) say3("Offset changing from %ld to %ld\n", last_offset, offset);#endif last_offset = offset; return first_guess+offset; } else if (check_before && patch_match(first_guess, -offset, fuzz)) {#ifdef DEBUGGING if (debug & 1) say3("Offset changing from %ld to %ld\n", last_offset, -offset);#endif last_offset = -offset; return first_guess-offset; } else if (!check_before && !check_after) return Nulline; }}/* We did not find the pattern, dump out the hunk so they can handle it. */voidabort_hunk(){ Reg1 LINENUM i; Reg2 LINENUM pat_end = pch_end(); /* add in last_offset to guess the same as the previous successful hunk */ LINENUM oldfirst = pch_first() + last_offset; LINENUM newfirst = pch_newfirst() + last_offset; LINENUM oldlast = oldfirst + pch_ptrn_lines() - 1; LINENUM newlast = newfirst + pch_repl_lines() - 1; char *stars = (diff_type == NEW_CONTEXT_DIFF ? " ****" : ""); char *minuses = (diff_type == NEW_CONTEXT_DIFF ? " ----" : " -----"); fprintf(rejfp, "***************\n"); for (i=0; i<=pat_end; i++) { switch (pch_char(i)) { case '*': if (oldlast < oldfirst) fprintf(rejfp, "*** 0%s\n", stars); else if (oldlast == oldfirst) fprintf(rejfp, "*** %ld%s\n", oldfirst, stars); else fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars); break; case '=': if (newlast < newfirst) fprintf(rejfp, "--- 0%s\n", minuses); else if (newlast == newfirst) fprintf(rejfp, "--- %ld%s\n", newfirst, minuses); else fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses); break; case '\n': fprintf(rejfp, "%s", pfetch(i)); break; case ' ': case '-': case '+': case '!': fprintf(rejfp, "%c %s", pch_char(i), pfetch(i)); break; default: say1("Fatal internal error in abort_hunk().\n"); abort(); } }}/* We found where to apply it (we hope), so do it. */voidapply_hunk(where)LINENUM where;{ Reg1 LINENUM old = 1; Reg2 LINENUM lastline = pch_ptrn_lines(); Reg3 LINENUM new = lastline+1;#define OUTSIDE 0#define IN_IFNDEF 1#define IN_IFDEF 2#define IN_ELSE 3 Reg4 int def_state = OUTSIDE; Reg5 bool R_do_defines = do_defines; Reg6 LINENUM pat_end = pch_end(); where--; while (pch_char(new) == '=' || pch_char(new) == '\n') new++; while (old <= lastline) { if (pch_char(old) == '-') { copy_till(where + old - 1); if (R_do_defines) { if (def_state == OUTSIDE) { fputs(not_defined, ofp); def_state = IN_IFNDEF; } else if (def_state == IN_IFDEF) { fputs(else_defined, ofp); def_state = IN_ELSE; } fputs(pfetch(old), ofp); } last_frozen_line++; old++; } else if (new > pat_end) break; else if (pch_char(new) == '+') { copy_till(where + old - 1); if (R_do_defines) { if (def_state == IN_IFNDEF) { fputs(else_defined, ofp); def_state = IN_ELSE; } else if (def_state == OUTSIDE) { fputs(if_defined, ofp); def_state = IN_IFDEF; } } fputs(pfetch(new), ofp); new++; } else { if (pch_char(new) != pch_char(old)) { say3("Out-of-sync patch, lines %ld,%ld--mangled text or line numbers, maybe?\n", pch_hunk_beg() + old, pch_hunk_beg() + new);#ifdef DEBUGGING say3("oldchar = '%c', newchar = '%c'\n", pch_char(old), pch_char(new));#endif my_exit(1); } if (pch_char(new) == '!') { copy_till(where + old - 1); if (R_do_defines) { fputs(not_defined, ofp); def_state = IN_IFNDEF; } while (pch_char(old) == '!') { if (R_do_defines) { fputs(pfetch(old), ofp); } last_frozen_line++; old++; } if (R_do_defines) { fputs(else_defined, ofp); def_state = IN_ELSE; } while (pch_char(new) == '!') { fputs(pfetch(new), ofp); new++; } if (R_do_defines) { fputs(end_defined, ofp); def_state = OUTSIDE; } } else { assert(pch_char(new) == ' '); old++; new++; } } } if (new <= pat_end && pch_char(new) == '+') { copy_till(where + old - 1); if (R_do_defines) { if (def_state == OUTSIDE) { fputs(if_defined, ofp); def_state = IN_IFDEF; } else if (def_state == IN_IFNDEF) { fputs(else_defined, ofp); def_state = IN_ELSE; } } while (new <= pat_end && pch_char(new) == '+') { fputs(pfetch(new), ofp); new++; } } if (R_do_defines && def_state != OUTSIDE) { fputs(end_defined, ofp); }}/* Open the new file. */voidinit_output(name)char *name;{ ofp = fopen(name, "w"); if (ofp == Nullfp) fatal2("patch: can't create %s.\n", name);}/* Open a file to put hunks we can't locate. */voidinit_reject(name)char *name;{ rejfp = fopen(name, "w"); if (rejfp == Nullfp) fatal2("patch: can't create %s.\n", name);}/* Copy input file to output, up to wherever hunk is to be applied. */voidcopy_till(lastline)Reg1 LINENUM lastline;{ Reg2 LINENUM R_last_frozen_line = last_frozen_line; if (R_last_frozen_line > lastline) say1("patch: misordered hunks! output will be garbled.\n"); while (R_last_frozen_line < lastline) { dump_line(++R_last_frozen_line); } last_frozen_line = R_last_frozen_line;}/* Finish copying the input file to the output file. */voidspew_output(){#ifdef DEBUGGING if (debug & 256) say3("il=%ld lfl=%ld\n",input_lines,last_frozen_line);#endif if (input_lines) copy_till(input_lines); /* dump remainder of file */ Fclose(ofp); ofp = Nullfp;}/* Copy one line from input to output. */voiddump_line(line)LINENUM line;{ Reg1 char *s; Reg2 char R_newline = '\n'; /* Note: string is not null terminated. */ for (s=ifetch(line, 0); putc(*s, ofp) != R_newline; s++) ;}/* Does the patch pattern match at line base+offset? */boolpatch_match(base, offset, fuzz)LINENUM base;LINENUM offset;LINENUM fuzz;{ Reg1 LINENUM pline = 1 + fuzz; Reg2 LINENUM iline; Reg3 LINENUM pat_lines = pch_ptrn_lines() - fuzz; for (iline=base+offset+fuzz; pline <= pat_lines; pline++,iline++) { if (canonicalize) { if (!similar(ifetch(iline, (offset >= 0)), pfetch(pline), pch_line_len(pline) )) return FALSE; } else if (strnNE(ifetch(iline, (offset >= 0)), pfetch(pline), pch_line_len(pline) )) return FALSE; } return TRUE;}/* Do two lines match with canonicalized white space? */boolsimilar(a,b,len)Reg1 char *a;Reg2 char *b;Reg3 int len;{ while (len) { if (isspace(*b)) { /* whitespace (or \n) to match? */ if (!isspace(*a)) /* no corresponding whitespace? */ return FALSE; while (len && isspace(*b) && *b != '\n') b++,len--; /* skip pattern whitespace */ while (isspace(*a) && *a != '\n') a++; /* skip target whitespace */ if (*a == '\n' || *b == '\n') return (*a == *b); /* should end in sync */ } else if (*a++ != *b++) /* match non-whitespace chars */ return FALSE; else len--; /* probably not necessary */ } return TRUE; /* actually, this is not reached */ /* since there is always a \n */}/* Exit with cleanup. */voidmy_exit(status)int status;{ Unlink(TMPINNAME); if (!toutkeep) { Unlink(TMPOUTNAME); } if (!trejkeep) { Unlink(TMPREJNAME); } Unlink(TMPPATNAME);#ifdef SMALL Unlink(TMPSTRNAME);#endif exit(status);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -