commit - 5ed6e4d2a7519005ddb8c8b7f47a02f6085df3fe
commit + 13e2caa3edcc68a62e29b4d5503254cd5bf80b2b
blob - 0bcda3a003c8741c8ea2e2801503387eb993bd12
blob + 6bd48428c4f92c5ed7c7d1695af2f866b953cefb
--- diff/diff.c
+++ diff/diff.c
};
__dead void usage(void);
-int diffreg(char *, char *, enum diffreg_algo, bool, int, bool);
+int diffreg(char *, char *, enum diffreg_algo, bool, bool,
+ int, bool);
FILE * openfile(const char *, char **, struct stat *);
__dead void
usage(void)
{
fprintf(stderr,
- "usage: %s [-PQTwe] [-U n] file1 file2\n"
+ "usage: %s [-pPQTwe] [-U n] file1 file2\n"
"\n"
+ " -p Show function prototypes in hunk headers\n"
" -P Use Patience Diff (slower but often nicer)\n"
" -Q Use forward-Myers for small files, otherwise Patience\n"
" -T Trivial algo: detect similar start and end only\n"
{
int ch, rc;
bool ignore_whitespace = false;
+ bool show_function_prototypes = false;
bool edscript = false;
int context_lines = 3;
enum diffreg_algo algo = DIFFREG_ALGO_MYERS_THEN_MYERS_DIVIDE;
- while ((ch = getopt(argc, argv, "PQTwU:e")) != -1) {
+ while ((ch = getopt(argc, argv, "pPQTwU:e")) != -1) {
switch (ch) {
+ case 'p':
+ show_function_prototypes = true;
+ break;
case 'P':
algo = DIFFREG_ALGO_PATIENCE;
break;
usage();
rc = diffreg(argv[0], argv[1], algo, ignore_whitespace,
- context_lines, edscript);
+ show_function_prototypes, context_lines, edscript);
if (rc != DIFF_RC_OK) {
fprintf(stderr, "diff: %s\n", strerror(rc));
return 1;
int
diffreg(char *file1, char *file2, enum diffreg_algo algo, bool ignore_whitespace,
- int context_lines, bool edscript)
+ bool show_function_prototypes, int context_lines, bool edscript)
{
char *str1, *str2;
FILE *f1, *f2;
if (ignore_whitespace)
diff_flags |= DIFF_FLAG_IGNORE_WHITESPACE;
+ if (show_function_prototypes)
+ diff_flags |= DIFF_FLAG_SHOW_PROTOTYPES;
result = diff_main(cfg, f1, str1, st1.st_size, f2, str2, st2.st_size,
diff_flags);
blob - f49a6893b6847f02d5127764222375f1184d051d
blob + 99669105d130b9e49ecf3ba09743e0e2c8b1e031
--- include/diff_main.h
+++ include/diff_main.h
};
#define DIFF_FLAG_IGNORE_WHITESPACE 0x00000001
+#define DIFF_FLAG_SHOW_PROTOTYPES 0x00000002
void diff_data_free(struct diff_data *diff_data);
blob - f48c869ab05318ba318a42e11631e120cedb7cb6
blob + e4d0d0f911a91395f8dd56ae7de181ff081cfbdf
--- lib/diff_internal.h
+++ lib/diff_internal.h
&& ((ATOM) - (DIFF_DATA)->atoms.head < (DIFF_DATA)->atoms.len); \
(ATOM)++)
+#define diff_data_foreach_atom_backwards_from(FROM, ATOM, DIFF_DATA) \
+ for ((ATOM) = (FROM); \
+ (ATOM) \
+ && ((ATOM) >= (DIFF_DATA)->atoms.head) \
+ && ((ATOM) - (DIFF_DATA)->atoms.head >= 0); \
+ (ATOM)--)
+
/* A diff chunk represents a set of atoms on the left and/or a set of atoms on
* the right.
*
int diff_output_trailing_newline_msg(struct diff_output_info *outinfo,
FILE *dest,
const struct diff_chunk *c);
+int diff_output_match_function_prototype(char **prototype,
+ const struct diff_result *result,
+ const struct diff_chunk_context *cc);
struct diff_output_info *diff_output_info_alloc(void);
blob - 8832026c2c75b90807d7a10e032484e14cc4efd6
blob + 5101e49206dbcf9bfcd8df71242aec39ed8f57a0
--- lib/diff_output.c
+++ lib/diff_output.c
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <arraylist.h>
return DIFF_RC_OK;
}
+static bool
+is_function_prototype(const char *buf)
+{
+ return isalpha(buf[0]) || buf[0] == '_' || buf[0] == '$';
+}
+
+#define FUNCTION_CONTEXT_SIZE 55
+
+int
+diff_output_match_function_prototype(char **prototype,
+ const struct diff_result *result,
+ const struct diff_chunk_context *cc)
+{
+ struct diff_atom *start_atom, *atom;
+ const struct diff_data *data;
+ unsigned char buf[FUNCTION_CONTEXT_SIZE];
+ int rc, i;
+
+ *prototype = NULL;
+
+ if (result->left.atoms.len > 0) {
+ data = &result->left;
+ start_atom = &data->atoms.head[cc->left.start];
+ } else if (result->right.atoms.len > 0) {
+ data = &result->right;
+ start_atom = &data->atoms.head[cc->right.start];
+ } else
+ return DIFF_RC_OK;
+
+ diff_data_foreach_atom_backwards_from(start_atom, atom, data) {
+ for (i = 0; i < atom->len && i < sizeof(buf) - 1; i++) {
+ unsigned int ch;
+ rc = get_atom_byte(&ch, atom, i);
+ if (rc)
+ return rc;
+ if (ch == '\n')
+ break;
+ buf[i] = ch;
+ }
+ buf[i] = '\0';
+ if (is_function_prototype(buf)) {
+ *prototype = strdup(buf);
+ if (*prototype == NULL)
+ return ENOMEM;
+ return DIFF_RC_OK;
+ }
+ }
+
+ return DIFF_RC_OK;
+}
+
struct diff_output_info *
diff_output_info_alloc(void)
{
blob - a0dba87608e0c39d9e91584b1864e08f921d39d3
blob + 5afb38442065c67a00db9ee4ff61c2348c491507
--- lib/diff_output_unidiff.c
+++ lib/diff_output_unidiff.c
struct diff_output_unidiff_state *state,
const struct diff_input_info *info,
const struct diff_result *result,
- bool print_header,
+ bool print_header, bool show_function_prototypes,
const struct diff_chunk_context *cc)
{
int rc, left_start, left_len, right_start, right_len;
off_t outoff = 0, *offp;
+ char *prototype = NULL;
if (diff_range_empty(&cc->left) && diff_range_empty(&cc->right))
return DIFF_RC_OK;
right_start = cc->right.start;
else
right_start = cc->right.start + 1;
+
+ if (show_function_prototypes) {
+ rc = diff_output_match_function_prototype(&prototype,
+ result, cc);
+ if (rc)
+ return rc;
+ }
if (left_len == 1 && right_len == 1) {
- rc = fprintf(dest, "@@ -%d +%d @@\n",
- left_start, right_start);
+ rc = fprintf(dest, "@@ -%d +%d @@%s%s\n",
+ left_start, right_start,
+ prototype ? " " : "",
+ prototype ? : "");
} else if (left_len == 1 && right_len != 1) {
- rc = fprintf(dest, "@@ -%d +%d,%d @@\n",
- left_start, right_start, right_len);
+ rc = fprintf(dest, "@@ -%d +%d,%d @@%s%s\n",
+ left_start, right_start, right_len,
+ prototype ? " " : "",
+ prototype ? : "");
} else if (left_len != 1 && right_len == 1) {
- rc = fprintf(dest, "@@ -%d,%d +%d @@\n",
- left_start, left_len, right_start);
+ rc = fprintf(dest, "@@ -%d,%d +%d @@%s%s\n",
+ left_start, left_len, right_start,
+ prototype ? " " : "",
+ prototype ? : "");
} else {
- rc = fprintf(dest, "@@ -%d,%d +%d,%d @@\n",
- left_start, left_len, right_start, right_len);
+ rc = fprintf(dest, "@@ -%d,%d +%d,%d @@%s%s\n",
+ left_start, left_len, right_start, right_len,
+ prototype ? " " : "",
+ prototype ? : "");
}
+ free(prototype);
if (rc < 0)
return errno;
if (outinfo) {
const struct diff_chunk_context *cc)
{
struct diff_output_info *outinfo = NULL;
+ int flags = (result->left.root->diff_flags |
+ result->right.root->diff_flags);
+ bool show_function_prototypes = (flags & DIFF_FLAG_SHOW_PROTOTYPES);
if (output_info) {
*output_info = diff_output_info_alloc();
}
return output_unidiff_chunk(outinfo, dest, state, info,
- result, false, cc);
+ result, false, show_function_prototypes, cc);
}
int
struct diff_output_unidiff_state *state;
struct diff_chunk_context cc = {};
struct diff_output_info *outinfo = NULL;
+ int flags = (result->left.root->diff_flags |
+ result->right.root->diff_flags);
+ bool show_function_prototypes = (flags & DIFF_FLAG_SHOW_PROTOTYPES);
int i;
if (!result)
" print left %d-%d right %d-%d\n",
cc.left.start, cc.left.end, cc.right.start, cc.right.end);
output_unidiff_chunk(outinfo, dest, state, info, result,
- true, &cc);
+ true, show_function_prototypes, &cc);
cc = next;
debug("new unprinted chunk is left %d-%d right %d-%d\n",
cc.left.start, cc.left.end, cc.right.start, cc.right.end);
if (!diff_chunk_context_empty(&cc))
output_unidiff_chunk(outinfo, dest, state, info, result,
- true, &cc);
+ true, show_function_prototypes, &cc);
diff_output_unidiff_state_free(state);
return DIFF_RC_OK;
}