diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-01 15:06:09 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-01 15:06:09 +0000 |
commit | 174ab8396535806d77708990568f9817d11d5bb3 (patch) | |
tree | 66bd7b055747e81d50846c4fb137b2abf93d4fe4 /src | |
parent | 203069b84a21bd917b6d971705fcf0480579e718 (diff) | |
download | diffutils-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.c | 544 |
1 files changed, 271 insertions, 273 deletions
@@ -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) |