summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2004-09-01 15:06:09 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2004-09-01 15:06:09 +0000
commit174ab8396535806d77708990568f9817d11d5bb3 (patch)
tree66bd7b055747e81d50846c4fb137b2abf93d4fe4 /src
parent203069b84a21bd917b6d971705fcf0480579e718 (diff)
downloaddiffutils-174ab8396535806d77708990568f9817d11d5bb3.tar.gz
(recursive, new_file, unidirectional_new_file,
report_identical_files): Move into struct diffopt. All uses changed. (exclude_options, compare_files, specify_style, check_stdout): New arg OPT. All uses changed. (GDIFF_MAIN): Remove. All uses removed. (function_regexp_list, ignore_regexp_list): No longer static; now locals in 'main'. (main): Set opt.function_regexp, opt.ignore_regexp if using regexps; all other code now tests these pointers rather than inspecting fastmap internals. New local OPT to hold former statics; initialize it. (init_regexp_list): New function, used by main. (summarize_regexp_list): Now returns struct re_pattern_buffer *, and assumes reglist->regexps is not NULL. All uses changed.
Diffstat (limited to 'src')
-rw-r--r--src/diff.c544
1 files changed, 271 insertions, 273 deletions
diff --git a/src/diff.c b/src/diff.c
index a975107..1546819 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -20,7 +20,6 @@
If not, write to the Free Software Foundation,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-#define GDIFF_MAIN
#include "diff.h"
#include "paths.h"
#include <c-stack.h>
@@ -53,25 +52,16 @@ struct regexp_list
struct re_pattern_buffer *buf;
};
-static int compare_files (struct comparison const *, char const *, char const *);
+static int compare_files (struct comparison const *, char const *, char const *, struct diffopt *);
+static void init_regexp_list (struct regexp_list *, struct re_pattern_buffer *);
static void add_regexp (struct regexp_list *, char const *);
-static void summarize_regexp_list (struct regexp_list *);
-static void specify_style (enum output_style);
+static struct re_pattern_buffer *summarize_regexp_list (struct regexp_list *);
+static void specify_style (enum output_style, struct diffopt *);
static void specify_value (char const **, char const *, char const *);
static void try_help (char const *, char const *) __attribute__((noreturn));
-static void check_stdout (void);
+static void check_stdout (struct diffopt const *);
static void usage (void);
-/* If comparing directories, compare their common subdirectories
- recursively. */
-static bool recursive;
-
-/* In context diffs, show previous lines that match these regexps. */
-static struct regexp_list function_regexp_list;
-
-/* Ignore changes affecting only lines that match these regexps. */
-static struct regexp_list ignore_regexp_list;
-
#if HAVE_SETMODE_DOS
/* Use binary I/O when reading and writing data (--binary).
On POSIX hosts, this has no effect. */
@@ -79,62 +69,6 @@ static bool binary;
#else
enum { binary = true };
#endif
-
-/* When comparing directories, if a file appears only in one
- directory, treat it as present but empty in the other (-N).
- Then `patch' would create the file with appropriate contents. */
-static bool new_file;
-
-/* When comparing directories, if a file appears only in the second
- directory of the two, treat it as present but empty in the other
- (--unidirectional-new-file).
- Then `patch' would create the file with appropriate contents. */
-static bool unidirectional_new_file;
-
-/* Report files compared that are the same (-s).
- Normally nothing is output when that happens. */
-static bool report_identical_files;
-
-
-/* Return a string containing the command options with which diff was invoked.
- Spaces appear between what were separate ARGV-elements.
- There is a space at the beginning but none at the end.
- If there were no options, the result is an empty string.
-
- Arguments: OPTIONVEC, a vector containing separate ARGV-elements, and COUNT,
- the length of that vector. */
-
-static char *
-option_list (char **optionvec, int count)
-{
- int i;
- size_t size = 1;
- char *result;
- char *p;
-
- for (i = 0; i < count; i++)
- size += 1 + quote_system_arg ((char *) 0, optionvec[i]);
-
- p = result = xmalloc (size);
-
- for (i = 0; i < count; i++)
- {
- *p++ = ' ';
- p += quote_system_arg (p, optionvec[i]);
- }
-
- *p = 0;
- return result;
-}
-
-
-/* Return an option value suitable for add_exclude. */
-
-static int
-exclude_options (void)
-{
- return EXCLUDE_WILDCARDS | (ignore_file_name_case ? FNM_CASEFOLD : 0);
-}
static char const shortopts[] =
"0123456789abBcC:dD:eEfF:hHiI:lL:nNpPqrsS:tTuU:vwW:x:X:y";
@@ -244,6 +178,49 @@ static struct option const longopts[] =
{0, 0, 0, 0}
};
+/* Program name. */
+char *program_name;
+
+/* Return a string containing the command options with which diff was invoked.
+ Spaces appear between what were separate ARGV-elements.
+ There is a space at the beginning but none at the end.
+ If there were no options, the result is an empty string.
+
+ Arguments: OPTIONVEC, a vector containing separate ARGV-elements, and COUNT,
+ the length of that vector. */
+
+static char *
+option_list (char **optionvec, int count)
+{
+ int i;
+ size_t size = 1;
+ char *result;
+ char *p;
+
+ for (i = 0; i < count; i++)
+ size += 1 + quote_system_arg (NULL, optionvec[i]);
+
+ p = result = xmalloc (size);
+
+ for (i = 0; i < count; i++)
+ {
+ *p++ = ' ';
+ p += quote_system_arg (p, optionvec[i]);
+ }
+
+ *p = '\0';
+ return result;
+}
+
+
+/* Return an option value suitable for add_exclude. */
+
+static int
+exclude_options (struct diffopt const *opt)
+{
+ return EXCLUDE_WILDCARDS | (opt->ignore_file_name_case ? FNM_CASEFOLD : 0);
+}
+
int
main (int argc, char **argv)
{
@@ -255,10 +232,15 @@ main (int argc, char **argv)
bool explicit_context = false;
size_t width = 0;
bool show_c_function = false;
- char const *from_file = 0;
- char const *to_file = 0;
+ char const *from_file = NULL;
+ char const *to_file = NULL;
uintmax_t numval;
char *numend;
+ struct regexp_list function_regexp_list;
+ struct regexp_list ignore_regexp_list;
+ struct re_pattern_buffer function_regexp;
+ struct re_pattern_buffer ignore_regexp;
+ struct diffopt opt;
/* Do our initializations. */
exit_failure = 2;
@@ -268,14 +250,16 @@ main (int argc, char **argv)
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
c_stack_action (0);
- function_regexp_list.buf = &function_regexp;
- ignore_regexp_list.buf = &ignore_regexp;
re_set_syntax (RE_SYNTAX_GREP | RE_NO_POSIX_BACKTRACKING);
- excluded = new_exclude ();
+
+ memset (&opt, 0, sizeof opt);
+ init_regexp_list (&function_regexp_list, &function_regexp);
+ init_regexp_list (&ignore_regexp_list, &ignore_regexp);
+ opt.excluded = new_exclude ();
/* Decode the options. */
- while ((c = getopt_long (argc, argv, shortopts, longopts, 0)) != -1)
+ while ((c = getopt_long (argc, argv, shortopts, longopts, NULL)) != -1)
{
switch (c)
{
@@ -300,16 +284,16 @@ main (int argc, char **argv)
break;
case 'a':
- text = true;
+ opt.text = true;
break;
case 'b':
- if (ignore_white_space < IGNORE_SPACE_CHANGE)
- ignore_white_space = IGNORE_SPACE_CHANGE;
+ if (opt.ignore_white_space < IGNORE_SPACE_CHANGE)
+ opt.ignore_white_space = IGNORE_SPACE_CHANGE;
break;
case 'B':
- ignore_blank_lines = true;
+ opt.ignore_blank_lines = true;
break;
case 'C':
@@ -326,25 +310,25 @@ main (int argc, char **argv)
else
numval = 3;
- specify_style (c == 'U' ? OUTPUT_UNIFIED : OUTPUT_CONTEXT);
- if (context < numval)
- context = numval;
+ specify_style (c == 'U' ? OUTPUT_UNIFIED : OUTPUT_CONTEXT, &opt);
+ if (opt.context < numval)
+ opt.context = numval;
explicit_context = true;
}
break;
case 'c':
- specify_style (OUTPUT_CONTEXT);
- if (context < 3)
- context = 3;
+ specify_style (OUTPUT_CONTEXT, &opt);
+ if (opt.context < 3)
+ opt.context = 3;
break;
case 'd':
- minimal = true;
+ opt.minimal = true;
break;
case 'D':
- specify_style (OUTPUT_IFDEF);
+ specify_style (OUTPUT_IFDEF, &opt);
{
static char const C_ifdef_group_formats[] =
"%%=%c#ifndef %s\n%%<#endif /* ! %s */\n%c#ifdef %s\n%%>#endif /* %s */\n%c#ifndef %s\n%%<#else /* %s */\n%%>#endif /* %s */\n";
@@ -356,25 +340,27 @@ main (int argc, char **argv)
optarg, optarg, 0,
optarg, optarg, 0,
optarg, optarg, optarg);
- for (i = 0; i < sizeof group_format / sizeof *group_format; i++)
+ for (i = 0;
+ i < sizeof opt.group_format / sizeof opt.group_format[0];
+ i++)
{
- specify_value (&group_format[i], b, "-D");
+ specify_value (&opt.group_format[i], b, "-D");
b += strlen (b) + 1;
}
}
break;
case 'e':
- specify_style (OUTPUT_ED);
+ specify_style (OUTPUT_ED, &opt);
break;
case 'E':
- if (ignore_white_space < IGNORE_TAB_EXPANSION)
- ignore_white_space = IGNORE_TAB_EXPANSION;
+ if (opt.ignore_white_space < IGNORE_TAB_EXPANSION)
+ opt.ignore_white_space = IGNORE_TAB_EXPANSION;
break;
case 'f':
- specify_style (OUTPUT_FORWARD_ED);
+ specify_style (OUTPUT_FORWARD_ED, &opt);
break;
case 'F':
@@ -389,11 +375,11 @@ main (int argc, char **argv)
break;
case 'H':
- speed_large_files = true;
+ opt.speed_large_files = true;
break;
case 'i':
- ignore_case = true;
+ opt.ignore_case = true;
break;
case 'I':
@@ -402,8 +388,8 @@ main (int argc, char **argv)
case 'l':
if (!pr_program[0])
- try_help ("pagination not supported on this host", 0);
- paginate = true;
+ try_help ("pagination not supported on this host", NULL);
+ opt.paginate = true;
#ifdef SIGCHLD
/* Pagination requires forking and waiting, and
System V fork+wait does not work if SIGCHLD is ignored. */
@@ -412,20 +398,20 @@ main (int argc, char **argv)
break;
case 'L':
- if (!file_label[0])
- file_label[0] = optarg;
- else if (!file_label[1])
- file_label[1] = optarg;
+ if (!opt.file_label[0])
+ opt.file_label[0] = optarg;
+ else if (!opt.file_label[1])
+ opt.file_label[1] = optarg;
else
- fatal ("too many file label options");
+ fatal ("too many file label options", &opt);
break;
case 'n':
- specify_style (OUTPUT_RCS);
+ specify_style (OUTPUT_RCS, &opt);
break;
case 'N':
- new_file = true;
+ opt.new_file = true;
break;
case 'p':
@@ -434,62 +420,62 @@ main (int argc, char **argv)
break;
case 'P':
- unidirectional_new_file = true;
+ opt.unidirectional_new_file = true;
break;
case 'q':
- brief = true;
+ opt.brief = true;
break;
case 'r':
- recursive = true;
+ opt.recursive = true;
break;
case 's':
- report_identical_files = true;
+ opt.report_identical_files = true;
break;
case 'S':
- specify_value (&starting_file, optarg, "-S");
+ specify_value (&opt.starting_file, optarg, "-S");
break;
case 't':
- expand_tabs = true;
+ opt.expand_tabs = true;
break;
case 'T':
- initial_tab = true;
+ opt.initial_tab = true;
break;
case 'u':
- specify_style (OUTPUT_UNIFIED);
- if (context < 3)
- context = 3;
+ specify_style (OUTPUT_UNIFIED, &opt);
+ if (opt.context < 3)
+ opt.context = 3;
break;
case 'v':
version_etc (stdout, "diff", PACKAGE_NAME, PACKAGE_VERSION,
"Paul Eggert", "Mike Haertel", "David Hayes",
- "Richard Stallman", "Len Tower", (char *) 0);
- check_stdout ();
+ "Richard Stallman", "Len Tower", (char *) NULL);
+ check_stdout (&opt);
return EXIT_SUCCESS;
case 'w':
- ignore_white_space = IGNORE_ALL_SPACE;
+ opt.ignore_white_space = IGNORE_ALL_SPACE;
break;
case 'x':
- add_exclude (excluded, optarg, exclude_options ());
+ add_exclude (opt.excluded, optarg, exclude_options (&opt));
break;
case 'X':
- if (add_exclude_file (add_exclude, excluded, optarg,
- exclude_options (), '\n'))
- pfatal_with_name (optarg);
+ if (add_exclude_file (add_exclude, opt.excluded, optarg,
+ exclude_options (&opt), '\n'))
+ pfatal_with_name (optarg, &opt);
break;
case 'y':
- specify_style (OUTPUT_SDIFF);
+ specify_style (OUTPUT_SDIFF, &opt);
break;
case 'W':
@@ -499,7 +485,7 @@ main (int argc, char **argv)
if (width != numval)
{
if (width)
- fatal ("conflicting width options");
+ fatal ("conflicting width options", &opt);
width = numval;
}
break;
@@ -517,18 +503,18 @@ main (int argc, char **argv)
case HELP_OPTION:
usage ();
- check_stdout ();
+ check_stdout (&opt);
return EXIT_SUCCESS;
case HORIZON_LINES_OPTION:
numval = strtoumax (optarg, &numend, 10);
if (*numend)
try_help ("invalid horizon length `%s'", optarg);
- horizon_lines = MAX (horizon_lines, MIN (numval, LIN_MAX));
+ opt.horizon_lines = MAX (opt.horizon_lines, MIN (numval, LIN_MAX));
break;
case IGNORE_FILE_NAME_CASE_OPTION:
- ignore_file_name_case = true;
+ opt.ignore_file_name_case = true;
break;
case INHIBIT_HUNK_MERGE_OPTION:
@@ -537,45 +523,47 @@ main (int argc, char **argv)
break;
case LEFT_COLUMN_OPTION:
- left_column = true;
+ opt.left_column = true;
break;
case LINE_FORMAT_OPTION:
- specify_style (OUTPUT_IFDEF);
- for (i = 0; i < sizeof line_format / sizeof *line_format; i++)
- specify_value (&line_format[i], optarg, "--line-format");
+ specify_style (OUTPUT_IFDEF, &opt);
+ for (i = 0;
+ i < sizeof opt.line_format / sizeof opt.line_format[0];
+ i++)
+ specify_value (&opt.line_format[i], optarg, "--line-format");
break;
case NO_IGNORE_FILE_NAME_CASE_OPTION:
- ignore_file_name_case = false;
+ opt.ignore_file_name_case = false;
break;
case NORMAL_OPTION:
- specify_style (OUTPUT_NORMAL);
+ specify_style (OUTPUT_NORMAL, &opt);
break;
case SDIFF_MERGE_ASSIST_OPTION:
- specify_style (OUTPUT_SDIFF);
- sdiff_merge_assist = true;
+ specify_style (OUTPUT_SDIFF, &opt);
+ opt.sdiff_merge_assist = true;
break;
case STRIP_TRAILING_CR_OPTION:
- strip_trailing_cr = true;
+ opt.strip_trailing_cr = true;
break;
case SUPPRESS_COMMON_LINES_OPTION:
- suppress_common_lines = true;
+ opt.suppress_common_lines = true;
break;
case TABSIZE_OPTION:
numval = strtoumax (optarg, &numend, 10);
if (! (0 < numval && numval <= SIZE_MAX) || *numend)
try_help ("invalid tabsize `%s'", optarg);
- if (tabsize != numval)
+ if (opt.tabsize != numval)
{
- if (tabsize)
- fatal ("conflicting tabsize options");
- tabsize = numval;
+ if (opt.tabsize)
+ fatal ("conflicting tabsize options", &opt);
+ opt.tabsize = numval;
}
break;
@@ -586,71 +574,71 @@ main (int argc, char **argv)
case UNCHANGED_LINE_FORMAT_OPTION:
case OLD_LINE_FORMAT_OPTION:
case NEW_LINE_FORMAT_OPTION:
- specify_style (OUTPUT_IFDEF);
+ specify_style (OUTPUT_IFDEF, &opt);
c -= UNCHANGED_LINE_FORMAT_OPTION;
- specify_value (&line_format[c], optarg, line_format_option[c]);
+ specify_value (&opt.line_format[c], optarg, line_format_option[c]);
break;
case UNCHANGED_GROUP_FORMAT_OPTION:
case OLD_GROUP_FORMAT_OPTION:
case NEW_GROUP_FORMAT_OPTION:
case CHANGED_GROUP_FORMAT_OPTION:
- specify_style (OUTPUT_IFDEF);
+ specify_style (OUTPUT_IFDEF, &opt);
c -= UNCHANGED_GROUP_FORMAT_OPTION;
- specify_value (&group_format[c], optarg, group_format_option[c]);
+ specify_value (&opt.group_format[c], optarg, group_format_option[c]);
break;
default:
- try_help (0, 0);
+ try_help (NULL, NULL);
}
prev = c;
}
- if (output_style == OUTPUT_UNSPECIFIED)
+ if (opt.output_style == OUTPUT_UNSPECIFIED)
{
if (show_c_function)
{
- specify_style (OUTPUT_CONTEXT);
+ specify_style (OUTPUT_CONTEXT, &opt);
if (ocontext < 0)
- context = 3;
+ opt.context = 3;
}
else
- specify_style (OUTPUT_NORMAL);
+ specify_style (OUTPUT_NORMAL, &opt);
}
- if (output_style != OUTPUT_CONTEXT || hard_locale (LC_TIME))
+ if (opt.output_style != OUTPUT_CONTEXT || hard_locale (LC_TIME))
{
#ifdef ST_MTIM_NSEC
- time_format = "%Y-%m-%d %H:%M:%S.%N %z";
+ opt.time_format = "%Y-%m-%d %H:%M:%S.%N %z";
#else
- time_format = "%Y-%m-%d %H:%M:%S %z";
+ opt.time_format = "%Y-%m-%d %H:%M:%S %z";
#endif
}
else
{
/* See POSIX 1003.1-2001 for this format. */
- time_format = "%a %b %e %T %Y";
+ opt.time_format = "%a %b %e %T %Y";
}
if (0 <= ocontext)
{
bool modern_usage = 200112 <= posix2_version ();
- if ((output_style == OUTPUT_CONTEXT
- || output_style == OUTPUT_UNIFIED)
- && (context < ocontext
- || (ocontext < context && ! explicit_context)))
+ if ((opt.output_style == OUTPUT_CONTEXT
+ || opt.output_style == OUTPUT_UNIFIED)
+ && (opt.context < ocontext
+ || (ocontext < opt.context && ! explicit_context)))
{
if (modern_usage)
{
error (0, 0,
_("`-%ld' option is obsolete; use `-%c %ld'"),
(long int) ocontext,
- output_style == OUTPUT_CONTEXT ? 'C' : 'U',
+ opt.output_style == OUTPUT_CONTEXT ? 'C' : 'U',
(long int) ocontext);
- try_help (0, 0);
+ try_help (NULL, NULL);
}
- context = ocontext;
+ opt.context = ocontext;
}
else
{
@@ -658,13 +646,13 @@ main (int argc, char **argv)
{
error (0, 0, _("`-%ld' option is obsolete; omit it"),
(long int) ocontext);
- try_help (0, 0);
+ try_help (NULL, NULL);
}
}
}
- if (! tabsize)
- tabsize = 8;
+ if (! opt.tabsize)
+ opt.tabsize = 8;
if (! width)
width = 130;
@@ -679,62 +667,63 @@ main (int argc, char **argv)
a half line plus a gutter is an integral number of tabs,
so that tabs in the right column line up. */
- intmax_t t = expand_tabs ? 1 : tabsize;
+ intmax_t t = opt.expand_tabs ? 1 : opt.tabsize;
intmax_t w = width;
intmax_t off = (w + t + GUTTER_WIDTH_MINIMUM) / (2 * t) * t;
- sdiff_half_width = MAX (0, MIN (off - GUTTER_WIDTH_MINIMUM, w - off)),
- sdiff_column2_offset = sdiff_half_width ? off : w;
+ opt.sdiff_half_width = MAX (0, MIN (off - GUTTER_WIDTH_MINIMUM, w - off)),
+ opt.sdiff_column2_offset = opt.sdiff_half_width ? off : w;
}
/* Make the horizon at least as large as the context, so that
shift_boundaries has more freedom to shift the first and last hunks. */
- if (horizon_lines < context)
- horizon_lines = context;
+ if (opt.horizon_lines < opt.context)
+ opt.horizon_lines = opt.context;
- summarize_regexp_list (&function_regexp_list);
- summarize_regexp_list (&ignore_regexp_list);
+ if (function_regexp_list.regexps)
+ opt.function_regexp = summarize_regexp_list (&function_regexp_list);
+ if (ignore_regexp_list.regexps)
+ opt.ignore_regexp = summarize_regexp_list (&ignore_regexp_list);
- if (output_style == OUTPUT_IFDEF)
+ if (opt.output_style == OUTPUT_IFDEF)
{
- for (i = 0; i < sizeof line_format / sizeof *line_format; i++)
- if (!line_format[i])
- line_format[i] = "%l\n";
- if (!group_format[OLD])
- group_format[OLD]
- = group_format[CHANGED] ? group_format[CHANGED] : "%<";
- if (!group_format[NEW])
- group_format[NEW]
- = group_format[CHANGED] ? group_format[CHANGED] : "%>";
- if (!group_format[UNCHANGED])
- group_format[UNCHANGED] = "%=";
- if (!group_format[CHANGED])
- group_format[CHANGED] = concat (group_format[OLD],
- group_format[NEW], "");
+ for (i = 0; i < sizeof opt.line_format / sizeof opt.line_format[0]; i++)
+ if (!opt.line_format[i])
+ opt.line_format[i] = "%l\n";
+ if (!opt.group_format[OLD])
+ opt.group_format[OLD]
+ = opt.group_format[CHANGED] ? opt.group_format[CHANGED] : "%<";
+ if (!opt.group_format[NEW])
+ opt.group_format[NEW]
+ = opt.group_format[CHANGED] ? opt.group_format[CHANGED] : "%>";
+ if (!opt.group_format[UNCHANGED])
+ opt.group_format[UNCHANGED] = "%=";
+ if (!opt.group_format[CHANGED])
+ opt.group_format[CHANGED] = concat (opt.group_format[OLD],
+ opt.group_format[NEW], "");
}
- no_diff_means_no_output =
- (output_style == OUTPUT_IFDEF ?
- (!*group_format[UNCHANGED]
- || (strcmp (group_format[UNCHANGED], "%=") == 0
- && !*line_format[UNCHANGED]))
- : (output_style != OUTPUT_SDIFF) | suppress_common_lines);
+ opt.no_diff_means_no_output =
+ (opt.output_style == OUTPUT_IFDEF ?
+ (!*opt.group_format[UNCHANGED]
+ || (strcmp (opt.group_format[UNCHANGED], "%=") == 0
+ && !*opt.line_format[UNCHANGED]))
+ : (opt.output_style != OUTPUT_SDIFF) | opt.suppress_common_lines);
- files_can_be_treated_as_binary =
- (brief & binary
- & ~ (ignore_blank_lines | ignore_case | strip_trailing_cr
- | (ignore_regexp_list.regexps || ignore_white_space)));
+ opt.files_can_be_treated_as_binary =
+ (opt.brief & binary
+ & ~ (opt.ignore_blank_lines | opt.ignore_case | opt.strip_trailing_cr
+ | (ignore_regexp_list.regexps || opt.ignore_white_space)));
- switch_string = option_list (argv + 1, optind - 1);
+ opt.switch_string = option_list (argv + 1, optind - 1);
if (from_file)
{
if (to_file)
- fatal ("--from-file and --to-file both specified");
+ fatal ("--from-file and --to-file both specified", &opt);
else
for (; optind < argc; optind++)
{
- int status = compare_files ((struct comparison *) 0,
- from_file, argv[optind]);
+ int status = compare_files (NULL, from_file, argv[optind], &opt);
if (exit_status < status)
exit_status = status;
}
@@ -744,8 +733,7 @@ main (int argc, char **argv)
if (to_file)
for (; optind < argc; optind++)
{
- int status = compare_files ((struct comparison *) 0,
- argv[optind], to_file);
+ int status = compare_files (NULL, argv[optind], to_file, &opt);
if (exit_status < status)
exit_status = status;
}
@@ -759,19 +747,31 @@ main (int argc, char **argv)
try_help ("extra operand `%s'", argv[optind + 2]);
}
- exit_status = compare_files ((struct comparison *) 0,
- argv[optind], argv[optind + 1]);
+ exit_status = compare_files (NULL, argv[optind], argv[optind + 1],
+ &opt);
}
}
/* Print any messages that were saved up for last. */
- print_message_queue ();
+ print_message_queue (&opt);
- check_stdout ();
+ check_stdout (&opt);
exit (exit_status);
return exit_status;
}
+/* Initialize REGLIST for BUF. */
+
+static void
+init_regexp_list (struct regexp_list *reglist, struct re_pattern_buffer *buf)
+{
+ reglist->regexps = NULL;
+ reglist->len = 0;
+ reglist->size = 0;
+ reglist->multiple_regexps = false;
+ reglist->buf = buf;
+}
+
/* Append to REGLIST the regexp PATTERN. */
static void
@@ -811,25 +811,23 @@ add_regexp (struct regexp_list *reglist, char const *pattern)
}
/* Ensure that REGLIST represents the disjunction of its regexps.
- This is done here, rather than earlier, to avoid O(N^2) behavior. */
+ This is done here, rather than earlier, to avoid O(N^2) behavior.
+ Return the compiled regular expression summarizing the disjunction. */
-static void
+static struct re_pattern_buffer *
summarize_regexp_list (struct regexp_list *reglist)
{
- if (reglist->regexps)
+ reglist->buf->fastmap = xmalloc (1 << CHAR_BIT);
+ if (reglist->multiple_regexps)
{
- /* At least one regexp was specified. Allocate a fastmap for it. */
- reglist->buf->fastmap = xmalloc (1 << CHAR_BIT);
- if (reglist->multiple_regexps)
- {
- /* Compile the disjunction of the regexps.
- (If just one regexp was specified, it is already compiled.) */
- char const *m = re_compile_pattern (reglist->regexps, reglist->len,
- reglist->buf);
- if (m != 0)
- error (EXIT_TROUBLE, 0, "%s: %s", reglist->regexps, m);
- }
+ /* Compile the disjunction of the regexps.
+ (If just one regexp was specified, it is already compiled.) */
+ char const *m = re_compile_pattern (reglist->regexps, reglist->len,
+ reglist->buf);
+ if (m)
+ error (EXIT_TROUBLE, 0, "%s: %s", reglist->regexps, m);
}
+ return reglist->buf;
}
static void
@@ -843,12 +841,12 @@ try_help (char const *reason_msgid, char const *operand)
}
static void
-check_stdout (void)
+check_stdout (struct diffopt const *opt)
{
if (ferror (stdout))
- fatal ("write failed");
+ fatal ("write failed", opt);
else if (fclose (stdout) != 0)
- pfatal_with_name (_("standard output"));
+ pfatal_with_name (_("standard output"), opt);
}
static char const * const option_help_msgid[] = {
@@ -972,20 +970,20 @@ specify_value (char const **var, char const *value, char const *option)
if (*var && strcmp (*var, value) != 0)
{
error (0, 0, _("conflicting %s option value `%s'"), option, value);
- try_help (0, 0);
+ try_help (NULL, NULL);
}
*var = value;
}
/* Set the output style to STYLE, diagnosing conflicts. */
static void
-specify_style (enum output_style style)
+specify_style (enum output_style style, struct diffopt *opt)
{
- if (output_style != style)
+ if (opt->output_style != style)
{
- if (output_style != OUTPUT_UNSPECIFIED)
- try_help ("conflicting output style options", 0);
- output_style = style;
+ if (opt->output_style != OUTPUT_UNSPECIFIED)
+ try_help ("conflicting output style options", NULL);
+ opt->output_style = style;
}
}
@@ -1020,7 +1018,7 @@ set_mtime_to_now (struct stat *st)
/* Compare two files (or dirs) with parent comparison PARENT
and names NAME0 and NAME1.
- (If PARENT is 0, then the first name is just NAME0, etc.)
+ (If PARENT is null, then the first name is just NAME0, etc.)
This is self-contained; it opens the files and closes them.
Value is EXIT_SUCCESS if files are the same, EXIT_FAILURE if
@@ -1029,28 +1027,30 @@ set_mtime_to_now (struct stat *st)
static int
compare_files (struct comparison const *parent,
char const *name0,
- char const *name1)
+ char const *name1,
+ struct diffopt *opt)
{
struct comparison cmp;
#define DIR_P(f) (S_ISDIR (cmp.file[f].stat.st_mode) != 0)
register int f;
int status = EXIT_SUCCESS;
bool same_files;
- char *free0, *free1;
+ char *free0;
+ char *free1;
/* If this is directory comparison, perhaps we have a file
that exists only in one of the directories.
If so, just print a message to that effect. */
if (! ((name0 && name1)
- || (unidirectional_new_file && name1)
- || new_file))
+ || (opt->unidirectional_new_file && name1)
+ || opt->new_file))
{
- char const *name = name0 == 0 ? name1 : name0;
- char const *dir = parent->file[name0 == 0].name;
+ char const *name = name0 ? name0 : name1;
+ char const *dir = parent->file[!name0].name;
/* See POSIX 1003.1-2001 for this format. */
- message ("Only in %s: %s\n", dir, name);
+ message (opt, "Only in %s: %s\n", dir, name);
/* Return EXIT_FAILURE so that diff_dirs will return
EXIT_FAILURE ("some files differ"). */
@@ -1067,20 +1067,20 @@ compare_files (struct comparison const *parent,
#define ERRNO_DECODE(desc) (-3 - (desc)) /* inverse of ERRNO_ENCODE */
- cmp.file[0].desc = name0 == 0 ? NONEXISTENT : UNOPENED;
- cmp.file[1].desc = name1 == 0 ? NONEXISTENT : UNOPENED;
+ cmp.file[0].desc = name0 ? UNOPENED : NONEXISTENT;
+ cmp.file[1].desc = name1 ? UNOPENED : NONEXISTENT;
/* Now record the full name of each file, including nonexistent ones. */
- if (name0 == 0)
+ if (!name0)
name0 = name1;
- if (name1 == 0)
+ if (!name1)
name1 = name0;
if (!parent)
{
- free0 = 0;
- free1 = 0;
+ free0 = NULL;
+ free1 = NULL;
cmp.file[0].name = name0;
cmp.file[1].name = name1;
}
@@ -1112,7 +1112,7 @@ compare_files (struct comparison const *parent,
{
if (S_ISREG (cmp.file[f].stat.st_mode))
{
- off_t pos = lseek (STDIN_FILENO, (off_t) 0, SEEK_CUR);
+ off_t pos = lseek (STDIN_FILENO, 0, SEEK_CUR);
if (pos < 0)
cmp.file[f].desc = ERRNO_ENCODE (errno);
else
@@ -1136,7 +1136,7 @@ compare_files (struct comparison const *parent,
top-level files that do not exist but their counterparts do
exist. */
for (f = 0; f < 2; f++)
- if ((new_file || (f == 0 && unidirectional_new_file))
+ if ((opt->new_file || (f == 0 && opt->unidirectional_new_file))
&& (cmp.file[f].desc == UNOPENED
? (S_ISREG (cmp.file[f].stat.st_mode)
&& ! (cmp.file[f].stat.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO))
@@ -1177,7 +1177,7 @@ compare_files (struct comparison const *parent,
= dir_file_pathname (dir, base_name (fnm));
if (strcmp (fnm, "-") == 0)
- fatal ("cannot compare `-' to a directory");
+ fatal ("cannot compare `-' to a directory", opt);
if (stat (filename, &cmp.file[dir_arg].stat) != 0)
{
@@ -1201,28 +1201,28 @@ compare_files (struct comparison const *parent,
&& 0 < same_file (&cmp.file[0].stat, &cmp.file[1].stat)
&& same_file_attributes (&cmp.file[0].stat,
&cmp.file[1].stat)))
- && no_diff_means_no_output)
+ && opt->no_diff_means_no_output)
{
/* The two named files are actually the same physical file.
We know they are identical without actually reading them. */
}
else if (DIR_P (0) & DIR_P (1))
{
- if (output_style == OUTPUT_IFDEF)
- fatal ("-D option not supported with directories");
+ if (opt->output_style == OUTPUT_IFDEF)
+ fatal ("-D option not supported with directories", opt);
/* If both are directories, compare the files in them. */
- if (parent && !recursive)
+ if (parent && !opt->recursive)
{
/* But don't compare dir contents one level down
unless -r was specified.
See POSIX 1003.1-2001 for this format. */
- message ("Common subdirectories: %s and %s\n",
+ message (opt, "Common subdirectories: %s and %s\n",
cmp.file[0].name, cmp.file[1].name);
}
else
- status = diff_dirs (&cmp, compare_files);
+ status = diff_dirs (&cmp, compare_files, opt);
}
else if ((DIR_P (0) | DIR_P (1))
|| (parent
@@ -1234,18 +1234,18 @@ compare_files (struct comparison const *parent,
/* We have a subdirectory that exists only in one directory. */
if ((DIR_P (0) | DIR_P (1))
- && recursive
- && (new_file
- || (unidirectional_new_file
+ && opt->recursive
+ && (opt->new_file
+ || (opt->unidirectional_new_file
&& cmp.file[0].desc == NONEXISTENT)))
- status = diff_dirs (&cmp, compare_files);
+ status = diff_dirs (&cmp, compare_files, opt);
else
{
char const *dir
= parent->file[cmp.file[0].desc == NONEXISTENT].name;
/* See POSIX 1003.1-2001 for this format. */
- message ("Only in %s: %s\n", dir, name0);
+ message (opt, "Only in %s: %s\n", dir, name0);
status = EXIT_FAILURE;
}
@@ -1255,24 +1255,22 @@ compare_files (struct comparison const *parent,
/* We have two files that are not to be compared. */
/* See POSIX 1003.1-2001 for this format. */
- message5 ("File %s is a %s while file %s is a %s\n",
- file_label[0] ? file_label[0] : cmp.file[0].name,
- file_type (&cmp.file[0].stat),
- file_label[1] ? file_label[1] : cmp.file[1].name,
- file_type (&cmp.file[1].stat));
+ message5 (opt, "File %s is a %s while file %s is a %s\n",
+ file_label (0, opt), file_type (&cmp.file[0].stat),
+ file_label (1, opt), file_type (&cmp.file[1].stat));
/* This is a difference. */
status = EXIT_FAILURE;
}
}
- else if (files_can_be_treated_as_binary
+ else if (opt->files_can_be_treated_as_binary
&& S_ISREG (cmp.file[0].stat.st_mode)
&& S_ISREG (cmp.file[1].stat.st_mode)
&& cmp.file[0].stat.st_size != cmp.file[1].stat.st_size)
{
- message ("Files %s and %s differ\n",
- file_label[0] ? file_label[0] : cmp.file[0].name,
- file_label[1] ? file_label[1] : cmp.file[1].name);
+ message (opt, "Files %s and %s differ\n",
+ file_label (0, opt),
+ file_label (1, opt));
status = EXIT_FAILURE;
}
else
@@ -1309,7 +1307,7 @@ compare_files (struct comparison const *parent,
/* Compare the files, if no error was found. */
if (status == EXIT_SUCCESS)
- status = diff_2_files (&cmp);
+ status = diff_2_files (&cmp, opt);
/* Close the file descriptors. */
@@ -1331,17 +1329,17 @@ compare_files (struct comparison const *parent,
if (status == EXIT_SUCCESS)
{
- if (report_identical_files && !DIR_P (0))
- message ("Files %s and %s are identical\n",
- file_label[0] ? file_label[0] : cmp.file[0].name,
- file_label[1] ? file_label[1] : cmp.file[1].name);
+ if (opt->report_identical_files && !DIR_P (0))
+ message (opt, "Files %s and %s are identical\n",
+ file_label (0, opt),
+ file_label (1, opt));
}
else
{
/* Flush stdout so that the user sees differences immediately.
This can hurt performance, unfortunately. */
if (fflush (stdout) != 0)
- pfatal_with_name (_("standard output"));
+ pfatal_with_name (_("standard output"), opt);
}
if (free0)