toybox
changeset 362:d15520819347
Fix reversed patch detection logic, remove unused variables, rename variables, better comments.
| author | Rob Landley <rob@landley.net> |
|---|---|
| date | Sun Nov 29 22:14:06 2009 -0600 (2009-11-29) |
| parents | e5b5c6293f58 |
| children | 2428870ce50c |
| files | toys/patch.c |
line diff
1.1 --- a/toys/patch.c Fri Oct 23 17:42:13 2009 -0500 1.2 +++ b/toys/patch.c Sun Nov 29 22:14:06 2009 -0600 1.3 @@ -50,7 +50,7 @@ 1.4 char *infile; 1.5 long prefix; 1.6 1.7 - struct double_list *plines, *flines; 1.8 + struct double_list *current_hunk; 1.9 long oldline, oldlen, newline, newlen, linenum; 1.10 int context, state, filein, fileout, filepatch, hunknum; 1.11 char *tempname; 1.12 @@ -88,18 +88,18 @@ 1.13 1.14 static void fail_hunk(void) 1.15 { 1.16 - if (!TT.plines) return; 1.17 - TT.plines->prev->next = 0; 1.18 + if (!TT.current_hunk) return; 1.19 + TT.current_hunk->prev->next = 0; 1.20 1.21 - fdprintf(2, "Hunk %d FAILED.\n", TT.hunknum); 1.22 + fdprintf(2, "Hunk %d FAILED %ld/%ld.\n", TT.hunknum, TT.oldline, TT.newline); 1.23 toys.exitval = 1; 1.24 1.25 // If we got to this point, we've seeked to the end. Discard changes to 1.26 // this file and advance to next file. 1.27 1.28 TT.state = 2; 1.29 - llist_free(TT.plines, do_line); 1.30 - TT.plines = NULL; 1.31 + llist_free(TT.current_hunk, do_line); 1.32 + TT.current_hunk = NULL; 1.33 delete_tempfile(TT.filein, TT.fileout, &TT.tempname); 1.34 TT.state = 0; 1.35 } 1.36 @@ -107,38 +107,38 @@ 1.37 static int apply_hunk(void) 1.38 { 1.39 struct double_list *plist, *buf = NULL, *check; 1.40 - int i = 0, backwards = 0, matcheof = 0, 1.41 - reverse = toys.optflags & FLAG_REVERSE; 1.42 + int matcheof = 0, reverse = toys.optflags & FLAG_REVERSE, backwarn = 0; 1.43 1.44 // Break doubly linked list so we can use singly linked traversal function. 1.45 - TT.plines->prev->next = NULL; 1.46 + TT.current_hunk->prev->next = NULL; 1.47 1.48 // Match EOF if there aren't as many ending context lines as beginning 1.49 - for (plist = TT.plines; plist; plist = plist->next) { 1.50 - if (plist->data[0]==' ') i++; 1.51 - else i = 0; 1.52 + for (plist = TT.current_hunk; plist; plist = plist->next) { 1.53 + if (plist->data[0]==' ') matcheof++; 1.54 + else matcheof = 0; 1.55 } 1.56 - if (i < TT.context) matcheof++; 1.57 + matcheof = matcheof < TT.context; 1.58 1.59 - // Search for a place to apply this hunk. Match all context lines and 1.60 - // lines to be removed. 1.61 - plist = TT.plines; 1.62 + // Loop through input data searching for this hunk. Match all context 1.63 + // lines and all lines to be removed until we've found the end of a 1.64 + // complete hunk. 1.65 + plist = TT.current_hunk; 1.66 buf = NULL; 1.67 - i = 0; 1.68 - 1.69 - // Start of for loop 1.70 if (TT.context) for (;;) { 1.71 char *data = get_line(TT.filein); 1.72 1.73 TT.linenum++; 1.74 1.75 - // Skip lines of the hunk we'd be adding. 1.76 + // Figure out which line of hunk to compare with next. (Skip lines 1.77 + // of the hunk we'd be adding.) 1.78 while (plist && *plist->data == "+-"[reverse]) { 1.79 if (data && !strcmp(data, plist->data+1)) { 1.80 - if (++backwards == TT.context) 1.81 + if (!backwarn) { 1.82 fdprintf(2,"Possibly reversed hunk %d at %ld\n", 1.83 TT.hunknum, TT.linenum); 1.84 - } else backwards=0; 1.85 + backwarn++; 1.86 + } 1.87 + } 1.88 plist = plist->next; 1.89 } 1.90 1.91 @@ -153,23 +153,30 @@ 1.92 } 1.93 check = dlist_add(&buf, data); 1.94 1.95 + // Compare this line with next expected line of hunk. 1.96 // todo: teach the strcmp() to ignore whitespace. 1.97 1.98 + // A match can fail because the next line doesn't match, or because 1.99 + // we hit the end of a hunk that needed EOF, and this isn't EOF. 1.100 + 1.101 + // If match failed, flush first line of buffered data and 1.102 + // recheck buffered data for a new match until we find one or run 1.103 + // out of buffer. 1.104 + 1.105 for (;;) { 1.106 - // If we hit the end of a hunk that needed EOF and this isn't EOF, 1.107 - // or next line doesn't match, flush first line of buffered data and 1.108 - // recheck match until we find a new match or run out of buffer. 1.109 + if (!plist || strcmp(check->data, plist->data+1)) { 1.110 + // Match failed. Write out first line of buffered data and 1.111 + // recheck remaining buffered data for a new match. 1.112 1.113 - if (!plist || strcmp(check->data, plist->data+1)) { 1.114 - // First line isn't a match, write it out. 1.115 TT.state = 3; 1.116 check = llist_pop(&buf); 1.117 check->prev->next = buf; 1.118 buf->prev = check->prev; 1.119 do_line(check); 1.120 - plist = TT.plines; 1.121 + plist = TT.current_hunk; 1.122 1.123 - // Out of buffered lines? 1.124 + // If we've reached the end of the buffer without confirming a 1.125 + // match, read more lines. 1.126 if (check==buf) { 1.127 buf = 0; 1.128 break; 1.129 @@ -185,10 +192,10 @@ 1.130 } 1.131 } 1.132 out: 1.133 - // Got it. Emit changed data. 1.134 + // We have a match. Emit changed data. 1.135 TT.state = "-+"[reverse]; 1.136 - llist_free(TT.plines, do_line); 1.137 - TT.plines = NULL; 1.138 + llist_free(TT.current_hunk, do_line); 1.139 + TT.current_hunk = NULL; 1.140 TT.state = 1; 1.141 done: 1.142 if (buf) { 1.143 @@ -229,7 +236,7 @@ 1.144 // Are we assembling a hunk? 1.145 if (state >= 2) { 1.146 if (*patchline==' ' || *patchline=='+' || *patchline=='-') { 1.147 - dlist_add(&TT.plines, patchline); 1.148 + dlist_add(&TT.current_hunk, patchline); 1.149 1.150 if (*patchline != '+') TT.oldlen--; 1.151 if (*patchline != '-') TT.newlen--;
