/*
* wiggle - apply rejected patches
*
- * Copyright (C) 2003 Neil Brown <neilb@cse.unsw.edu.au>
+ * Copyright (C) 2003-2013 Neil Brown <neilb@suse.de>
*
*
* This program is free software; you can redistribute it and/or modify
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * along with this program.
*
* Author: Neil Brown
- * Email: <neilb@suse.de>
+ * Email: <neil@brown.name>
*/
+#define _GNU_SOURCE /* for asprintf */
#include <stdio.h>
#include <string.h>
#include <memory.h>
* 'start' points into a 'body' in a stream.
* When a stream is made of 'diff' hunks, there is a special
* elmnt at the start of each hunk which starts with '\0' and
- * records the line offsets of the hunk. These are 20 bytes long.
- * "\0\d{5} \d{5} \d{5}\n\0"
- * The 3 numbers are: chunk number, starting line, number if lines.
+ * records the line offsets of the hunk. These are 20+ bytes long.
+ * "\0\d{5} \d{5} \d{5}{SP funcname}?\n\0"
+ * The 3 numbers are: chunk number, starting line, number of lines.
* An element with len==0 marks EOF.
*/
struct elmnt {
short len, plen, prefix;
};
-static inline int match(struct elmnt *a, struct elmnt *b)
+static inline int match(struct elmnt *a, struct elmnt *b)
{
return
a->hash == b->hash &&
- a->len == b->len &&
- strncmp(a->start, b->start, a->len) == 0;
+ ((a->start[0] == 0 && b->start[0] == 0)
+ ||
+ (a->len == b->len &&
+ strncmp(a->start, b->start, a->len) == 0));
}
/* end-of-line is important for narrowing conflicts.
*/
static inline int ends_line(struct elmnt e)
{
- if (e.len == 20 && e.start[0] == 0)
+ if (e.len >= 20 && e.start[0] == 0)
return 1;
return e.len && e.start[e.plen-1] == '\n';
}
enum mergetype {
End, Unmatched, Unchanged, Extraneous,
Changed, Conflict, AlreadyApplied,
- } type;
+ } type, oldtype;
int a, b, c; /* start of ranges */
int al, bl, cl; /* length of ranges */
int c1, c2; /* this or next common-sequence */
int in_conflict;
- int ignored;
int lo, hi; /* region of a Changed or Unchanged that is not involved
* in a conflict.
* These are distances from start of the "before" section,
* as a directory-tree.
*/
struct plist {
- char *file;
+ char *file, *outfile;
unsigned int start, end;
int parent;
int next, prev, last;
char *before, *after;
};
-extern struct plist *sort_patches(struct plist *pl, int *np);
-extern void plist_free(struct plist *pl, int num);
-extern struct plist *parse_patch(FILE *f, FILE *of, int *np);
-extern struct stream load_segment(FILE *f, unsigned int start,
- unsigned int end);
-extern int set_prefix(struct plist *pl, int n, int strip);
-extern struct stream load_file(char *name);
-extern int split_patch(struct stream, struct stream*, struct stream*);
-extern int split_merge(struct stream, struct stream*, struct stream*,
- struct stream*);
-extern struct file split_stream(struct stream s, int type);
-extern struct csl *pdiff(struct file a, struct file b, int chunks);
-extern struct csl *diff(struct file a, struct file b);
-extern struct csl *diff_patch(struct file a, struct file b);
-extern struct csl *diff_partial(struct file a, struct file b,
- int alo, int ahi, int blo, int bhi);
+extern struct plist *wiggle_sort_patches(struct plist *pl, int *np);
+extern void wiggle_plist_free(struct plist *pl, int num);
+extern struct plist *wiggle_parse_patch(FILE *f, FILE *of, int *np);
+extern struct stream wiggle_load_segment(FILE *f, unsigned int start,
+ unsigned int end);
+extern int wiggle_set_prefix(struct plist *pl, int n, int strip);
+extern struct stream wiggle_load_file(char *name);
+extern int wiggle_split_patch(struct stream, struct stream*, struct stream*);
+extern int wiggle_split_merge(struct stream, struct stream*, struct stream*,
+ struct stream*);
+extern struct file wiggle_split_stream(struct stream s, int type);
+extern struct csl *wiggle_pdiff(struct file a, struct file b, int chunks);
+extern struct csl *wiggle_diff(struct file a, struct file b, int shortest);
+extern struct csl *wiggle_diff_patch(struct file a, struct file b, int shortest);
+extern struct csl *wiggle_diff_partial(struct file a, struct file b,
+ int alo, int ahi, int blo, int bhi);
extern struct csl *worddiff(struct stream f1, struct stream f2,
struct file *fl1p, struct file *fl2p);
-extern struct csl *csl_join(struct csl *c1, struct csl *c2);
+extern struct csl *wiggle_csl_join(struct csl *c1, struct csl *c2);
struct ci {
int conflicts, wiggles, ignored;
struct merge *merger;
};
-extern void print_merge(FILE *out,
- struct file *a, struct file *b, struct file *c,
- int words, struct merge *merger);
-extern void printword(FILE *f, struct elmnt e);
-extern int save_merge(struct file a, struct file b, struct file c,
- struct merge *merger, char *file, int backup);
-
-extern int isolate_conflicts(struct file af, struct file bf, struct file cf,
- struct csl *csl1, struct csl *csl2, int words,
- struct merge *m, int show_wiggles);
-extern struct ci make_merger(struct file a, struct file b, struct file c,
- struct csl *c1, struct csl *c2, int words,
- int ignore_already, int show_wiggles);
-
-extern void die(void);
-extern void *xmalloc(int len);
-extern int do_trace;
+extern int wiggle_print_merge(FILE *out,
+ struct file *a, struct file *b, struct file *c,
+ int words, struct merge *merger,
+ struct merge *mpos, int streampos, int offsetpos);
+extern void wiggle_printword(FILE *f, struct elmnt e);
+
+extern int wiggle_isolate_conflicts(struct file af, struct file bf, struct file cf,
+ struct csl *csl1, struct csl *csl2, int words,
+ struct merge *m, int show_wiggles, int *wigglesp);
+extern struct ci wiggle_make_merger(struct file a, struct file b, struct file c,
+ struct csl *c1, struct csl *c2, int words,
+ int ignore_already, int show_wiggles);
+
+extern void wiggle_die(char *reason);
+extern void wiggle_check_dir(char *name, int fd);
+extern void *wiggle_xmalloc(int len);
+extern int wiggle_do_trace;
extern int vpatch(int argc, char *argv[], int patch, int strip,
- int reverse, int replace, int selftest);
+ int reverse, int replace, char *outfile,
+ int selftest,
+ int ignore_blanks, int backup);
-extern char *Cmd;
+extern char *wiggle_Cmd;
extern char Version[];
extern char short_options[];
extern struct option long_options[];
enum other_options {
SELF_TEST = 300,
+ REPORT_WIGGLES,
+ NO_BACKUP,
+ NON_SPACE,
+ SHORTEST,
};
extern char Usage[];
extern char Help[];
extern void cleanlist(struct file a, struct file b, struct csl *list);
enum {
- ByLine,
- ByWord,
+ ByLine = 0,
+ ByWord = 1,
+ ByMask = 3,
+ IgnoreBlanks = 8, /* 'or'ed in */
+ WholeWord = 16,
};