Still more updates to 'p'
[wiggle.git] / extract.c
blob755a725afa8565e15392e78b69628848fe946ad0
1 /*
2 * wiggle - apply rejected patches
4 * Copyright (C) 2003 Neil Brown <neilb@cse.unsw.edu.au>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * Author: Neil Brown
22 * Email: <neilb@cse.unsw.edu.au>
23 * Paper: Neil Brown
24 * School of Computer Science and Engineering
25 * The University of New South Wales
26 * Sydney, 2052
27 * Australia
31 * split patch or merge files.
35 #include "wiggle.h"
36 #include <malloc.h>
37 #include <stdlib.h>
39 void skip_eol(char **cp, char *end)
41 char *c = *cp;
42 while (c < end && *c != '\n')
43 c++;
44 if (c < end) c++;
45 *cp = c;
48 void copyline(struct stream *s, char **cp, char *end)
50 char *from = *cp;
51 char *to = s->body+s->len;
53 while (from < end && *from != '\n')
54 *to++ = *from++;
55 if (from < end)
56 *to++ = *from++;
57 s->len = to-s->body;
58 *cp = from;
61 int split_patch(struct stream f, struct stream *f1, struct stream *f2)
63 struct stream r1, r2;
64 int chunks=0;
65 char *cp, *end;
66 int state = 0;
67 int acnt=0, bcnt=0;
68 int a,b,c,d;
69 int lineno = 0;
71 f1->body = f2->body = NULL;
73 r1.body = malloc(f.len);
74 r2.body = malloc(f.len);
75 if (!r1.body || !r2.body)
76 die();
78 r1.len = r2.len = 0;
80 cp = f.body;
81 end = f.body+f.len;
82 while (cp < end) {
83 /* state:
84 * 0 not in a patch
85 * 1 first half of context
86 * 2 second half of context
87 * 3 unified
89 lineno++;
90 switch(state) {
91 case 0:
92 if (sscanf(cp, "@@ -%d,%d +%d,%d @@", &a, &b, &c, &d)==4) {
93 acnt = b;
94 bcnt = d;
95 state = 3;
96 } else if (sscanf(cp, "*** %d,%d ****", &a, &b)==2) {
97 acnt = b-a+1;
98 state = 1;
99 } else if (sscanf(cp, "--- %d,%d ----", &c, &d)==2) {
100 bcnt = d-c+1;
101 state = 2;
103 skip_eol(&cp, end);
104 if (state==1 || state == 3) {
105 char buf[20];
106 buf[0] = 0;
107 chunks++;
108 sprintf(buf+1, "%5d %5d %5d\n", chunks, a, acnt);
109 memcpy(r1.body+r1.len, buf, 19);
110 r1.len += 19;
112 if (state==2 || state == 3) {
113 char buf[20];
114 buf[0] = 0;
115 sprintf(buf+1, "%5d %5d %5d\n", chunks, c, bcnt);
116 memcpy(r2.body+r2.len, buf, 19);
117 r2.len += 19;
119 break;
120 case 1:
121 if ((*cp == ' ' || *cp=='!' || *cp == '-' || *cp == '+')
122 && cp[1] == ' ') {
123 cp+=2;
124 copyline(&r1, &cp, end);
125 acnt--;
126 if (acnt == 0)
127 state = 0;
128 } else {
129 fprintf(stderr, "wiggle: bad context patch at line %d\n", lineno);
130 return 0;
132 break;
133 case 2:
134 if ((*cp == ' ' || *cp=='!' || *cp == '-' || *cp == '+')
135 && cp[1] == ' ') {
136 cp+= 2;
137 copyline(&r2, &cp, end);
138 bcnt--;
139 if (bcnt == 0)
140 state = 0;
141 } else {
142 fprintf(stderr, "wiggle: bad context patch/2 at line %d\n", lineno);
143 return 0;
145 break;
146 case 3:
147 if (*cp == ' ') {
148 char *cp2;
149 cp++;
150 cp2 = cp;
151 copyline(&r1, &cp, end);
152 copyline(&r2, &cp2, end);
153 acnt--; bcnt--;
154 } else if (*cp == '-') {
155 cp++;
156 copyline(&r1, &cp, end);
157 acnt--;
158 } else if (*cp == '+') {
159 cp++;
160 copyline(&r2, &cp, end);
161 bcnt--;
162 } else {
163 fprintf(stderr, "wiggle: bad unified patch at line %d\n", lineno);
164 return 0;
166 if (acnt <= 0 && bcnt <= 0)
167 state = 0;
168 break;
171 if (r1.len > f.len || r2.len > f.len)
172 abort();
173 *f1 = r1;
174 *f2 = r2;
175 return chunks;
179 * extract parts of a "diff3 -m" or "wiggle -m" output
181 int split_merge(struct stream f, struct stream *f1, struct stream *f2, struct stream *f3)
183 int lineno;
184 int state = 0;
185 char *cp, *end;
186 struct stream r1,r2,r3;
187 f1->body = f2->body = f2->body = NULL;
189 r1.body = malloc(f.len);
190 r2.body = malloc(f.len);
191 r3.body = malloc(f.len);
192 if (!r1.body || !r2.body || !r3.body)
193 die();
195 r1.len = r2.len = r3.len = 0;
197 cp = f.body;
198 end = f.body+f.len;
199 while (cp < end) {
200 /* state:
201 * 0 not in conflict
202 * 1 in file 1 of conflict
203 * 2 in file 2 of conflict
204 * 3 in file 3 of conflict
206 int len = end-cp;
207 lineno++;
208 switch(state) {
209 case 0:
210 if (len>=8 &&
211 strncmp(cp, "<<<<<<<", 7)==0 &&
212 (cp[7] == ' ' || cp[7] == '\n')
214 state = 1;
215 skip_eol(&cp, end);
216 } else {
217 char *cp2= cp;
218 copyline(&r1, &cp2, end);
219 cp2 = cp;
220 copyline(&r2, &cp2, end);
221 copyline(&r3, &cp, end);
223 break;
224 case 1:
225 if (len>=8 &&
226 strncmp(cp, "|||||||", 7)==0 &&
227 (cp[7] == ' ' || cp[7] == '\n')
229 state = 2;
230 skip_eol(&cp, end);
231 } else
232 copyline(&r1, &cp, end);
233 break;
234 case 2:
235 if (len>=8 &&
236 strncmp(cp, "=======", 7)==0 &&
237 (cp[7] == ' ' || cp[7] == '\n')
239 state = 3;
240 skip_eol(&cp, end);
241 } else
242 copyline(&r2, &cp, end);
243 break;
244 case 3:
245 if (len>=8 &&
246 strncmp(cp, ">>>>>>>", 7)==0 &&
247 (cp[7] == ' ' || cp[7] == '\n')
249 state = 0;
250 skip_eol(&cp, end);
251 } else
252 copyline(&r3, &cp, end);
253 break;
256 *f1 = r1;
257 *f2 = r2;
258 *f3 = r3;
259 return state == 0;