version 1.41, 2013/11/26 13:19:07 |
version 1.42, 2014/11/17 10:58:09 |
|
|
|
|
/* Patch (diff listing) abstract type. */ |
/* Patch (diff listing) abstract type. */ |
|
|
static long p_filesize; /* size of the patch file */ |
static off_t p_filesize; /* size of the patch file */ |
static LINENUM p_first; /* 1st line number */ |
static LINENUM p_first; /* 1st line number */ |
static LINENUM p_newfirst; /* 1st line number of replacement */ |
static LINENUM p_newfirst; /* 1st line number of replacement */ |
static LINENUM p_ptrn_lines; /* # lines in pattern */ |
static LINENUM p_ptrn_lines; /* # lines in pattern */ |
|
|
static char *p_char = NULL; /* +, -, and ! */ |
static char *p_char = NULL; /* +, -, and ! */ |
static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */ |
static int hunkmax = INITHUNKMAX; /* size of above arrays to begin with */ |
static int p_indent; /* indent to patch */ |
static int p_indent; /* indent to patch */ |
static LINENUM p_base; /* where to intuit this time */ |
static off_t p_base; /* where to intuit this time */ |
static LINENUM p_bline; /* line # of p_base */ |
static LINENUM p_bline; /* line # of p_base */ |
static LINENUM p_start; /* where intuit found a patch */ |
static off_t p_start; /* where intuit found a patch */ |
static LINENUM p_sline; /* and the line number for it */ |
static LINENUM p_sline; /* and the line number for it */ |
static LINENUM p_hunk_beg; /* line number of current hunk */ |
static LINENUM p_hunk_beg; /* line number of current hunk */ |
static LINENUM p_efake = -1; /* end of faked up lines--don't free */ |
static LINENUM p_efake = -1; /* end of faked up lines--don't free */ |
|
|
|
|
static void grow_hunkmax(void); |
static void grow_hunkmax(void); |
static int intuit_diff_type(void); |
static int intuit_diff_type(void); |
static void next_intuit_at(LINENUM, LINENUM); |
static void next_intuit_at(off_t, LINENUM); |
static void skip_to(LINENUM, LINENUM); |
static void skip_to(off_t, LINENUM); |
static char *pgets(char *, int, FILE *); |
static char *pgets(char *, int, FILE *); |
static char *best_name(const struct file_name *, bool); |
static char *best_name(const struct file_name *, bool); |
static char *posix_name(const struct file_name *, bool); |
static char *posix_name(const struct file_name *, bool); |
|
|
pfp = fopen(filename, "r"); |
pfp = fopen(filename, "r"); |
if (pfp == NULL) |
if (pfp == NULL) |
pfatal("patch file %s not found", filename); |
pfatal("patch file %s not found", filename); |
fstat(fileno(pfp), &filestat); |
if (fstat(fileno(pfp), &filestat)) |
|
pfatal("can't stat %s", filename); |
p_filesize = filestat.st_size; |
p_filesize = filestat.st_size; |
next_intuit_at(0L, 1L); /* start at the beginning */ |
next_intuit_at(0, 1L); /* start at the beginning */ |
set_hunkmax(); |
set_hunkmax(); |
} |
} |
|
|
|
|
{ |
{ |
bool exists = false; |
bool exists = false; |
|
|
if (p_base != 0L && p_base >= p_filesize) { |
if (p_base != 0 && p_base >= p_filesize) { |
if (verbose) |
if (verbose) |
say("done\n"); |
say("done\n"); |
return false; |
return false; |
|
|
say("Hmm..."); |
say("Hmm..."); |
diff_type = intuit_diff_type(); |
diff_type = intuit_diff_type(); |
if (!diff_type) { |
if (!diff_type) { |
if (p_base != 0L) { |
if (p_base != 0) { |
if (verbose) |
if (verbose) |
say(" Ignoring the trailing garbage.\ndone\n"); |
say(" Ignoring the trailing garbage.\ndone\n"); |
} else |
} else |
|
|
} |
} |
if (verbose) |
if (verbose) |
say(" %sooks like %s to me...\n", |
say(" %sooks like %s to me...\n", |
(p_base == 0L ? "L" : "The next patch l"), |
(p_base == 0 ? "L" : "The next patch l"), |
diff_type == UNI_DIFF ? "a unified diff" : |
diff_type == UNI_DIFF ? "a unified diff" : |
diff_type == CONTEXT_DIFF ? "a context diff" : |
diff_type == CONTEXT_DIFF ? "a context diff" : |
diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" : |
diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" : |
|
|
static int |
static int |
intuit_diff_type(void) |
intuit_diff_type(void) |
{ |
{ |
long this_line = 0, previous_line; |
off_t this_line = 0, previous_line; |
long first_command_line = -1; |
off_t first_command_line = -1; |
LINENUM fcl_line = -1; |
LINENUM fcl_line = -1; |
bool last_line_was_command = false, this_is_a_command = false; |
bool last_line_was_command = false, this_is_a_command = false; |
bool stars_last_line = false, stars_this_line = false; |
bool stars_last_line = false, stars_this_line = false; |
|
|
|
|
memset(names, 0, sizeof(names)); |
memset(names, 0, sizeof(names)); |
ok_to_create_file = false; |
ok_to_create_file = false; |
fseek(pfp, p_base, SEEK_SET); |
fseeko(pfp, p_base, SEEK_SET); |
p_input_line = p_bline - 1; |
p_input_line = p_bline - 1; |
for (;;) { |
for (;;) { |
previous_line = this_line; |
previous_line = this_line; |
last_line_was_command = this_is_a_command; |
last_line_was_command = this_is_a_command; |
stars_last_line = stars_this_line; |
stars_last_line = stars_this_line; |
this_line = ftell(pfp); |
this_line = ftello(pfp); |
indent = 0; |
indent = 0; |
p_input_line++; |
p_input_line++; |
if (fgets(buf, sizeof buf, pfp) == NULL) { |
if (fgets(buf, sizeof buf, pfp) == NULL) { |
if (first_command_line >= 0L) { |
if (first_command_line >= 0) { |
/* nothing but deletes!? */ |
/* nothing but deletes!? */ |
p_start = first_command_line; |
p_start = first_command_line; |
p_sline = fcl_line; |
p_sline = fcl_line; |
|
|
; |
; |
this_is_a_command = (isdigit((unsigned char)*s) && |
this_is_a_command = (isdigit((unsigned char)*s) && |
(*t == 'd' || *t == 'c' || *t == 'a')); |
(*t == 'd' || *t == 'c' || *t == 'a')); |
if (first_command_line < 0L && this_is_a_command) { |
if (first_command_line < 0 && this_is_a_command) { |
first_command_line = this_line; |
first_command_line = this_line; |
fcl_line = p_input_line; |
fcl_line = p_input_line; |
p_indent = indent; /* assume this for now */ |
p_indent = indent; /* assume this for now */ |
|
|
} |
} |
} |
} |
if ((!diff_type || diff_type == ED_DIFF) && |
if ((!diff_type || diff_type == ED_DIFF) && |
first_command_line >= 0L && |
first_command_line >= 0 && |
strEQ(s, ".\n")) { |
strEQ(s, ".\n")) { |
p_indent = indent; |
p_indent = indent; |
p_start = first_command_line; |
p_start = first_command_line; |
|
|
* Remember where this patch ends so we know where to start up again. |
* Remember where this patch ends so we know where to start up again. |
*/ |
*/ |
static void |
static void |
next_intuit_at(LINENUM file_pos, LINENUM file_line) |
next_intuit_at(off_t file_pos, LINENUM file_line) |
{ |
{ |
p_base = file_pos; |
p_base = file_pos; |
p_bline = file_line; |
p_bline = file_line; |
} |
} |
|
|
/* |
/* |
* Basically a verbose fseek() to the actual diff listing. |
* Basically a verbose fseeko() to the actual diff listing. |
*/ |
*/ |
static void |
static void |
skip_to(LINENUM file_pos, LINENUM file_line) |
skip_to(off_t file_pos, LINENUM file_line) |
{ |
{ |
char *ret; |
char *ret; |
|
|
if (p_base > file_pos) |
if (p_base > file_pos) |
fatal("Internal error: seek %ld>%ld\n", p_base, file_pos); |
fatal("Internal error: seek %lld>%lld\n", |
|
(long long)p_base, (long long)file_pos); |
if (verbose && p_base < file_pos) { |
if (verbose && p_base < file_pos) { |
fseek(pfp, p_base, SEEK_SET); |
fseeko(pfp, p_base, SEEK_SET); |
say("The text leading up to this was:\n--------------------------\n"); |
say("The text leading up to this was:\n--------------------------\n"); |
while (ftell(pfp) < file_pos) { |
while (ftello(pfp) < file_pos) { |
ret = fgets(buf, sizeof buf, pfp); |
ret = fgets(buf, sizeof buf, pfp); |
if (ret == NULL) |
if (ret == NULL) |
fatal("Unexpected end of file\n"); |
fatal("Unexpected end of file\n"); |
|
|
} |
} |
say("--------------------------\n"); |
say("--------------------------\n"); |
} else |
} else |
fseek(pfp, file_pos, SEEK_SET); |
fseeko(pfp, file_pos, SEEK_SET); |
p_input_line = file_line - 1; |
p_input_line = file_line - 1; |
} |
} |
|
|
|
|
return true; |
return true; |
} |
} |
if (c != EOF) |
if (c != EOF) |
fseek(pfp, -1L, SEEK_CUR); |
fseeko(pfp, -1, SEEK_CUR); |
|
|
return false; |
return false; |
} |
} |
|
|
bool |
bool |
another_hunk(void) |
another_hunk(void) |
{ |
{ |
long line_beginning; /* file pos of the current line */ |
off_t line_beginning; /* file pos of the current line */ |
LINENUM repl_beginning; /* index of --- line */ |
LINENUM repl_beginning; /* index of --- line */ |
LINENUM fillcnt; /* #lines of missing ptrn or repl */ |
LINENUM fillcnt; /* #lines of missing ptrn or repl */ |
LINENUM fillsrc; /* index of first line to copy */ |
LINENUM fillsrc; /* index of first line to copy */ |
|
|
bool ptrn_spaces_eaten; /* ptrn was slightly misformed */ |
bool ptrn_spaces_eaten; /* ptrn was slightly misformed */ |
bool repl_could_be_missing; /* no + or ! lines in this hunk */ |
bool repl_could_be_missing; /* no + or ! lines in this hunk */ |
bool repl_missing; /* we are now backtracking */ |
bool repl_missing; /* we are now backtracking */ |
long repl_backtrack_position; /* file pos of first repl line */ |
off_t repl_backtrack_position; /* file pos of first repl line */ |
LINENUM repl_patch_line; /* input line number for same */ |
LINENUM repl_patch_line; /* input line number for same */ |
LINENUM ptrn_copiable; /* # of copiable lines in ptrn */ |
LINENUM ptrn_copiable; /* # of copiable lines in ptrn */ |
char *s, *ret; |
char *s, *ret; |
|
|
|
|
p_max = hunkmax; /* gets reduced when --- found */ |
p_max = hunkmax; /* gets reduced when --- found */ |
if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) { |
if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) { |
line_beginning = ftell(pfp); |
line_beginning = ftello(pfp); |
repl_beginning = 0; |
repl_beginning = 0; |
fillcnt = 0; |
fillcnt = 0; |
fillsrc = 0; |
fillsrc = 0; |
|
|
p_context = 100; |
p_context = 100; |
p_hunk_beg = p_input_line + 1; |
p_hunk_beg = p_input_line + 1; |
while (p_end < p_max) { |
while (p_end < p_max) { |
line_beginning = ftell(pfp); |
line_beginning = ftello(pfp); |
ret = pgets(buf, sizeof buf, pfp); |
ret = pgets(buf, sizeof buf, pfp); |
p_input_line++; |
p_input_line++; |
if (ret == NULL) { |
if (ret == NULL) { |
|
|
} |
} |
} |
} |
repl_beginning = p_end; |
repl_beginning = p_end; |
repl_backtrack_position = ftell(pfp); |
repl_backtrack_position = ftello(pfp); |
repl_patch_line = p_input_line; |
repl_patch_line = p_input_line; |
p_line[p_end] = savestr(buf); |
p_line[p_end] = savestr(buf); |
if (out_of_mem) { |
if (out_of_mem) { |
|
|
p_input_line = repl_patch_line; |
p_input_line = repl_patch_line; |
for (p_end--; p_end > repl_beginning; p_end--) |
for (p_end--; p_end > repl_beginning; p_end--) |
free(p_line[p_end]); |
free(p_line[p_end]); |
fseek(pfp, repl_backtrack_position, SEEK_SET); |
fseeko(pfp, repl_backtrack_position, SEEK_SET); |
|
|
/* redundant 'new' context lines were omitted - set */ |
/* redundant 'new' context lines were omitted - set */ |
/* up to fill them in from the old file context */ |
/* up to fill them in from the old file context */ |
|
|
} |
} |
} |
} |
} else if (diff_type == UNI_DIFF) { |
} else if (diff_type == UNI_DIFF) { |
long line_beginning = ftell(pfp); /* file pos of the current line */ |
off_t line_beginning = ftello(pfp); /* file pos of the current line */ |
LINENUM fillsrc; /* index of old lines */ |
LINENUM fillsrc; /* index of old lines */ |
LINENUM filldst; /* index of new lines */ |
LINENUM filldst; /* index of new lines */ |
char ch; |
char ch; |
|
|
context = 0; |
context = 0; |
p_hunk_beg = p_input_line + 1; |
p_hunk_beg = p_input_line + 1; |
while (fillsrc <= p_ptrn_lines || filldst <= p_end) { |
while (fillsrc <= p_ptrn_lines || filldst <= p_end) { |
line_beginning = ftell(pfp); |
line_beginning = ftello(pfp); |
ret = pgets(buf, sizeof buf, pfp); |
ret = pgets(buf, sizeof buf, pfp); |
p_input_line++; |
p_input_line++; |
if (ret == NULL) { |
if (ret == NULL) { |
|
|
char hunk_type; |
char hunk_type; |
int i; |
int i; |
LINENUM min, max; |
LINENUM min, max; |
long line_beginning = ftell(pfp); |
off_t line_beginning = ftello(pfp); |
|
|
p_context = 0; |
p_context = 0; |
ret = pgets(buf, sizeof buf, pfp); |
ret = pgets(buf, sizeof buf, pfp); |
|
|
do_ed_script(void) |
do_ed_script(void) |
{ |
{ |
char *t; |
char *t; |
long beginning_of_this_line; |
off_t beginning_of_this_line; |
FILE *pipefp = NULL; |
FILE *pipefp = NULL; |
|
|
if (!skip_rest_of_patch) { |
if (!skip_rest_of_patch) { |
|
|
pipefp = popen(buf, "w"); |
pipefp = popen(buf, "w"); |
} |
} |
for (;;) { |
for (;;) { |
beginning_of_this_line = ftell(pfp); |
beginning_of_this_line = ftello(pfp); |
if (pgets(buf, sizeof buf, pfp) == NULL) { |
if (pgets(buf, sizeof buf, pfp) == NULL) { |
next_intuit_at(beginning_of_this_line, p_input_line); |
next_intuit_at(beginning_of_this_line, p_input_line); |
break; |
break; |