diff options
author | delphij <delphij@FreeBSD.org> | 2007-06-15 07:22:26 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2007-06-15 07:22:26 +0000 |
commit | 2a4f71e2a081befac01737d16f2410928f43f65e (patch) | |
tree | 6b9e44b19cbe0e818b2f24efa24fa4ce3896342f /contrib | |
parent | 019bb6b05e782444408e9d3c2aa418b846d9e9ca (diff) | |
download | FreeBSD-src-2a4f71e2a081befac01737d16f2410928f43f65e.zip FreeBSD-src-2a4f71e2a081befac01737d16f2410928f43f65e.tar.gz |
Remove files that were taken off vendor branch. Difference
against vendor branch is now maintained in patchsets.
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/diff/diff.c | 1121 | ||||
-rw-r--r-- | contrib/diff/diff.h | 341 | ||||
-rw-r--r-- | contrib/diff/prepend_args.c | 87 | ||||
-rw-r--r-- | contrib/diff/prepend_args.h | 21 | ||||
-rw-r--r-- | contrib/diff/sdiff.c | 1109 | ||||
-rw-r--r-- | contrib/diff/util.c | 759 |
6 files changed, 0 insertions, 3438 deletions
diff --git a/contrib/diff/diff.c b/contrib/diff/diff.c deleted file mode 100644 index 1f5f842..0000000 --- a/contrib/diff/diff.c +++ /dev/null @@ -1,1121 +0,0 @@ -/* GNU DIFF main routine. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. - -This file is part of GNU DIFF. - -GNU DIFF is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU DIFF is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU DIFF; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* GNU DIFF was written by Mike Haertel, David Hayes, - Richard Stallman, Len Tower, and Paul Eggert. */ - -/* $FreeBSD$ */ - -#define GDIFF_MAIN -#include "diff.h" -#include <signal.h> -#include "getopt.h" -#ifdef __FreeBSD__ -#include <locale.h> -#include <fnmatch.h> -#else -#include "fnmatch.h" -#endif -#include "prepend_args.h" - -#ifndef DEFAULT_WIDTH -#define DEFAULT_WIDTH 130 -#endif - -#ifndef GUTTER_WIDTH_MINIMUM -#define GUTTER_WIDTH_MINIMUM 3 -#endif - -static char const *filetype PARAMS((struct stat const *)); -static char *option_list PARAMS((char **, int)); -static int add_exclude_file PARAMS((char const *)); -static int ck_atoi PARAMS((char const *, int *)); -static int compare_files PARAMS((char const *, char const *, char const *, char const *, int)); -static int specify_format PARAMS((char **, char *)); -static void add_exclude PARAMS((char const *)); -static void add_regexp PARAMS((struct regexp_list **, char const *)); -static void specify_style PARAMS((enum output_style)); -static void try_help PARAMS((char const *)); -static void check_stdout PARAMS((void)); -static void usage PARAMS((void)); - -/* Nonzero for -r: if comparing two directories, - compare their common subdirectories recursively. */ - -static int recursive; - -/* For debugging: don't do discard_confusing_lines. */ - -int no_discards; - -#if HAVE_SETMODE -/* I/O mode: nonzero only if using binary input/output. */ -static int binary_I_O; -#endif - -/* 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 (optionvec, count) - char **optionvec; /* Was `vector', but that collides on Alliant. */ - int count; -{ - int i; - size_t length = 0; - char *result; - - for (i = 0; i < count; i++) - length += strlen (optionvec[i]) + 1; - - result = xmalloc (length + 1); - result[0] = 0; - - for (i = 0; i < count; i++) - { - strcat (result, " "); - strcat (result, optionvec[i]); - } - - return result; -} - -/* Convert STR to a positive integer, storing the result in *OUT. - If STR is not a valid integer, return -1 (otherwise 0). */ -static int -ck_atoi (str, out) - char const *str; - int *out; -{ - char const *p; - for (p = str; *p; p++) - if (*p < '0' || *p > '9') - return -1; - - *out = atoi (optarg); - return 0; -} - -/* Keep track of excluded file name patterns. */ - -static char const **exclude; -static int exclude_alloc, exclude_count; - -int -excluded_filename (f) - char const *f; -{ - int i; - for (i = 0; i < exclude_count; i++) - if (fnmatch (exclude[i], f, 0) == 0) - return 1; - return 0; -} - -static void -add_exclude (pattern) - char const *pattern; -{ - if (exclude_alloc <= exclude_count) - exclude = (char const **) - (exclude_alloc == 0 - ? xmalloc ((exclude_alloc = 64) * sizeof (*exclude)) - : xrealloc (exclude, (exclude_alloc *= 2) * sizeof (*exclude))); - - exclude[exclude_count++] = pattern; -} - -static int -add_exclude_file (name) - char const *name; -{ - struct file_data f; - char *p, *q, *lim; - - f.name = optarg; - f.desc = (strcmp (optarg, "-") == 0 - ? STDIN_FILENO - : open (optarg, O_RDONLY, 0)); - if (f.desc < 0 || fstat (f.desc, &f.stat) != 0) - return -1; - - sip (&f, 1); - slurp (&f); - - for (p = f.buffer, lim = p + f.buffered_chars; p < lim; p = q) - { - q = (char *) memchr (p, '\n', lim - p); - if (!q) - q = lim; - *q++ = 0; - add_exclude (p); - } - - return close (f.desc); -} - -/* The numbers 129- that appear in the fourth element of some entries - tell the big switch in `main' how to process those options. */ - -static struct option const longopts[] = -{ - {"ignore-blank-lines", 0, 0, 'B'}, - {"context", 2, 0, 'C'}, - {"ifdef", 1, 0, 'D'}, - {"show-function-line", 1, 0, 'F'}, - {"speed-large-files", 0, 0, 'H'}, - {"ignore-matching-lines", 1, 0, 'I'}, - {"label", 1, 0, 'L'}, - {"file-label", 1, 0, 'L'}, /* An alias, no longer recommended */ - {"new-file", 0, 0, 'N'}, - {"entire-new-file", 0, 0, 'N'}, /* An alias, no longer recommended */ - {"unidirectional-new-file", 0, 0, 'P'}, - {"starting-file", 1, 0, 'S'}, - {"initial-tab", 0, 0, 'T'}, - {"width", 1, 0, 'W'}, - {"text", 0, 0, 'a'}, - {"ascii", 0, 0, 'a'}, /* An alias, no longer recommended */ - {"ignore-space-change", 0, 0, 'b'}, - {"minimal", 0, 0, 'd'}, - {"ed", 0, 0, 'e'}, - {"forward-ed", 0, 0, 'f'}, - {"ignore-case", 0, 0, 'i'}, - {"paginate", 0, 0, 'l'}, - {"print", 0, 0, 'l'}, /* An alias, no longer recommended */ - {"rcs", 0, 0, 'n'}, - {"show-c-function", 0, 0, 'p'}, - {"brief", 0, 0, 'q'}, - {"recursive", 0, 0, 'r'}, - {"report-identical-files", 0, 0, 's'}, - {"expand-tabs", 0, 0, 't'}, - {"version", 0, 0, 'v'}, - {"ignore-all-space", 0, 0, 'w'}, - {"exclude", 1, 0, 'x'}, - {"exclude-from", 1, 0, 'X'}, - {"side-by-side", 0, 0, 'y'}, - {"unified", 2, 0, 'U'}, - {"left-column", 0, 0, 129}, - {"suppress-common-lines", 0, 0, 130}, - {"sdiff-merge-assist", 0, 0, 131}, - {"old-line-format", 1, 0, 132}, - {"new-line-format", 1, 0, 133}, - {"unchanged-line-format", 1, 0, 134}, - {"line-format", 1, 0, 135}, - {"old-group-format", 1, 0, 136}, - {"new-group-format", 1, 0, 137}, - {"unchanged-group-format", 1, 0, 138}, - {"changed-group-format", 1, 0, 139}, - {"horizon-lines", 1, 0, 140}, - {"help", 0, 0, 141}, - {"binary", 0, 0, 142}, - {0, 0, 0, 0} -}; - -int -main (argc, argv) - int argc; - char *argv[]; -{ - int val; - int c; - int prev = -1; - int width = DEFAULT_WIDTH; - int show_c_function = 0; - -#ifdef __FreeBSD__ - setlocale(LC_ALL, ""); -#endif - /* Do our initializations. */ - initialize_main (&argc, &argv); - program_name = argv[0]; - output_style = OUTPUT_NORMAL; - context = -1; - - prepend_default_options (getenv ("DIFF_OPTIONS"), &argc, &argv); - - /* Decode the options. */ - - while ((c = getopt_long (argc, argv, - "0123456789abBcC:dD:efF:hHiI:lL:nNopPqrsS:tTuU:vwW:x:X:y", - longopts, 0)) != EOF) - { - switch (c) - { - /* All digits combine in decimal to specify the context-size. */ - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '0': - if (context == -1) - context = 0; - /* If a context length has already been specified, - more digits allowed only if they follow right after the others. - Reject two separate runs of digits, or digits after -C. */ - else if (prev < '0' || prev > '9') - fatal ("context length specified twice"); - - context = context * 10 + c - '0'; - break; - - case 'a': - /* Treat all files as text files; never treat as binary. */ - always_text_flag = 1; - break; - - case 'b': - /* Ignore changes in amount of white space. */ - ignore_space_change_flag = 1; - ignore_some_changes = 1; - ignore_some_line_changes = 1; - break; - - case 'B': - /* Ignore changes affecting only blank lines. */ - ignore_blank_lines_flag = 1; - ignore_some_changes = 1; - break; - - case 'C': /* +context[=lines] */ - case 'U': /* +unified[=lines] */ - if (optarg) - { - if (context >= 0) - fatal ("context length specified twice"); - - if (ck_atoi (optarg, &context)) - fatal ("invalid context length argument"); - } - - /* Falls through. */ - case 'c': - /* Make context-style output. */ - specify_style (c == 'U' ? OUTPUT_UNIFIED : OUTPUT_CONTEXT); - break; - - case 'd': - /* Don't discard lines. This makes things slower (sometimes much - slower) but will find a guaranteed minimal set of changes. */ - no_discards = 1; - break; - - case 'D': - /* Make merged #ifdef output. */ - specify_style (OUTPUT_IFDEF); - { - int i, err = 0; - static char const C_ifdef_group_formats[] = - "#ifndef %s\n%%<#endif /* not %s */\n%c#ifdef %s\n%%>#endif /* %s */\n%c%%=%c#ifndef %s\n%%<#else /* %s */\n%%>#endif /* %s */\n"; - char *b = xmalloc (sizeof (C_ifdef_group_formats) - + 7 * strlen(optarg) - 14 /* 7*"%s" */ - - 8 /* 5*"%%" + 3*"%c" */); - sprintf (b, C_ifdef_group_formats, - optarg, optarg, 0, - optarg, optarg, 0, 0, - optarg, optarg, optarg); - for (i = 0; i < 4; i++) - { - err |= specify_format (&group_format[i], b); - b += strlen (b) + 1; - } - if (err) - error ("conflicting #ifdef formats", 0, 0); - } - break; - - case 'e': - /* Make output that is a valid `ed' script. */ - specify_style (OUTPUT_ED); - break; - - case 'f': - /* Make output that looks vaguely like an `ed' script - but has changes in the order they appear in the file. */ - specify_style (OUTPUT_FORWARD_ED); - break; - - case 'F': - /* Show, for each set of changes, the previous line that - matches the specified regexp. Currently affects only - context-style output. */ - add_regexp (&function_regexp_list, optarg); - break; - - case 'h': - /* Split the files into chunks of around 1500 lines - for faster processing. Usually does not change the result. - - This currently has no effect. */ - break; - - case 'H': - /* Turn on heuristics that speed processing of large files - with a small density of changes. */ - heuristic = 1; - break; - - case 'i': - /* Ignore changes in case. */ - ignore_case_flag = 1; - ignore_some_changes = 1; - ignore_some_line_changes = 1; - break; - - case 'I': - /* Ignore changes affecting only lines that match the - specified regexp. */ - add_regexp (&ignore_regexp_list, optarg); - ignore_some_changes = 1; - break; - - case 'l': - /* Pass the output through `pr' to paginate it. */ - paginate_flag = 1; -#if !defined(SIGCHLD) && defined(SIGCLD) -#define SIGCHLD SIGCLD -#endif -#ifdef SIGCHLD - /* Pagination requires forking and waiting, and - System V fork+wait does not work if SIGCHLD is ignored. */ - signal (SIGCHLD, SIG_DFL); -#endif - break; - - case 'L': - /* Specify file labels for `-c' output headers. */ - if (!file_label[0]) - file_label[0] = optarg; - else if (!file_label[1]) - file_label[1] = optarg; - else - fatal ("too many file label options"); - break; - - case 'n': - /* Output RCS-style diffs, like `-f' except that each command - specifies the number of lines affected. */ - specify_style (OUTPUT_RCS); - break; - - case 'N': - /* When comparing directories, if a file appears only in one - directory, treat it as present but empty in the other. */ - entire_new_file_flag = 1; - break; - - case 'o': - /* Output in the old tradition style. */ - specify_style (OUTPUT_NORMAL); - break; - - case 'p': - /* Make context-style output and show name of last C function. */ - show_c_function = 1; - add_regexp (&function_regexp_list, "^[_a-zA-Z$]"); - break; - - case 'P': - /* 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_flag = 1; - break; - - case 'q': - no_details_flag = 1; - break; - - case 'r': - /* When comparing directories, - recursively compare any subdirectories found. */ - recursive = 1; - break; - - case 's': - /* Print a message if the files are the same. */ - print_file_same_flag = 1; - break; - - case 'S': - /* When comparing directories, start with the specified - file name. This is used for resuming an aborted comparison. */ - dir_start_file = optarg; - break; - - case 't': - /* Expand tabs to spaces in the output so that it preserves - the alignment of the input files. */ - tab_expand_flag = 1; - break; - - case 'T': - /* Use a tab in the output, rather than a space, before the - text of an input line, so as to keep the proper alignment - in the input line without changing the characters in it. */ - tab_align_flag = 1; - break; - - case 'u': - /* Output the context diff in unidiff format. */ - specify_style (OUTPUT_UNIFIED); - break; - - case 'v': - printf ("diff - GNU diffutils version %s\n", version_string); - exit (0); - - case 'w': - /* Ignore horizontal white space when comparing lines. */ - ignore_all_space_flag = 1; - ignore_some_changes = 1; - ignore_some_line_changes = 1; - break; - - case 'x': - add_exclude (optarg); - break; - - case 'X': - if (add_exclude_file (optarg) != 0) - pfatal_with_name (optarg); - break; - - case 'y': - /* Use side-by-side (sdiff-style) columnar output. */ - specify_style (OUTPUT_SDIFF); - break; - - case 'W': - /* Set the line width for OUTPUT_SDIFF. */ - if (ck_atoi (optarg, &width) || width <= 0) - fatal ("column width must be a positive integer"); - break; - - case 129: - sdiff_left_only = 1; - break; - - case 130: - sdiff_skip_common_lines = 1; - break; - - case 131: - /* sdiff-style columns output. */ - specify_style (OUTPUT_SDIFF); - sdiff_help_sdiff = 1; - break; - - case 132: - case 133: - case 134: - specify_style (OUTPUT_IFDEF); - if (specify_format (&line_format[c - 132], optarg) != 0) - error ("conflicting line format", 0, 0); - break; - - case 135: - specify_style (OUTPUT_IFDEF); - { - int i, err = 0; - for (i = 0; i < sizeof (line_format) / sizeof (*line_format); i++) - err |= specify_format (&line_format[i], optarg); - if (err) - error ("conflicting line format", 0, 0); - } - break; - - case 136: - case 137: - case 138: - case 139: - specify_style (OUTPUT_IFDEF); - if (specify_format (&group_format[c - 136], optarg) != 0) - error ("conflicting group format", 0, 0); - break; - - case 140: - if (ck_atoi (optarg, &horizon_lines) || horizon_lines < 0) - fatal ("horizon must be a nonnegative integer"); - break; - - case 141: - usage (); - check_stdout (); - exit (0); - - case 142: - /* Use binary I/O when reading and writing data. - On Posix hosts, this has no effect. */ -#if HAVE_SETMODE - binary_I_O = 1; - setmode (STDOUT_FILENO, O_BINARY); -#endif - break; - - default: - try_help (0); - } - prev = c; - } - - if (argc - optind != 2) - try_help (argc - optind < 2 ? "missing operand" : "extra operand"); - - - { - /* - * We maximize first the half line width, and then the gutter width, - * according to the following constraints: - * 1. Two half lines plus a gutter must fit in a line. - * 2. If the half line width is nonzero: - * a. The gutter width is at least GUTTER_WIDTH_MINIMUM. - * b. If tabs are not expanded to spaces, - * a half line plus a gutter is an integral number of tabs, - * so that tabs in the right column line up. - */ - int t = tab_expand_flag ? 1 : TAB_WIDTH; - int off = (width + t + GUTTER_WIDTH_MINIMUM) / (2*t) * t; - sdiff_half_width = max (0, min (off - GUTTER_WIDTH_MINIMUM, width - off)), - sdiff_column2_offset = sdiff_half_width ? off : width; - } - - if (show_c_function && output_style != OUTPUT_UNIFIED) - specify_style (OUTPUT_CONTEXT); - - if (output_style != OUTPUT_CONTEXT && output_style != OUTPUT_UNIFIED) - context = 0; - else if (context == -1) - /* Default amount of context for -c. */ - context = 3; - - if (output_style == OUTPUT_IFDEF) - { - /* Format arrays are char *, not char const *, - because integer formats are temporarily modified. - But it is safe to assign a constant like "%=" to a format array, - since "%=" does not format any integers. */ - int i; - 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[UNCHANGED] ? group_format[UNCHANGED] : "%<"; - if (!group_format[NEW]) - group_format[NEW] - = group_format[UNCHANGED] ? group_format[UNCHANGED] : "%>"; - if (!group_format[UNCHANGED]) - group_format[UNCHANGED] = "%="; - if (!group_format[CHANGED]) - group_format[CHANGED] = concat (group_format[OLD], - 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 ? sdiff_skip_common_lines : 1); - - switch_string = option_list (argv + 1, optind - 1); - - val = compare_files (0, argv[optind], 0, argv[optind + 1], 0); - - /* Print any messages that were saved up for last. */ - print_message_queue (); - - check_stdout (); - exit (val); - return val; -} - -/* Add the compiled form of regexp PATTERN to REGLIST. */ - -static void -add_regexp (reglist, pattern) - struct regexp_list **reglist; - char const *pattern; -{ - struct regexp_list *r; - char const *m; - - r = (struct regexp_list *) xmalloc (sizeof (*r)); - bzero (r, sizeof (*r)); - r->buf.fastmap = xmalloc (256); - m = re_compile_pattern (pattern, strlen (pattern), &r->buf); - if (m != 0) - error ("%s: %s", pattern, m); - - /* Add to the start of the list, since it's easier than the end. */ - r->next = *reglist; - *reglist = r; -} - -static void -try_help (reason) - char const *reason; -{ - if (reason) - error ("%s", reason, 0); - error ("Try `%s --help' for more information.", program_name, 0); - exit (2); -} - -static void -check_stdout () -{ - if (ferror (stdout) || fclose (stdout) != 0) - fatal ("write error"); -} - -static char const * const option_help[] = { -"-i --ignore-case Consider upper- and lower-case to be the same.", -"-w --ignore-all-space Ignore all white space.", -"-b --ignore-space-change Ignore changes in the amount of white space.", -"-B --ignore-blank-lines Ignore changes whose lines are all blank.", -"-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.", -#if HAVE_SETMODE -"--binary Read and write data in binary mode.", -#endif -"-a --text Treat all files as text.\n", -"-c -C NUM --context[=NUM] Output NUM (default 2) lines of copied context.", -"-u -U NUM --unified[=NUM] Output NUM (default 2) lines of unified context.", -" -NUM Use NUM context lines.", -" -L LABEL --label LABEL Use LABEL instead of file name.", -" -p --show-c-function Show which C function each change is in.", -" -F RE --show-function-line=RE Show the most recent line matching RE.", -"-q --brief Output only whether files differ.", -"-e --ed Output an ed script.", -"-n --rcs Output an RCS format diff.", -"-y --side-by-side Output in two columns.", -" -W NUM --width=NUM Output at most NUM (default 130) characters per line.", -" --left-column Output only the left column of common lines.", -" --suppress-common-lines Do not output common lines.", -"-DNAME --ifdef=NAME Output merged file to show `#ifdef NAME' diffs.", -"--GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT.", -"--line-format=LFMT Similar, but format all input lines with LFMT.", -"--LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT.", -" LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'.", -" GFMT may contain:", -" %< lines from FILE1", -" %> lines from FILE2", -" %= lines common to FILE1 and FILE2", -" %[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER", -" LETTERs are as follows for new group, lower case for old group:", -" F first line number", -" L last line number", -" N number of lines = L-F+1", -" E F-1", -" M L+1", -" LFMT may contain:", -" %L contents of line", -" %l contents of line, excluding any trailing newline", -" %[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number", -" Either GFMT or LFMT may contain:", -" %% %", -" %c'C' the single character C", -" %c'\\OOO' the character with octal code OOO\n", -"-l --paginate Pass the output through `pr' to paginate it.", -"-t --expand-tabs Expand tabs to spaces in output.", -"-T --initial-tab Make tabs line up by prepending a tab.\n", -"-r --recursive Recursively compare any subdirectories found.", -"-N --new-file Treat absent files as empty.", -"-P --unidirectional-new-file Treat absent first files as empty.", -"-s --report-identical-files Report when two files are the same.", -"-x PAT --exclude=PAT Exclude files that match PAT.", -"-X FILE --exclude-from=FILE Exclude files that match any pattern in FILE.", -"-S FILE --starting-file=FILE Start with FILE when comparing directories.\n", -"--horizon-lines=NUM Keep NUM lines of the common prefix and suffix.", -"-d --minimal Try hard to find a smaller set of changes.", -"-H --speed-large-files Assume large files and many scattered small changes.\n", -"-v --version Output version info.", -"--help Output this help.", -0 -}; - -static void -usage () -{ - char const * const *p; - - printf ("Usage: %s [OPTION]... FILE1 FILE2\n\n", program_name); - for (p = option_help; *p; p++) - printf (" %s\n", *p); - printf ("\nIf FILE1 or FILE2 is `-', read standard input.\n"); -} - -static int -specify_format (var, value) - char **var; - char *value; -{ - int err = *var ? strcmp (*var, value) : 0; - *var = value; - return err; -} - -static void -specify_style (style) - enum output_style style; -{ - output_style = style; -} - -static char const * -filetype (st) - struct stat const *st; -{ - /* See Posix.2 section 4.17.6.1.1 and Table 5-1 for these formats. - To keep diagnostics grammatical, the returned string must start - with a consonant. */ - - if (S_ISREG (st->st_mode)) - { - if (st->st_size == 0) - return "regular empty file"; - /* Posix.2 section 5.14.2 seems to suggest that we must read the file - and guess whether it's C, Fortran, etc., but this is somewhat useless - and doesn't reflect historical practice. We're allowed to guess - wrong, so we don't bother to read the file. */ - return "regular file"; - } - if (S_ISDIR (st->st_mode)) return "directory"; - - /* other Posix.1 file types */ -#ifdef S_ISBLK - if (S_ISBLK (st->st_mode)) return "block special file"; -#endif -#ifdef S_ISCHR - if (S_ISCHR (st->st_mode)) return "character special file"; -#endif -#ifdef S_ISFIFO - if (S_ISFIFO (st->st_mode)) return "fifo"; -#endif - - /* other Posix.1b file types */ -#ifdef S_TYPEISMQ - if (S_TYPEISMQ (st)) return "message queue"; -#endif -#ifdef S_TYPEISSEM - if (S_TYPEISSEM (st)) return "semaphore"; -#endif -#ifdef S_TYPEISSHM - if (S_TYPEISSHM (st)) return "shared memory object"; -#endif - - /* other popular file types */ - /* S_ISLNK is impossible with `fstat' and `stat'. */ -#ifdef S_ISSOCK - if (S_ISSOCK (st->st_mode)) return "socket"; -#endif - - return "weird file"; -} - -/* Compare two files (or dirs) with specified names - DIR0/NAME0 and DIR1/NAME1, at level DEPTH in directory recursion. - (if DIR0 is 0, then the name is just NAME0, etc.) - This is self-contained; it opens the files and closes them. - - Value is 0 if files are the same, 1 if different, - 2 if there is a problem opening them. */ - -static int -compare_files (dir0, name0, dir1, name1, depth) - char const *dir0, *dir1; - char const *name0, *name1; - int depth; -{ - struct file_data inf[2]; - register int i; - int val; - int same_files; - int failed = 0; - char *free0 = 0, *free1 = 0; - - /* 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 != 0 && name1 != 0) - || (unidirectional_new_file_flag && name1 != 0) - || entire_new_file_flag)) - { - char const *name = name0 == 0 ? name1 : name0; - char const *dir = name0 == 0 ? dir1 : dir0; - message ("Only in %s: %s\n", dir, name); - /* Return 1 so that diff_dirs will return 1 ("some files differ"). */ - return 1; - } - - bzero (inf, sizeof (inf)); - - /* Mark any nonexistent file with -1 in the desc field. */ - /* Mark unopened files (e.g. directories) with -2. */ - - inf[0].desc = name0 == 0 ? -1 : -2; - inf[1].desc = name1 == 0 ? -1 : -2; - - /* Now record the full name of each file, including nonexistent ones. */ - - if (name0 == 0) - name0 = name1; - if (name1 == 0) - name1 = name0; - - inf[0].name = dir0 == 0 ? name0 : (free0 = dir_file_pathname (dir0, name0)); - inf[1].name = dir1 == 0 ? name1 : (free1 = dir_file_pathname (dir1, name1)); - - /* Stat the files. Record whether they are directories. */ - - for (i = 0; i <= 1; i++) - { - if (inf[i].desc != -1) - { - int stat_result; - - if (i && filename_cmp (inf[i].name, inf[0].name) == 0) - { - inf[i].stat = inf[0].stat; - stat_result = 0; - } - else if (strcmp (inf[i].name, "-") == 0) - { - inf[i].desc = STDIN_FILENO; - stat_result = fstat (STDIN_FILENO, &inf[i].stat); - if (stat_result == 0 && S_ISREG (inf[i].stat.st_mode)) - { - off_t pos = lseek (STDIN_FILENO, (off_t) 0, SEEK_CUR); - if (pos == -1) - stat_result = -1; - else - { - if (pos <= inf[i].stat.st_size) - inf[i].stat.st_size -= pos; - else - inf[i].stat.st_size = 0; - /* Posix.2 4.17.6.1.4 requires current time for stdin. */ - time (&inf[i].stat.st_mtime); - } - } - } - else - stat_result = stat (inf[i].name, &inf[i].stat); - - if (stat_result != 0) - { - perror_with_name (inf[i].name); - failed = 1; - } - else - { - inf[i].dir_p = S_ISDIR (inf[i].stat.st_mode) && inf[i].desc != 0; - if (inf[1 - i].desc == -1) - { - inf[1 - i].dir_p = inf[i].dir_p; - inf[1 - i].stat.st_mode = inf[i].stat.st_mode; - } - } - } - } - - if (! failed && depth == 0 && inf[0].dir_p != inf[1].dir_p) - { - /* If one is a directory, and it was specified in the command line, - use the file in that dir with the other file's basename. */ - - int fnm_arg = inf[0].dir_p; - int dir_arg = 1 - fnm_arg; - char const *fnm = inf[fnm_arg].name; - char const *dir = inf[dir_arg].name; - char const *p = filename_lastdirchar (fnm); - char const *filename = inf[dir_arg].name - = dir_file_pathname (dir, p ? p + 1 : fnm); - - if (strcmp (fnm, "-") == 0) - fatal ("can't compare - to a directory"); - - if (stat (filename, &inf[dir_arg].stat) != 0) - { - perror_with_name (filename); - failed = 1; - } - else - inf[dir_arg].dir_p = S_ISDIR (inf[dir_arg].stat.st_mode); - } - - if (failed) - { - - /* If either file should exist but does not, return 2. */ - - val = 2; - - } - else if ((same_files = inf[0].desc != -1 && inf[1].desc != -1 - && 0 < same_file (&inf[0].stat, &inf[1].stat)) - && no_diff_means_no_output) - { - /* The two named files are actually the same physical file. - We know they are identical without actually reading them. */ - - val = 0; - } - else if (inf[0].dir_p & inf[1].dir_p) - { - if (output_style == OUTPUT_IFDEF) - fatal ("-D option not supported with directories"); - - /* If both are directories, compare the files in them. */ - - if (depth > 0 && !recursive) - { - /* But don't compare dir contents one level down - unless -r was specified. */ - message ("Common subdirectories: %s and %s\n", - inf[0].name, inf[1].name); - val = 0; - } - else - { - val = diff_dirs (inf, compare_files, depth); - } - - } - else if ((inf[0].dir_p | inf[1].dir_p) - || (depth > 0 - && (! S_ISREG (inf[0].stat.st_mode) - || ! S_ISREG (inf[1].stat.st_mode)))) - { - /* Perhaps we have a subdirectory that exists only in one directory. - If so, just print a message to that effect. */ - - if (inf[0].desc == -1 || inf[1].desc == -1) - { - if ((inf[0].dir_p | inf[1].dir_p) - && recursive - && (entire_new_file_flag - || (unidirectional_new_file_flag && inf[0].desc == -1))) - val = diff_dirs (inf, compare_files, depth); - else - { - char const *dir = (inf[0].desc == -1) ? dir1 : dir0; - /* See Posix.2 section 4.17.6.1.1 for this format. */ - message ("Only in %s: %s\n", dir, name0); - val = 1; - } - } - else - { - /* We have two files that are not to be compared. */ - - /* See Posix.2 section 4.17.6.1.1 for this format. */ - message5 ("File %s is a %s while file %s is a %s\n", - inf[0].name, filetype (&inf[0].stat), - inf[1].name, filetype (&inf[1].stat)); - - /* This is a difference. */ - val = 1; - } - } - else if ((no_details_flag & ~ignore_some_changes) - && inf[0].stat.st_size != inf[1].stat.st_size - && (inf[0].desc == -1 || S_ISREG (inf[0].stat.st_mode)) - && (inf[1].desc == -1 || S_ISREG (inf[1].stat.st_mode))) - { - message ("Files %s and %s differ\n", inf[0].name, inf[1].name); - val = 1; - } - else - { - /* Both exist and neither is a directory. */ - - /* Open the files and record their descriptors. */ - - if (inf[0].desc == -2) - if ((inf[0].desc = open (inf[0].name, O_RDONLY, 0)) < 0) - { - perror_with_name (inf[0].name); - failed = 1; - } - if (inf[1].desc == -2) - if (same_files) - inf[1].desc = inf[0].desc; - else if ((inf[1].desc = open (inf[1].name, O_RDONLY, 0)) < 0) - { - perror_with_name (inf[1].name); - failed = 1; - } - -#if HAVE_SETMODE - if (binary_I_O) - for (i = 0; i <= 1; i++) - if (0 <= inf[i].desc) - setmode (inf[i].desc, O_BINARY); -#endif - - /* Compare the files, if no error was found. */ - - val = failed ? 2 : diff_2_files (inf, depth); - - /* Close the file descriptors. */ - - if (inf[0].desc >= 0 && close (inf[0].desc) != 0) - { - perror_with_name (inf[0].name); - val = 2; - } - if (inf[1].desc >= 0 && inf[0].desc != inf[1].desc - && close (inf[1].desc) != 0) - { - perror_with_name (inf[1].name); - val = 2; - } - } - - /* Now the comparison has been done, if no error prevented it, - and VAL is the value this function will return. */ - - if (val == 0 && !inf[0].dir_p) - { - if (print_file_same_flag) - message ("Files %s and %s are identical\n", - inf[0].name, inf[1].name); - } - else - fflush (stdout); - - if (free0) - free (free0); - if (free1) - free (free1); - - return val; -} diff --git a/contrib/diff/diff.h b/contrib/diff/diff.h deleted file mode 100644 index 9a92e0d..0000000 --- a/contrib/diff/diff.h +++ /dev/null @@ -1,341 +0,0 @@ -/* Shared definitions for GNU DIFF - Copyright (C) 1988, 89, 91, 92, 93 Free Software Foundation, Inc. - -This file is part of GNU DIFF. - -GNU DIFF is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU DIFF is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU DIFF; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $FreeBSD$ */ - -#include "system.h" -#include <stdio.h> -#include "regex.h" - -#define TAB_WIDTH 8 - -/* Variables for command line options */ - -#ifndef GDIFF_MAIN -#define EXTERN extern -#else -#define EXTERN -#endif - -enum output_style { - /* Default output style. */ - OUTPUT_NORMAL, - /* Output the differences with lines of context before and after (-c). */ - OUTPUT_CONTEXT, - /* Output the differences in a unified context diff format (-u). */ - OUTPUT_UNIFIED, - /* Output the differences as commands suitable for `ed' (-e). */ - OUTPUT_ED, - /* Output the diff as a forward ed script (-f). */ - OUTPUT_FORWARD_ED, - /* Like -f, but output a count of changed lines in each "command" (-n). */ - OUTPUT_RCS, - /* Output merged #ifdef'd file (-D). */ - OUTPUT_IFDEF, - /* Output sdiff style (-y). */ - OUTPUT_SDIFF -}; - -/* True for output styles that are robust, - i.e. can handle a file that ends in a non-newline. */ -#define ROBUST_OUTPUT_STYLE(S) ((S) != OUTPUT_ED && (S) != OUTPUT_FORWARD_ED) - -EXTERN enum output_style output_style; - -/* Nonzero if output cannot be generated for identical files. */ -EXTERN int no_diff_means_no_output; - -/* Number of lines of context to show in each set of diffs. - This is zero when context is not to be shown. */ -EXTERN int context; - -/* Consider all files as text files (-a). - Don't interpret codes over 0177 as implying a "binary file". */ -EXTERN int always_text_flag; - -/* Number of lines to keep in identical prefix and suffix. */ -EXTERN int horizon_lines; - -/* Ignore changes in horizontal white space (-b). */ -EXTERN int ignore_space_change_flag; - -/* Ignore all horizontal white space (-w). */ -EXTERN int ignore_all_space_flag; - -/* Ignore changes that affect only blank lines (-B). */ -EXTERN int ignore_blank_lines_flag; - -/* 1 if lines may match even if their contents do not match exactly. - This depends on various options. */ -EXTERN int ignore_some_line_changes; - -/* 1 if files may match even if their contents are not byte-for-byte identical. - This depends on various options. */ -EXTERN int ignore_some_changes; - -/* Ignore differences in case of letters (-i). */ -EXTERN int ignore_case_flag; - -/* File labels for `-c' output headers (-L). */ -EXTERN char *file_label[2]; - -struct regexp_list -{ - struct re_pattern_buffer buf; - struct regexp_list *next; -}; - -/* Regexp to identify function-header lines (-F). */ -EXTERN struct regexp_list *function_regexp_list; - -/* Ignore changes that affect only lines matching this regexp (-I). */ -EXTERN struct regexp_list *ignore_regexp_list; - -/* Say only whether files differ, not how (-q). */ -EXTERN int no_details_flag; - -/* Report files compared that match (-s). - Normally nothing is output when that happens. */ -EXTERN int print_file_same_flag; - -/* Output the differences with exactly 8 columns added to each line - so that any tabs in the text line up properly (-T). */ -EXTERN int tab_align_flag; - -/* Expand tabs in the output so the text lines up properly - despite the characters added to the front of each line (-t). */ -EXTERN int tab_expand_flag; - -/* In directory comparison, specify file to start with (-S). - All file names less than this name are ignored. */ -EXTERN char *dir_start_file; - -/* If a file is new (appears in only one dir) - include its entire contents (-N). - Then `patch' would create the file with appropriate contents. */ -EXTERN int entire_new_file_flag; - -/* If a file is new (appears in only the second dir) - include its entire contents (-P). - Then `patch' would create the file with appropriate contents. */ -EXTERN int unidirectional_new_file_flag; - -/* Pipe each file's output through pr (-l). */ -EXTERN int paginate_flag; - -enum line_class { - /* Lines taken from just the first file. */ - OLD, - /* Lines taken from just the second file. */ - NEW, - /* Lines common to both files. */ - UNCHANGED, - /* A hunk containing both old and new lines (line groups only). */ - CHANGED -}; - -/* Line group formats for old, new, unchanged, and changed groups. */ -EXTERN char *group_format[CHANGED + 1]; - -/* Line formats for old, new, and unchanged lines. */ -EXTERN char *line_format[UNCHANGED + 1]; - -/* If using OUTPUT_SDIFF print extra information to help the sdiff filter. */ -EXTERN int sdiff_help_sdiff; - -/* Tell OUTPUT_SDIFF to show only the left version of common lines. */ -EXTERN int sdiff_left_only; - -/* Tell OUTPUT_SDIFF to not show common lines. */ -EXTERN int sdiff_skip_common_lines; - -/* The half line width and column 2 offset for OUTPUT_SDIFF. */ -EXTERN unsigned sdiff_half_width; -EXTERN unsigned sdiff_column2_offset; - -/* String containing all the command options diff received, - with spaces between and at the beginning but none at the end. - If there were no options given, this string is empty. */ -EXTERN char * switch_string; - -/* Nonzero means use heuristics for better speed. */ -EXTERN int heuristic; - -/* Name of program the user invoked (for error messages). */ -EXTERN char *program_name; - -/* The result of comparison is an "edit script": a chain of `struct change'. - Each `struct change' represents one place where some lines are deleted - and some are inserted. - - LINE0 and LINE1 are the first affected lines in the two files (origin 0). - DELETED is the number of lines deleted here from file 0. - INSERTED is the number of lines inserted here in file 1. - - If DELETED is 0 then LINE0 is the number of the line before - which the insertion was done; vice versa for INSERTED and LINE1. */ - -struct change -{ - struct change *link; /* Previous or next edit command */ - int inserted; /* # lines of file 1 changed here. */ - int deleted; /* # lines of file 0 changed here. */ - int line0; /* Line number of 1st deleted line. */ - int line1; /* Line number of 1st inserted line. */ - char ignore; /* Flag used in context.c */ -}; - -/* Structures that describe the input files. */ - -/* Data on one input file being compared. */ - -struct file_data { - int desc; /* File descriptor */ - char const *name; /* File name */ - struct stat stat; /* File status from fstat() */ - int dir_p; /* nonzero if file is a directory */ - - /* Buffer in which text of file is read. */ - char * buffer; - /* Allocated size of buffer. */ - size_t bufsize; - /* Number of valid characters now in the buffer. */ - size_t buffered_chars; - - /* Array of pointers to lines in the file. */ - char const **linbuf; - - /* linbuf_base <= buffered_lines <= valid_lines <= alloc_lines. - linebuf[linbuf_base ... buffered_lines - 1] are possibly differing. - linebuf[linbuf_base ... valid_lines - 1] contain valid data. - linebuf[linbuf_base ... alloc_lines - 1] are allocated. */ - int linbuf_base, buffered_lines, valid_lines, alloc_lines; - - /* Pointer to end of prefix of this file to ignore when hashing. */ - char const *prefix_end; - - /* Count of lines in the prefix. - There are this many lines in the file before linbuf[0]. */ - int prefix_lines; - - /* Pointer to start of suffix of this file to ignore when hashing. */ - char const *suffix_begin; - - /* Vector, indexed by line number, containing an equivalence code for - each line. It is this vector that is actually compared with that - of another file to generate differences. */ - int *equivs; - - /* Vector, like the previous one except that - the elements for discarded lines have been squeezed out. */ - int *undiscarded; - - /* Vector mapping virtual line numbers (not counting discarded lines) - to real ones (counting those lines). Both are origin-0. */ - int *realindexes; - - /* Total number of nondiscarded lines. */ - int nondiscarded_lines; - - /* Vector, indexed by real origin-0 line number, - containing 1 for a line that is an insertion or a deletion. - The results of comparison are stored here. */ - char *changed_flag; - - /* 1 if file ends in a line with no final newline. */ - int missing_newline; - - /* 1 more than the maximum equivalence value used for this or its - sibling file. */ - int equiv_max; -}; - -/* Describe the two files currently being compared. */ - -EXTERN struct file_data files[2]; - -/* Stdio stream to output diffs to. */ - -EXTERN FILE *outfile; - -/* Declare various functions. */ - -/* analyze.c */ -int diff_2_files PARAMS((struct file_data[], int)); - -/* context.c */ -void print_context_header PARAMS((struct file_data[], int)); -void print_context_script PARAMS((struct change *, int)); - -/* diff.c */ -int excluded_filename PARAMS((char const *)); - -/* dir.c */ -int diff_dirs PARAMS((struct file_data const[], int (*) PARAMS((char const *, char const *, char const *, char const *, int)), int)); - -/* ed.c */ -void print_ed_script PARAMS((struct change *)); -void pr_forward_ed_script PARAMS((struct change *)); - -/* ifdef.c */ -void print_ifdef_script PARAMS((struct change *)); - -/* io.c */ -int read_files PARAMS((struct file_data[], int)); -int sip PARAMS((struct file_data *, int)); -void slurp PARAMS((struct file_data *)); - -/* normal.c */ -void print_normal_script PARAMS((struct change *)); - -/* rcs.c */ -void print_rcs_script PARAMS((struct change *)); - -/* side.c */ -void print_sdiff_script PARAMS((struct change *)); - -/* util.c */ -VOID *xmalloc PARAMS((size_t)); -VOID *xrealloc PARAMS((VOID *, size_t)); -char *concat PARAMS((char const *, char const *, char const *)); -char *dir_file_pathname PARAMS((char const *, char const *)); -int change_letter PARAMS((int, int)); -int line_cmp PARAMS((char const *, char const *)); -int translate_line_number PARAMS((struct file_data const *, int)); -struct change *find_change PARAMS((struct change *)); -struct change *find_reverse_change PARAMS((struct change *)); -void analyze_hunk PARAMS((struct change *, int *, int *, int *, int *, int *, int *)); -void begin_output PARAMS((void)); -void debug_script PARAMS((struct change *)); -void error PARAMS((char const *, char const *, char const *)); -void fatal PARAMS((char const *)); -void finish_output PARAMS((void)); -void message PARAMS((char const *, char const *, char const *)); -void message5 PARAMS((char const *, char const *, char const *, char const *, char const *)); -void output_1_line PARAMS((char const *, char const *, char const *, char const *)); -void perror_with_name PARAMS((char const *)); -void pfatal_with_name PARAMS((char const *)); -void print_1_line PARAMS((char const *, char const * const *)); -void print_message_queue PARAMS((void)); -void print_number_range PARAMS((int, struct file_data *, int, int)); -void print_script PARAMS((struct change *, struct change * (*) PARAMS((struct change *)), void (*) PARAMS((struct change *)))); -void setup_output PARAMS((char const *, char const *, int)); -void translate_range PARAMS((struct file_data const *, int, int, int *, int *)); - -/* version.c */ -extern char const version_string[]; diff --git a/contrib/diff/prepend_args.c b/contrib/diff/prepend_args.c deleted file mode 100644 index 5dee55e..0000000 --- a/contrib/diff/prepend_args.c +++ /dev/null @@ -1,87 +0,0 @@ -/* prepend_args.c - utilility programs for manpiulating argv[] - Copyright (C) 1999 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -/* $FreeBSD$ */ - - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include "system.h" -#include "diff.h" -#include "prepend_args.h" - - -/* Find the white-space-separated options specified by OPTIONS, and - using BUF to store copies of these options, set ARGV[0], ARGV[1], - etc. to the option copies. Return the number N of options found. - Do not set ARGV[N] to NULL. If ARGV is NULL, do not store ARGV[0] - etc. Backslash can be used to escape whitespace (and backslashes). */ -static int -prepend_args (options, buf, argv) - char const *options; - char *buf; - char **argv; -{ - char const *o = options; - char *b = buf; - int n = 0; - - for (;;) - { - while (ISSPACE ((unsigned char) *o)) - o++; - if (!*o) - return n; - if (argv) - argv[n] = b; - n++; - - do - if ((*b++ = *o++) == '\\' && *o) - b[-1] = *o++; - while (*o && ! ISSPACE ((unsigned char) *o)); - - *b++ = '\0'; - } -} - -/* Prepend the whitespace-separated options in OPTIONS to the argument - vector of a main program with argument count *PARGC and argument - vector *PARGV. */ -void -prepend_default_options (options, pargc, pargv) - char const *options; - int *pargc; - char ***pargv; -{ - if (options) - { - char *buf = xmalloc (strlen (options) + 1); - int prepended = prepend_args (options, buf, (char **) NULL); - int argc = *pargc; - char * const *argv = *pargv; - char **pp = (char **) xmalloc ((prepended + argc + 1) * sizeof *pp); - *pargc = prepended + argc; - *pargv = pp; - *pp++ = *argv++; - pp += prepend_args (options, buf, pp); - while ((*pp++ = *argv++)) - continue; - } -} diff --git a/contrib/diff/prepend_args.h b/contrib/diff/prepend_args.h deleted file mode 100644 index 3f72cc2..0000000 --- a/contrib/diff/prepend_args.h +++ /dev/null @@ -1,21 +0,0 @@ -/* prepend_args.h - utilility programs for manpiulating argv[] - Copyright (C) 1999 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -/* $FreeBSD$ */ - -void prepend_default_options PARAMS ((char const *, int *, char ***)); diff --git a/contrib/diff/sdiff.c b/contrib/diff/sdiff.c deleted file mode 100644 index 5b5759e..0000000 --- a/contrib/diff/sdiff.c +++ /dev/null @@ -1,1109 +0,0 @@ -/* SDIFF -- interactive merge front end to diff - Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. - -This file is part of GNU DIFF. - -GNU DIFF is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU DIFF is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU DIFF; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* GNU SDIFF was written by Thomas Lord. */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include "system.h" -#include <stdio.h> -#include <signal.h> -#include "getopt.h" - -/* Size of chunks read from files which must be parsed into lines. */ -#define SDIFF_BUFSIZE ((size_t) 65536) - -/* Default name of the diff program */ -#ifndef DIFF_PROGRAM -#define DIFF_PROGRAM "/usr/bin/diff" -#endif - -/* Users' editor of nonchoice */ -#ifndef DEFAULT_EDITOR_PROGRAM -#define DEFAULT_EDITOR_PROGRAM "ed" -#endif - -extern char version_string[]; -static char const *program_name; -static char const *diffbin = DIFF_PROGRAM; -static char const *edbin = DEFAULT_EDITOR_PROGRAM; -static char const **diffargv; - -static char *tmpname; -static int volatile tmpmade; - -#if HAVE_FORK -static pid_t volatile diffpid; -#endif - -struct line_filter; - -static FILE *ck_fopen PARAMS((char const *, char const *)); -static RETSIGTYPE catchsig PARAMS((int)); -static VOID *xmalloc PARAMS((size_t)); -static char const *expand_name PARAMS((char *, int, char const *)); -static int edit PARAMS((struct line_filter *, int, struct line_filter *, int, FILE*)); -static int interact PARAMS((struct line_filter *, struct line_filter *, struct line_filter *, FILE*)); -static int lf_snarf PARAMS((struct line_filter *, char *, size_t)); -static int skip_white PARAMS((void)); -static size_t ck_fread PARAMS((char *, size_t, FILE *)); -static size_t lf_refill PARAMS((struct line_filter *)); -static void checksigs PARAMS((void)); -static void ck_fclose PARAMS((FILE *)); -static void ck_fflush PARAMS((FILE *)); -static void ck_fwrite PARAMS((char const *, size_t, FILE *)); -static void cleanup PARAMS((void)); -static void diffarg PARAMS((char const *)); -static void execdiff PARAMS((void)); -static void exiterr PARAMS((void)); -static void fatal PARAMS((char const *)); -static void flush_line PARAMS((void)); -static void give_help PARAMS((void)); -static void lf_copy PARAMS((struct line_filter *, int, FILE *)); -static void lf_init PARAMS((struct line_filter *, FILE *)); -static void lf_skip PARAMS((struct line_filter *, int)); -static void perror_fatal PARAMS((char const *)); -static void trapsigs PARAMS((void)); -static void try_help PARAMS((char const *)); -static void untrapsig PARAMS((int)); -static void usage PARAMS((void)); - -static int diraccess PARAMS((char const *)); - -/* Options: */ - -/* name of output file if -o spec'd */ -static char *out_file; - -/* do not print common lines if true, set by -s option */ -static int suppress_common_flag; - -static struct option const longopts[] = -{ - {"ignore-blank-lines", 0, 0, 'B'}, - {"speed-large-files", 0, 0, 'H'}, - {"ignore-matching-lines", 1, 0, 'I'}, - {"ignore-all-space", 0, 0, 'W'}, /* swap W and w for historical reasons */ - {"text", 0, 0, 'a'}, - {"ignore-space-change", 0, 0, 'b'}, - {"minimal", 0, 0, 'd'}, - {"ignore-case", 0, 0, 'i'}, - {"left-column", 0, 0, 'l'}, - {"output", 1, 0, 'o'}, - {"suppress-common-lines", 0, 0, 's'}, - {"expand-tabs", 0, 0, 't'}, - {"width", 1, 0, 'w'}, - {"version", 0, 0, 'v'}, - {"help", 0, 0, 129}, - {0, 0, 0, 0} -}; - -static void -try_help (reason) - char const *reason; -{ - if (reason) - fprintf (stderr, "%s: %s\n", program_name, reason); - fprintf (stderr, "%s: Try `%s --help' for more information.\n", - program_name, program_name); - exit (2); -} - -static void -usage () -{ - printf ("Usage: %s [OPTIONS]... FILE1 FILE2\n\n", program_name); - printf ("%s", "\ - -o FILE --output=FILE Operate interactively, sending output to FILE.\n\n"); - printf ("%s", "\ - -i --ignore-case Consider upper- and lower-case to be the same.\n\ - -W --ignore-all-space Ignore all white space.\n\ - -b --ignore-space-change Ignore changes in the amount of white space.\n\ - -B --ignore-blank-lines Ignore changes whose lines are all blank.\n\ - -I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.\n\ - -a --text Treat all files as text.\n\n"); - printf ("%s", "\ - -w NUM --width=NUM Output at most NUM (default 130) characters per line.\n\ - -l --left-column Output only the left column of common lines.\n\ - -s --suppress-common-lines Do not output common lines.\n\n"); - printf ("\ - -t --expand-tabs Expand tabs to spaces in output.\n\n"); - printf ("%s", "\ - -d --minimal Try hard to find a smaller set of changes.\n\ - -H --speed-large-files Assume large files and many scattered small changes.\n\n"); - printf ("%s", "\ - -v --version Output version info.\n\ - --help Output this help.\n\n\ -If FILE1 or FILE2 is `-', read standard input.\n"); -} - -static void -cleanup () -{ -#if HAVE_FORK - if (0 < diffpid) - kill (diffpid, SIGPIPE); -#endif - if (tmpmade) - unlink (tmpname); -} - -static void -exiterr () -{ - cleanup (); - untrapsig (0); - checksigs (); - exit (2); -} - -static void -fatal (msg) - char const *msg; -{ - fprintf (stderr, "%s: %s\n", program_name, msg); - exiterr (); -} - -static void -perror_fatal (msg) - char const *msg; -{ - int e = errno; - checksigs (); - fprintf (stderr, "%s: ", program_name); - errno = e; - perror (msg); - exiterr (); -} - - -/* malloc freely or DIE! */ -static VOID * -xmalloc (size) - size_t size; -{ - VOID *r = (VOID *) malloc (size); - if (!r) - fatal ("memory exhausted"); - return r; -} - -static FILE * -ck_fopen (fname, type) - char const *fname, *type; -{ - FILE *r = fopen (fname, type); - if (!r) - perror_fatal (fname); - return r; -} - -static void -ck_fclose (f) - FILE *f; -{ - if (fclose (f)) - perror_fatal ("input/output error"); -} - -static size_t -ck_fread (buf, size, f) - char *buf; - size_t size; - FILE *f; -{ - size_t r = fread (buf, sizeof (char), size, f); - if (r == 0 && ferror (f)) - perror_fatal ("input error"); - return r; -} - -static void -ck_fwrite (buf, size, f) - char const *buf; - size_t size; - FILE *f; -{ - if (fwrite (buf, sizeof (char), size, f) != size) - perror_fatal ("output error"); -} - -static void -ck_fflush (f) - FILE *f; -{ - if (fflush (f) != 0) - perror_fatal ("output error"); -} - -static char const * -expand_name (name, is_dir, other_name) - char *name; - int is_dir; - char const *other_name; -{ - if (strcmp (name, "-") == 0) - fatal ("cannot interactively merge standard input"); - if (!is_dir) - return name; - else - { - /* Yield NAME/BASE, where BASE is OTHER_NAME's basename. */ - char const *p = filename_lastdirchar (other_name); - char const *base = p ? p+1 : other_name; - size_t namelen = strlen (name), baselen = strlen (base); - char *r = xmalloc (namelen + baselen + 2); - memcpy (r, name, namelen); - r[namelen] = '/'; - memcpy (r + namelen + 1, base, baselen + 1); - return r; - } -} - - - -struct line_filter { - FILE *infile; - char *bufpos; - char *buffer; - char *buflim; -}; - -static void -lf_init (lf, infile) - struct line_filter *lf; - FILE *infile; -{ - lf->infile = infile; - lf->bufpos = lf->buffer = lf->buflim = xmalloc (SDIFF_BUFSIZE + 1); - lf->buflim[0] = '\n'; -} - -/* Fill an exhausted line_filter buffer from its INFILE */ -static size_t -lf_refill (lf) - struct line_filter *lf; -{ - size_t s = ck_fread (lf->buffer, SDIFF_BUFSIZE, lf->infile); - lf->bufpos = lf->buffer; - lf->buflim = lf->buffer + s; - lf->buflim[0] = '\n'; - checksigs (); - return s; -} - -/* Advance LINES on LF's infile, copying lines to OUTFILE */ -static void -lf_copy (lf, lines, outfile) - struct line_filter *lf; - int lines; - FILE *outfile; -{ - char *start = lf->bufpos; - - while (lines) - { - lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos); - if (! lf->bufpos) - { - ck_fwrite (start, lf->buflim - start, outfile); - if (! lf_refill (lf)) - return; - start = lf->bufpos; - } - else - { - --lines; - ++lf->bufpos; - } - } - - ck_fwrite (start, lf->bufpos - start, outfile); -} - -/* Advance LINES on LF's infile without doing output */ -static void -lf_skip (lf, lines) - struct line_filter *lf; - int lines; -{ - while (lines) - { - lf->bufpos = (char *) memchr (lf->bufpos, '\n', lf->buflim - lf->bufpos); - if (! lf->bufpos) - { - if (! lf_refill (lf)) - break; - } - else - { - --lines; - ++lf->bufpos; - } - } -} - -/* Snarf a line into a buffer. Return EOF if EOF, 0 if error, 1 if OK. */ -static int -lf_snarf (lf, buffer, bufsize) - struct line_filter *lf; - char *buffer; - size_t bufsize; -{ - char *start = lf->bufpos; - - for (;;) - { - char *next = (char *) memchr (start, '\n', lf->buflim + 1 - start); - size_t s = next - start; - if (bufsize <= s) - return 0; - memcpy (buffer, start, s); - if (next < lf->buflim) - { - buffer[s] = 0; - lf->bufpos = next + 1; - return 1; - } - if (! lf_refill (lf)) - return s ? 0 : EOF; - buffer += s; - bufsize -= s; - start = next; - } -} - - - -int -main (argc, argv) - int argc; - char *argv[]; -{ - int opt; - char *editor; - char *differ; - - initialize_main (&argc, &argv); - program_name = argv[0]; - - editor = getenv ("EDITOR"); - if (editor) - edbin = editor; - differ = getenv ("DIFF"); - if (differ) - diffbin = differ; - - diffarg ("diff"); - - /* parse command line args */ - while ((opt = getopt_long (argc, argv, "abBdHiI:lo:stvw:W", longopts, 0)) - != EOF) - { - switch (opt) - { - case 'a': - diffarg ("-a"); - break; - - case 'b': - diffarg ("-b"); - break; - - case 'B': - diffarg ("-B"); - break; - - case 'd': - diffarg ("-d"); - break; - - case 'H': - diffarg ("-H"); - break; - - case 'i': - diffarg ("-i"); - break; - - case 'I': - diffarg ("-I"); - diffarg (optarg); - break; - - case 'l': - diffarg ("--left-column"); - break; - - case 'o': - out_file = optarg; - break; - - case 's': - suppress_common_flag = 1; - break; - - case 't': - diffarg ("-t"); - break; - - case 'v': - printf ("sdiff - GNU diffutils version %s\n", version_string); - exit (0); - - case 'w': - diffarg ("-W"); - diffarg (optarg); - break; - - case 'W': - diffarg ("-w"); - break; - - case 129: - usage (); - if (ferror (stdout) || fclose (stdout) != 0) - fatal ("write error"); - exit (0); - - default: - try_help (0); - } - } - - if (argc - optind != 2) - try_help (argc - optind < 2 ? "missing operand" : "extra operand"); - - if (! out_file) - { - /* easy case: diff does everything for us */ - if (suppress_common_flag) - diffarg ("--suppress-common-lines"); - diffarg ("-y"); - diffarg ("--"); - diffarg (argv[optind]); - diffarg (argv[optind + 1]); - diffarg (0); - execdiff (); - } - else - { - FILE *left, *right, *out, *diffout; - int interact_ok; - struct line_filter lfilt; - struct line_filter rfilt; - struct line_filter diff_filt; - int leftdir = diraccess (argv[optind]); - int rightdir = diraccess (argv[optind + 1]); - - if (leftdir && rightdir) - fatal ("both files to be compared are directories"); - - left = ck_fopen (expand_name (argv[optind], leftdir, argv[optind + 1]), "r"); - ; - right = ck_fopen (expand_name (argv[optind + 1], rightdir, argv[optind]), "r"); - out = ck_fopen (out_file, "w"); - - diffarg ("--sdiff-merge-assist"); - diffarg ("--"); - diffarg (argv[optind]); - diffarg (argv[optind + 1]); - diffarg (0); - - trapsigs (); - -#if ! HAVE_FORK - { - size_t cmdsize = 1; - char *p, *command; - int i; - - for (i = 0; diffargv[i]; i++) - cmdsize += 4 * strlen (diffargv[i]) + 3; - command = p = xmalloc (cmdsize); - for (i = 0; diffargv[i]; i++) - { - char const *a = diffargv[i]; - SYSTEM_QUOTE_ARG (p, a); - *p++ = ' '; - } - p[-1] = '\0'; - diffout = popen (command, "r"); - if (!diffout) - perror_fatal (command); - free (command); - } -#else /* HAVE_FORK */ - { - int diff_fds[2]; - - if (pipe (diff_fds) != 0) - perror_fatal ("pipe"); - - diffpid = vfork (); - if (diffpid < 0) - perror_fatal ("fork failed"); - if (!diffpid) - { - signal (SIGINT, SIG_IGN); /* in case user interrupts editor */ - signal (SIGPIPE, SIG_DFL); - - close (diff_fds[0]); - if (diff_fds[1] != STDOUT_FILENO) - { - dup2 (diff_fds[1], STDOUT_FILENO); - close (diff_fds[1]); - } - - execdiff (); - } - - close (diff_fds[1]); - diffout = fdopen (diff_fds[0], "r"); - if (!diffout) - perror_fatal ("fdopen"); - } -#endif /* HAVE_FORK */ - - lf_init (&diff_filt, diffout); - lf_init (&lfilt, left); - lf_init (&rfilt, right); - - interact_ok = interact (&diff_filt, &lfilt, &rfilt, out); - - ck_fclose (left); - ck_fclose (right); - ck_fclose (out); - - { - int wstatus; - -#if ! HAVE_FORK - wstatus = pclose (diffout); -#else - ck_fclose (diffout); - while (waitpid (diffpid, &wstatus, 0) < 0) - if (errno == EINTR) - checksigs (); - else - perror_fatal ("wait failed"); - diffpid = 0; -#endif - - if (tmpmade) - { - unlink (tmpname); - tmpmade = 0; - } - - if (! interact_ok) - exiterr (); - - if (! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 2)) - fatal ("Subsidiary diff failed"); - - untrapsig (0); - checksigs (); - exit (WEXITSTATUS (wstatus)); - } - } - return 0; /* Fool -Wall . . . */ -} - -static void -diffarg (a) - char const *a; -{ - static unsigned diffargs, diffargsmax; - - if (diffargs == diffargsmax) - { - if (! diffargsmax) - { - diffargv = (char const **) xmalloc (sizeof (char)); - diffargsmax = 8; - } - diffargsmax *= 2; - diffargv = (char const **) realloc (diffargv, - diffargsmax * sizeof (char const *)); - if (! diffargv) - fatal ("out of memory"); - } - diffargv[diffargs++] = a; -} - -static void -execdiff () -{ - execvp (diffbin, (char **) diffargv); - write (STDERR_FILENO, diffbin, strlen (diffbin)); - write (STDERR_FILENO, ": not found\n", 12); - _exit (2); -} - - - - -/* Signal handling */ - -#define NUM_SIGS (sizeof (sigs) / sizeof (*sigs)) -static int const sigs[] = { -#ifdef SIGHUP - SIGHUP, -#endif -#ifdef SIGQUIT - SIGQUIT, -#endif -#ifdef SIGTERM - SIGTERM, -#endif -#ifdef SIGXCPU - SIGXCPU, -#endif -#ifdef SIGXFSZ - SIGXFSZ, -#endif - SIGINT, - SIGPIPE -}; - -/* Prefer `sigaction' if it is available, since `signal' can lose signals. */ -#if HAVE_SIGACTION -static struct sigaction initial_action[NUM_SIGS]; -#define initial_handler(i) (initial_action[i].sa_handler) -#else -static RETSIGTYPE (*initial_action[NUM_SIGS]) (); -#define initial_handler(i) (initial_action[i]) -#endif - -static int volatile ignore_SIGINT; -static int volatile signal_received; -static int sigs_trapped; - -static RETSIGTYPE -catchsig (s) - int s; -{ -#if ! HAVE_SIGACTION - signal (s, SIG_IGN); -#endif - if (! (s == SIGINT && ignore_SIGINT)) - signal_received = s; -} - -static void -trapsigs () -{ - int i; - -#if HAVE_SIGACTION - struct sigaction catchaction; - bzero (&catchaction, sizeof (catchaction)); - catchaction.sa_handler = catchsig; -#ifdef SA_INTERRUPT - /* Non-Posix BSD-style systems like SunOS 4.1.x need this - so that `read' calls are interrupted properly. */ - catchaction.sa_flags = SA_INTERRUPT; -#endif - sigemptyset (&catchaction.sa_mask); - for (i = 0; i < NUM_SIGS; i++) - sigaddset (&catchaction.sa_mask, sigs[i]); - for (i = 0; i < NUM_SIGS; i++) - { - sigaction (sigs[i], 0, &initial_action[i]); - if (initial_handler (i) != SIG_IGN - && sigaction (sigs[i], &catchaction, 0) != 0) - fatal ("signal error"); - } -#else /* ! HAVE_SIGACTION */ - for (i = 0; i < NUM_SIGS; i++) - { - initial_action[i] = signal (sigs[i], SIG_IGN); - if (initial_handler (i) != SIG_IGN - && signal (sigs[i], catchsig) != SIG_IGN) - fatal ("signal error"); - } -#endif /* ! HAVE_SIGACTION */ - -#if !defined(SIGCHLD) && defined(SIGCLD) -#define SIGCHLD SIGCLD -#endif -#ifdef SIGCHLD - /* System V fork+wait does not work if SIGCHLD is ignored. */ - signal (SIGCHLD, SIG_DFL); -#endif - - sigs_trapped = 1; -} - -/* Untrap signal S, or all trapped signals if S is zero. */ -static void -untrapsig (s) - int s; -{ - int i; - - if (sigs_trapped) - for (i = 0; i < NUM_SIGS; i++) - if ((!s || sigs[i] == s) && initial_handler (i) != SIG_IGN) -#if HAVE_SIGACTION - sigaction (sigs[i], &initial_action[i], 0); -#else - signal (sigs[i], initial_action[i]); -#endif -} - -/* Exit if a signal has been received. */ -static void -checksigs () -{ - int s = signal_received; - if (s) - { - cleanup (); - - /* Yield an exit status indicating that a signal was received. */ - untrapsig (s); - kill (getpid (), s); - - /* That didn't work, so exit with error status. */ - exit (2); - } -} - - - -static void -give_help () -{ - fprintf (stderr,"l:\tuse the left version\n"); - fprintf (stderr,"r:\tuse the right version\n"); - fprintf (stderr,"e l:\tedit then use the left version\n"); - fprintf (stderr,"e r:\tedit then use the right version\n"); - fprintf (stderr,"e b:\tedit then use the left and right versions concatenated\n"); - fprintf (stderr,"e:\tedit a new version\n"); - fprintf (stderr,"s:\tsilently include common lines\n"); - fprintf (stderr,"v:\tverbosely include common lines\n"); - fprintf (stderr,"q:\tquit\n"); -} - -static int -skip_white () -{ - int c; - for (;;) - { - c = getchar (); - if (!ISSPACE (c) || c == '\n') - break; - checksigs (); - } - if (ferror (stdin)) - perror_fatal ("input error"); - return c; -} - -static void -flush_line () -{ - int c; - while ((c = getchar ()) != '\n' && c != EOF) - ; - if (ferror (stdin)) - perror_fatal ("input error"); -} - - -/* interpret an edit command */ -static int -edit (left, lenl, right, lenr, outfile) - struct line_filter *left; - int lenl; - struct line_filter *right; - int lenr; - FILE *outfile; -{ - for (;;) - { - int cmd0, cmd1; - int gotcmd = 0; - - cmd1 = 0; /* Pacify `gcc -W'. */ - - while (!gotcmd) - { - if (putchar ('%') != '%') - perror_fatal ("output error"); - ck_fflush (stdout); - - cmd0 = skip_white (); - switch (cmd0) - { - case 'l': case 'r': case 's': case 'v': case 'q': - if (skip_white () != '\n') - { - give_help (); - flush_line (); - continue; - } - gotcmd = 1; - break; - - case 'e': - cmd1 = skip_white (); - switch (cmd1) - { - case 'l': case 'r': case 'b': - if (skip_white () != '\n') - { - give_help (); - flush_line (); - continue; - } - gotcmd = 1; - break; - case '\n': - gotcmd = 1; - break; - default: - give_help (); - flush_line (); - continue; - } - break; - case EOF: - if (feof (stdin)) - { - gotcmd = 1; - cmd0 = 'q'; - break; - } - /* falls through */ - default: - flush_line (); - /* falls through */ - case '\n': - give_help (); - continue; - } - } - - switch (cmd0) - { - case 'l': - lf_copy (left, lenl, outfile); - lf_skip (right, lenr); - return 1; - case 'r': - lf_copy (right, lenr, outfile); - lf_skip (left, lenl); - return 1; - case 's': - suppress_common_flag = 1; - break; - case 'v': - suppress_common_flag = 0; - break; - case 'q': - return 0; - case 'e': - { - int tfd; - FILE *tmp; - - if (tmpmade) - { - unlink (tmpname); - tmpmade = 0; - free (tmpname); - } - - asprintf (&tmpname, "%s/sdiff.XXXXXX", - getenv("TMPDIR") ?: P_tmpdir); - if (tmpname == NULL) - perror_fatal ("temporary file name"); - tfd = mkstemp(tmpname); - if (tfd == -1) - perror_fatal ("temporary file name"); - tmp = fdopen (tfd, "w+"); - if (tmp == NULL) - perror_fatal ("temporary file name"); - - tmpmade = 1; - - if (cmd1 == 'l' || cmd1 == 'b') - lf_copy (left, lenl, tmp); - else - lf_skip (left, lenl); - - if (cmd1 == 'r' || cmd1 == 'b') - lf_copy (right, lenr, tmp); - else - lf_skip (right, lenr); - - ck_fflush (tmp); - - { - int wstatus; -#if ! HAVE_FORK - char *command = xmalloc (strlen (edbin) + strlen (tmpname) + 2); - sprintf (command, "%s %s", edbin, tmpname); - wstatus = system (command); - free (command); -#else /* HAVE_FORK */ - pid_t pid; - - ignore_SIGINT = 1; - checksigs (); - - pid = vfork (); - if (pid == 0) - { - char const *argv[3]; - int i = 0; - - argv[i++] = edbin; - argv[i++] = tmpname; - argv[i++] = 0; - - execvp (edbin, (char **) argv); - write (STDERR_FILENO, edbin, strlen (edbin)); - write (STDERR_FILENO, ": not found\n", 12); - _exit (1); - } - - if (pid < 0) - perror_fatal ("fork failed"); - - while (waitpid (pid, &wstatus, 0) < 0) - if (errno == EINTR) - checksigs (); - else - perror_fatal ("wait failed"); - - ignore_SIGINT = 0; -#endif /* HAVE_FORK */ - - if (wstatus != 0) - fatal ("Subsidiary editor failed"); - } - - if (fseek (tmp, 0L, SEEK_SET) != 0) - perror_fatal ("fseek"); - { - /* SDIFF_BUFSIZE is too big for a local var - in some compilers, so we allocate it dynamically. */ - char *buf = xmalloc (SDIFF_BUFSIZE); - size_t size; - - while ((size = ck_fread (buf, SDIFF_BUFSIZE, tmp)) != 0) - { - checksigs (); - ck_fwrite (buf, size, outfile); - } - ck_fclose (tmp); - - free (buf); - } - return 1; - } - default: - give_help (); - break; - } - } -} - - - -/* Alternately reveal bursts of diff output and handle user commands. */ -static int -interact (diff, left, right, outfile) - struct line_filter *diff; - struct line_filter *left; - struct line_filter *right; - FILE *outfile; -{ - for (;;) - { - char diff_help[256]; - int snarfed = lf_snarf (diff, diff_help, sizeof (diff_help)); - - if (snarfed <= 0) - return snarfed; - - checksigs (); - - switch (diff_help[0]) - { - case ' ': - puts (diff_help + 1); - break; - case 'i': - { - int lenl = atoi (diff_help + 1), lenr, lenmax; - char *p = strchr (diff_help, ','); - - if (!p) - fatal (diff_help); - lenr = atoi (p + 1); - lenmax = max (lenl, lenr); - - if (suppress_common_flag) - lf_skip (diff, lenmax); - else - lf_copy (diff, lenmax, stdout); - - lf_copy (left, lenl, outfile); - lf_skip (right, lenr); - break; - } - case 'c': - { - int lenl = atoi (diff_help + 1), lenr; - char *p = strchr (diff_help, ','); - - if (!p) - fatal (diff_help); - lenr = atoi (p + 1); - lf_copy (diff, max (lenl, lenr), stdout); - if (! edit (left, lenl, right, lenr, outfile)) - return 0; - break; - } - default: - fatal (diff_help); - break; - } - } -} - - - -/* temporary lossage: this is torn from gnu libc */ -/* Return nonzero if DIR is an existing directory. */ -static int -diraccess (dir) - char const *dir; -{ - struct stat buf; - return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode); -} diff --git a/contrib/diff/util.c b/contrib/diff/util.c deleted file mode 100644 index 35b28ea..0000000 --- a/contrib/diff/util.c +++ /dev/null @@ -1,759 +0,0 @@ -/* Support routines for GNU DIFF. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. - -This file is part of GNU DIFF. - -GNU DIFF is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU DIFF is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU DIFF; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* $FreeBSD$ */ - -#include "diff.h" - -#ifndef PR_PROGRAM -#define PR_PROGRAM "/bin/pr" -#endif - -/* Queue up one-line messages to be printed at the end, - when -l is specified. Each message is recorded with a `struct msg'. */ - -struct msg -{ - struct msg *next; - char const *format; - char const *arg1; - char const *arg2; - char const *arg3; - char const *arg4; -}; - -/* Head of the chain of queues messages. */ - -static struct msg *msg_chain; - -/* Tail of the chain of queues messages. */ - -static struct msg **msg_chain_end = &msg_chain; - -/* Use when a system call returns non-zero status. - TEXT should normally be the file name. */ - -void -perror_with_name (text) - char const *text; -{ - int e = errno; - fprintf (stderr, "%s: ", program_name); - errno = e; - perror (text); -} - -/* Use when a system call returns non-zero status and that is fatal. */ - -void -pfatal_with_name (text) - char const *text; -{ - int e = errno; - print_message_queue (); - fprintf (stderr, "%s: ", program_name); - errno = e; - perror (text); - exit (2); -} - -/* Print an error message from the format-string FORMAT - with args ARG1 and ARG2. */ - -void -error (format, arg, arg1) - char const *format, *arg, *arg1; -{ - fprintf (stderr, "%s: ", program_name); - fprintf (stderr, format, arg, arg1); - fprintf (stderr, "\n"); -} - -/* Print an error message containing the string TEXT, then exit. */ - -void -fatal (m) - char const *m; -{ - print_message_queue (); - error ("%s", m, 0); - exit (2); -} - -/* Like printf, except if -l in effect then save the message and print later. - This is used for things like "binary files differ" and "Only in ...". */ - -void -message (format, arg1, arg2) - char const *format, *arg1, *arg2; -{ - message5 (format, arg1, arg2, 0, 0); -} - -void -message5 (format, arg1, arg2, arg3, arg4) - char const *format, *arg1, *arg2, *arg3, *arg4; -{ - if (paginate_flag) - { - struct msg *new = (struct msg *) xmalloc (sizeof (struct msg)); - new->format = format; - new->arg1 = concat (arg1, "", ""); - new->arg2 = concat (arg2, "", ""); - new->arg3 = arg3 ? concat (arg3, "", "") : 0; - new->arg4 = arg4 ? concat (arg4, "", "") : 0; - new->next = 0; - *msg_chain_end = new; - msg_chain_end = &new->next; - } - else - { - if (sdiff_help_sdiff) - putchar (' '); - printf (format, arg1, arg2, arg3, arg4); - } -} - -/* Output all the messages that were saved up by calls to `message'. */ - -void -print_message_queue () -{ - struct msg *m; - - for (m = msg_chain; m; m = m->next) - printf (m->format, m->arg1, m->arg2, m->arg3, m->arg4); -} - -/* Call before outputting the results of comparing files NAME0 and NAME1 - to set up OUTFILE, the stdio stream for the output to go to. - - Usually, OUTFILE is just stdout. But when -l was specified - we fork off a `pr' and make OUTFILE a pipe to it. - `pr' then outputs to our stdout. */ - -static char const *current_name0; -static char const *current_name1; -static int current_depth; - -void -setup_output (name0, name1, depth) - char const *name0, *name1; - int depth; -{ - current_name0 = name0; - current_name1 = name1; - current_depth = depth; - outfile = 0; -} - -#if HAVE_FORK -static pid_t pr_pid; -#endif - -void -begin_output () -{ - char *name; - - if (outfile != 0) - return; - - /* Construct the header of this piece of diff. */ - name = xmalloc (strlen (current_name0) + strlen (current_name1) - + strlen (switch_string) + 7); - /* Posix.2 section 4.17.6.1.1 specifies this format. But there is a - bug in the first printing (IEEE Std 1003.2-1992 p 251 l 3304): - it says that we must print only the last component of the pathnames. - This requirement is silly and does not match historical practice. */ - sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1); - - if (paginate_flag) - { - /* Make OUTFILE a pipe to a subsidiary `pr'. */ - -#if HAVE_FORK - int pipes[2]; - - if (pipe (pipes) != 0) - pfatal_with_name ("pipe"); - - fflush (stdout); - - pr_pid = vfork (); - if (pr_pid < 0) - pfatal_with_name ("vfork"); - - if (pr_pid == 0) - { - close (pipes[1]); - if (pipes[0] != STDIN_FILENO) - { - if (dup2 (pipes[0], STDIN_FILENO) < 0) - pfatal_with_name ("dup2"); - close (pipes[0]); - } -#ifdef __FreeBSD__ - execl (PR_PROGRAM, PR_PROGRAM, "-F", "-h", name, (char *)NULL); -#else - execl (PR_PROGRAM, PR_PROGRAM, "-f", "-h", name, (char *)NULL); -#endif - pfatal_with_name (PR_PROGRAM); - } - else - { - close (pipes[0]); - outfile = fdopen (pipes[1], "w"); - if (!outfile) - pfatal_with_name ("fdopen"); - } -#else /* ! HAVE_FORK */ - char *command = xmalloc (4 * strlen (name) + strlen (PR_PROGRAM) + 10); - char *p; - char const *a = name; - sprintf (command, "%s -f -h ", PR_PROGRAM); - p = command + strlen (command); - SYSTEM_QUOTE_ARG (p, a); - *p = 0; - outfile = popen (command, "w"); - if (!outfile) - pfatal_with_name (command); - free (command); -#endif /* ! HAVE_FORK */ - } - else - { - - /* If -l was not specified, output the diff straight to `stdout'. */ - - outfile = stdout; - - /* If handling multiple files (because scanning a directory), - print which files the following output is about. */ - if (current_depth > 0) - printf ("%s\n", name); - } - - free (name); - - /* A special header is needed at the beginning of context output. */ - switch (output_style) - { - case OUTPUT_CONTEXT: - print_context_header (files, 0); - break; - - case OUTPUT_UNIFIED: - print_context_header (files, 1); - break; - - default: - break; - } -} - -/* Call after the end of output of diffs for one file. - Close OUTFILE and get rid of the `pr' subfork. */ - -void -finish_output () -{ - if (outfile != 0 && outfile != stdout) - { - int wstatus; - if (ferror (outfile)) - fatal ("write error"); -#if ! HAVE_FORK - wstatus = pclose (outfile); -#else /* HAVE_FORK */ - if (fclose (outfile) != 0) - pfatal_with_name ("write error"); - if (waitpid (pr_pid, &wstatus, 0) < 0) - pfatal_with_name ("waitpid"); -#endif /* HAVE_FORK */ - if (wstatus != 0) - fatal ("subsidiary pr failed"); - } - - outfile = 0; -} - -/* Compare two lines (typically one from each input file) - according to the command line options. - For efficiency, this is invoked only when the lines do not match exactly - but an option like -i might cause us to ignore the difference. - Return nonzero if the lines differ. */ - -int -line_cmp (s1, s2) - char const *s1, *s2; -{ - register unsigned char const *t1 = (unsigned char const *) s1; - register unsigned char const *t2 = (unsigned char const *) s2; - - while (1) - { - register unsigned char c1 = *t1++; - register unsigned char c2 = *t2++; - - /* Test for exact char equality first, since it's a common case. */ - if (c1 != c2) - { - /* Ignore horizontal white space if -b or -w is specified. */ - - if (ignore_all_space_flag) - { - /* For -w, just skip past any white space. */ - while (ISSPACE (c1) && c1 != '\n') c1 = *t1++; - while (ISSPACE (c2) && c2 != '\n') c2 = *t2++; - } - else if (ignore_space_change_flag) - { - /* For -b, advance past any sequence of white space in line 1 - and consider it just one Space, or nothing at all - if it is at the end of the line. */ - if (ISSPACE (c1)) - { - while (c1 != '\n') - { - c1 = *t1++; - if (! ISSPACE (c1)) - { - --t1; - c1 = ' '; - break; - } - } - } - - /* Likewise for line 2. */ - if (ISSPACE (c2)) - { - while (c2 != '\n') - { - c2 = *t2++; - if (! ISSPACE (c2)) - { - --t2; - c2 = ' '; - break; - } - } - } - - if (c1 != c2) - { - /* If we went too far when doing the simple test - for equality, go back to the first non-white-space - character in both sides and try again. */ - if (c2 == ' ' && c1 != '\n' - && (unsigned char const *) s1 + 1 < t1 - && ISSPACE(t1[-2])) - { - --t1; - continue; - } - if (c1 == ' ' && c2 != '\n' - && (unsigned char const *) s2 + 1 < t2 - && ISSPACE(t2[-2])) - { - --t2; - continue; - } - } - } - - /* Lowercase all letters if -i is specified. */ - - if (ignore_case_flag) - { - if (ISUPPER (c1)) - c1 = tolower (c1); - if (ISUPPER (c2)) - c2 = tolower (c2); - } - - if (c1 != c2) - break; - } - if (c1 == '\n') - return 0; - } - - return (1); -} - -/* Find the consecutive changes at the start of the script START. - Return the last link before the first gap. */ - -struct change * -find_change (start) - struct change *start; -{ - return start; -} - -struct change * -find_reverse_change (start) - struct change *start; -{ - return start; -} - -/* Divide SCRIPT into pieces by calling HUNKFUN and - print each piece with PRINTFUN. - Both functions take one arg, an edit script. - - HUNKFUN is called with the tail of the script - and returns the last link that belongs together with the start - of the tail. - - PRINTFUN takes a subscript which belongs together (with a null - link at the end) and prints it. */ - -void -print_script (script, hunkfun, printfun) - struct change *script; - struct change * (*hunkfun) PARAMS((struct change *)); - void (*printfun) PARAMS((struct change *)); -{ - struct change *next = script; - - while (next) - { - struct change *this, *end; - - /* Find a set of changes that belong together. */ - this = next; - end = (*hunkfun) (next); - - /* Disconnect them from the rest of the changes, - making them a hunk, and remember the rest for next iteration. */ - next = end->link; - end->link = 0; -#ifdef DEBUG - debug_script (this); -#endif - - /* Print this hunk. */ - (*printfun) (this); - - /* Reconnect the script so it will all be freed properly. */ - end->link = next; - } -} - -/* Print the text of a single line LINE, - flagging it with the characters in LINE_FLAG (which say whether - the line is inserted, deleted, changed, etc.). */ - -void -print_1_line (line_flag, line) - char const *line_flag; - char const * const *line; -{ - char const *text = line[0], *limit = line[1]; /* Help the compiler. */ - FILE *out = outfile; /* Help the compiler some more. */ - char const *flag_format = 0; - - /* If -T was specified, use a Tab between the line-flag and the text. - Otherwise use a Space (as Unix diff does). - Print neither space nor tab if line-flags are empty. */ - - if (line_flag && *line_flag) - { - flag_format = tab_align_flag ? "%s\t" : "%s "; - fprintf (out, flag_format, line_flag); - } - - output_1_line (text, limit, flag_format, line_flag); - - if ((!line_flag || line_flag[0]) && limit[-1] != '\n') - fprintf (out, "\n\\ No newline at end of file\n"); -} - -/* Output a line from TEXT up to LIMIT. Without -t, output verbatim. - With -t, expand white space characters to spaces, and if FLAG_FORMAT - is nonzero, output it with argument LINE_FLAG after every - internal carriage return, so that tab stops continue to line up. */ - -void -output_1_line (text, limit, flag_format, line_flag) - char const *text, *limit, *flag_format, *line_flag; -{ - if (!tab_expand_flag) - fwrite (text, sizeof (char), limit - text, outfile); - else - { - register FILE *out = outfile; - register unsigned char c; - register char const *t = text; - register unsigned column = 0; - - while (t < limit) - switch ((c = *t++)) - { - case '\t': - { - unsigned spaces = TAB_WIDTH - column % TAB_WIDTH; - column += spaces; - do - putc (' ', out); - while (--spaces); - } - break; - - case '\r': - putc (c, out); - if (flag_format && t < limit && *t != '\n') - fprintf (out, flag_format, line_flag); - column = 0; - break; - - case '\b': - if (column == 0) - continue; - column--; - putc (c, out); - break; - - default: - if (ISPRINT (c)) - column++; - putc (c, out); - break; - } - } -} - -int -change_letter (inserts, deletes) - int inserts, deletes; -{ - if (!inserts) - return 'd'; - else if (!deletes) - return 'a'; - else - return 'c'; -} - -/* Translate an internal line number (an index into diff's table of lines) - into an actual line number in the input file. - The internal line number is LNUM. FILE points to the data on the file. - - Internal line numbers count from 0 starting after the prefix. - Actual line numbers count from 1 within the entire file. */ - -int -translate_line_number (file, lnum) - struct file_data const *file; - int lnum; -{ - return lnum + file->prefix_lines + 1; -} - -void -translate_range (file, a, b, aptr, bptr) - struct file_data const *file; - int a, b; - int *aptr, *bptr; -{ - *aptr = translate_line_number (file, a - 1) + 1; - *bptr = translate_line_number (file, b + 1) - 1; -} - -/* Print a pair of line numbers with SEPCHAR, translated for file FILE. - If the two numbers are identical, print just one number. - - Args A and B are internal line numbers. - We print the translated (real) line numbers. */ - -void -print_number_range (sepchar, file, a, b) - int sepchar; - struct file_data *file; - int a, b; -{ - int trans_a, trans_b; - translate_range (file, a, b, &trans_a, &trans_b); - - /* Note: we can have B < A in the case of a range of no lines. - In this case, we should print the line number before the range, - which is B. */ - if (trans_b > trans_a) - fprintf (outfile, "%d%c%d", trans_a, sepchar, trans_b); - else - fprintf (outfile, "%d", trans_b); -} - -/* Look at a hunk of edit script and report the range of lines in each file - that it applies to. HUNK is the start of the hunk, which is a chain - of `struct change'. The first and last line numbers of file 0 are stored in - *FIRST0 and *LAST0, and likewise for file 1 in *FIRST1 and *LAST1. - Note that these are internal line numbers that count from 0. - - If no lines from file 0 are deleted, then FIRST0 is LAST0+1. - - Also set *DELETES nonzero if any lines of file 0 are deleted - and set *INSERTS nonzero if any lines of file 1 are inserted. - If only ignorable lines are inserted or deleted, both are - set to 0. */ - -void -analyze_hunk (hunk, first0, last0, first1, last1, deletes, inserts) - struct change *hunk; - int *first0, *last0, *first1, *last1; - int *deletes, *inserts; -{ - int l0, l1, show_from, show_to; - int i; - int trivial = ignore_blank_lines_flag || ignore_regexp_list; - struct change *next; - - show_from = show_to = 0; - - *first0 = hunk->line0; - *first1 = hunk->line1; - - next = hunk; - do - { - l0 = next->line0 + next->deleted - 1; - l1 = next->line1 + next->inserted - 1; - show_from += next->deleted; - show_to += next->inserted; - - for (i = next->line0; i <= l0 && trivial; i++) - if (!ignore_blank_lines_flag || files[0].linbuf[i][0] != '\n') - { - struct regexp_list *r; - char const *line = files[0].linbuf[i]; - int len = files[0].linbuf[i + 1] - line; - - for (r = ignore_regexp_list; r; r = r->next) - if (0 <= re_search (&r->buf, line, len, 0, len, 0)) - break; /* Found a match. Ignore this line. */ - /* If we got all the way through the regexp list without - finding a match, then it's nontrivial. */ - if (!r) - trivial = 0; - } - - for (i = next->line1; i <= l1 && trivial; i++) - if (!ignore_blank_lines_flag || files[1].linbuf[i][0] != '\n') - { - struct regexp_list *r; - char const *line = files[1].linbuf[i]; - int len = files[1].linbuf[i + 1] - line; - - for (r = ignore_regexp_list; r; r = r->next) - if (0 <= re_search (&r->buf, line, len, 0, len, 0)) - break; /* Found a match. Ignore this line. */ - /* If we got all the way through the regexp list without - finding a match, then it's nontrivial. */ - if (!r) - trivial = 0; - } - } - while ((next = next->link) != 0); - - *last0 = l0; - *last1 = l1; - - /* If all inserted or deleted lines are ignorable, - tell the caller to ignore this hunk. */ - - if (trivial) - show_from = show_to = 0; - - *deletes = show_from; - *inserts = show_to; -} - -/* malloc a block of memory, with fatal error message if we can't do it. */ - -VOID * -xmalloc (size) - size_t size; -{ - register VOID *value; - - if (size == 0) - size = 1; - - value = (VOID *) malloc (size); - - if (!value) - fatal ("memory exhausted"); - return value; -} - -/* realloc a block of memory, with fatal error message if we can't do it. */ - -VOID * -xrealloc (old, size) - VOID *old; - size_t size; -{ - register VOID *value; - - if (size == 0) - size = 1; - - value = (VOID *) realloc (old, size); - - if (!value) - fatal ("memory exhausted"); - return value; -} - -/* Concatenate three strings, returning a newly malloc'd string. */ - -char * -concat (s1, s2, s3) - char const *s1, *s2, *s3; -{ - size_t len = strlen (s1) + strlen (s2) + strlen (s3); - char *new = xmalloc (len + 1); - sprintf (new, "%s%s%s", s1, s2, s3); - return new; -} - -/* Yield the newly malloc'd pathname - of the file in DIR whose filename is FILE. */ - -char * -dir_file_pathname (dir, file) - char const *dir, *file; -{ - char const *p = filename_lastdirchar (dir); - return concat (dir, "/" + (p && !p[1]), file); -} - -void -debug_script (sp) - struct change *sp; -{ - fflush (stdout); - for (; sp; sp = sp->link) - fprintf (stderr, "%3d %3d delete %d insert %d\n", - sp->line0, sp->line1, sp->deleted, sp->inserted); - fflush (stderr); -} |