diff options
Diffstat (limited to 'gnu/usr.bin/diff')
-rw-r--r-- | gnu/usr.bin/diff/Makefile | 11 | ||||
-rw-r--r-- | gnu/usr.bin/diff/analyze.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/diff/config.h | 56 | ||||
-rw-r--r-- | gnu/usr.bin/diff/context.c | 12 | ||||
-rw-r--r-- | gnu/usr.bin/diff/diff.1 | 473 | ||||
-rw-r--r-- | gnu/usr.bin/diff/diff.c | 213 | ||||
-rw-r--r-- | gnu/usr.bin/diff/diff.h | 18 | ||||
-rw-r--r-- | gnu/usr.bin/diff/diff3.c | 204 | ||||
-rw-r--r-- | gnu/usr.bin/diff/dir.c | 16 | ||||
-rw-r--r-- | gnu/usr.bin/diff/ed.c | 6 | ||||
-rw-r--r-- | gnu/usr.bin/diff/getopt.c | 215 | ||||
-rw-r--r-- | gnu/usr.bin/diff/getopt1.c | 7 | ||||
-rw-r--r-- | gnu/usr.bin/diff/ifdef.c | 22 | ||||
-rw-r--r-- | gnu/usr.bin/diff/io.c | 140 | ||||
-rw-r--r-- | gnu/usr.bin/diff/regex.c | 892 | ||||
-rw-r--r-- | gnu/usr.bin/diff/regex.h | 2 | ||||
-rw-r--r-- | gnu/usr.bin/diff/sdiff.c | 463 | ||||
-rw-r--r-- | gnu/usr.bin/diff/side.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/diff/system.h | 160 | ||||
-rw-r--r-- | gnu/usr.bin/diff/util.c | 174 | ||||
-rw-r--r-- | gnu/usr.bin/diff/version.c | 4 |
21 files changed, 1746 insertions, 1346 deletions
diff --git a/gnu/usr.bin/diff/Makefile b/gnu/usr.bin/diff/Makefile index e75c0a0..717a247 100644 --- a/gnu/usr.bin/diff/Makefile +++ b/gnu/usr.bin/diff/Makefile @@ -1,11 +1,10 @@ PROG= diff SRCS= diff.c analyze.c io.c context.c ed.c normal.c ifdef.c util.c dir.c \ - version.c regex.c getopt.c getopt1.c side.c -CFLAGS+=-DDIRENT=1 -DHAVE_UNISTD_H=1 -DHAVE_DUP2=1 -DHAVE_MEMCHR=1 \ - -DHAVE_STRERROR=1 -DHAVE_WAITPID=1 -DHAVE_FCNTL_H=1 \ - -DHAVE_STRING_H=1 -DHAVE_SYS_WAIT_H=1 -DHAVE_TIME_H=1 \ - -DHAVE_ST_BLKSIZE=1 -NOMAN=noman + version.c getopt.c getopt1.c side.c cmpbuf.c +CFLAGS+=-DHAVE_CONFIG_H + +DPADD+= ${LIBGNUREGEX} +LDADD+= -lgnuregex .include <bsd.prog.mk> diff --git a/gnu/usr.bin/diff/analyze.c b/gnu/usr.bin/diff/analyze.c index 556d388..03f5647 100644 --- a/gnu/usr.bin/diff/analyze.c +++ b/gnu/usr.bin/diff/analyze.c @@ -332,7 +332,7 @@ diag (xoff, xlim, yoff, ylim, minimal, part) Note that XLIM, YLIM are exclusive bounds. All line numbers are origin-0 and discarded lines are not counted. - + If MINIMAL is nonzero, find a minimal difference no matter how expensive it is. */ diff --git a/gnu/usr.bin/diff/config.h b/gnu/usr.bin/diff/config.h index 3d7e65b..ed8e8ef 100644 --- a/gnu/usr.bin/diff/config.h +++ b/gnu/usr.bin/diff/config.h @@ -1,12 +1,9 @@ /* config.h. Generated automatically by configure. */ -/* config.hin. Generated automatically from configure.in by autoheader. */ +/* config.h.in. Generated automatically from configure.in by autoheader. */ /* Define if using alloca.c. */ /* #undef C_ALLOCA */ -/* Define if the closedir function returns void instead of int. */ -/* #undef CLOSEDIR_VOID */ - /* Define to empty if the keyword does not work. */ /* #undef const */ @@ -14,7 +11,10 @@ This function is required for alloca.c support on those systems. */ /* #undef CRAY_STACKSEG_END */ -/* Define if you have <alloca.h> and it should be used (not on Ultrix). */ +/* Define if you have dirent.h. */ +#define DIRENT 1 + +/* Define if you have alloca.h and it should be used (not Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define if you don't have vprintf but do have _doprnt. */ @@ -23,7 +23,7 @@ /* Define if your struct stat has st_blksize. */ #define HAVE_ST_BLKSIZE 1 -/* Define if you have <vfork.h>. */ +/* Define if you have vfork.h. */ /* #undef HAVE_VFORK_H */ /* Define if you have the vprintf function. */ @@ -32,6 +32,9 @@ /* Define if on MINIX. */ /* #undef _MINIX */ +/* Define if you don't have dirent.h, but have ndir.h. */ +/* #undef NDIR */ + /* Define to `int' if <sys/types.h> doesn't define. */ /* #undef pid_t */ @@ -60,32 +63,32 @@ /* Define if you have the ANSI C header files. */ #define STDC_HEADERS 1 -/* Define if <sys/wait.h> is compatible with Posix applications. */ -#define HAVE_SYS_WAIT_H 1 +/* Define if you don't have dirent.h, but have sys/dir.h. */ +/* #undef SYSDIR */ + +/* Define if you don't have dirent.h, but have sys/ndir.h. */ +/* #undef SYSNDIR */ /* Define vfork as fork if vfork does not work. */ /* #undef vfork */ -/* Define if you have the dup2 function. */ +/* Define if the closedir function returns void instead of int. */ +/* #undef VOID_CLOSEDIR */ + +/* Define if you have dup2. */ #define HAVE_DUP2 1 -/* Define if you have the memchr function. */ +/* Define if you have memchr. */ #define HAVE_MEMCHR 1 -/* Define if you have the sigaction function. */ +/* Define if you have sigaction. */ #define HAVE_SIGACTION 1 -/* Define if you have the strchr function. */ -#define HAVE_STRCHR 1 - -/* Define if you have the strerror function. */ +/* Define if you have strerror. */ #define HAVE_STRERROR 1 -/* Define if you have the tmpnam function. */ -#define HAVE_TMPNAM 1 - -/* Define if you have the <dirent.h> header file. */ -#define HAVE_DIRENT_H 1 +/* Define if you have waitpid. */ +#define HAVE_WAITPID 1 /* Define if you have the <fcntl.h> header file. */ #define HAVE_FCNTL_H 1 @@ -93,23 +96,14 @@ /* Define if you have the <limits.h> header file. */ #define HAVE_LIMITS_H 1 -/* Define if you have the <ndir.h> header file. */ -/* #undef HAVE_NDIR_H */ - /* Define if you have the <stdlib.h> header file. */ #define HAVE_STDLIB_H 1 /* Define if you have the <string.h> header file. */ #define HAVE_STRING_H 1 -/* Define if you have the <sys/dir.h> header file. */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define if you have the <sys/file.h> header file. */ -#define HAVE_SYS_FILE_H 1 - -/* Define if you have the <sys/ndir.h> header file. */ -/* #undef HAVE_SYS_NDIR_H */ +/* Define if you have the <sys/wait.h> header file. */ +#define HAVE_SYS_WAIT_H 1 /* Define if you have the <time.h> header file. */ #define HAVE_TIME_H 1 diff --git a/gnu/usr.bin/diff/context.c b/gnu/usr.bin/diff/context.c index 14f950c..5b4b73f 100644 --- a/gnu/usr.bin/diff/context.c +++ b/gnu/usr.bin/diff/context.c @@ -1,5 +1,5 @@ /* Context-format output routines for GNU DIFF. - Copyright (C) 1988,1989,1991,1992,1993,1994 Free Software Foundation, Inc. + Copyright (C) 1988, 89, 91, 92, 93 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -45,13 +45,9 @@ print_context_label (mark, inf, label) if (label) fprintf (outfile, "%s %s\n", mark, label); else - { - char const *ct = ctime (&inf->stat.st_mtime); - if (!ct) - ct = "?\n"; - /* See Posix.2 section 4.17.6.1.4 for this format. */ - fprintf (outfile, "%s %s\t%s", mark, inf->name, ct); - } + /* See Posix.2 section 4.17.6.1.4 for this format. */ + fprintf (outfile, "%s %s\t%s", + mark, inf->name, ctime (&inf->stat.st_mtime)); } /* Print a header for a context diff, with the file names and dates. */ diff --git a/gnu/usr.bin/diff/diff.1 b/gnu/usr.bin/diff/diff.1 new file mode 100644 index 0000000..e16f6d9 --- /dev/null +++ b/gnu/usr.bin/diff/diff.1 @@ -0,0 +1,473 @@ +.TH DIFF 1 "22sep1993" "GNU Tools" "GNU Tools" +.SH NAME +diff \- find differences between two files +.SH SYNOPSIS +.B diff +[options] from-file to-file +.SH DESCRIPTION +In the simplest case, +.I diff +compares the contents of the two files +.I from-file +and +.IR to-file . +A file name of +.B \- +stands for +text read from the standard input. As a special case, +.B "diff \- \-" +compares a copy of standard input to itself. + +If +.I from-file +is a directory and +.I to-file +is not, +.I diff +compares the file in +.I from-file +whose file name is that of +.IR to-file , +and vice versa. The non-directory file must not be +.BR \- . + +If both +.I from-file +and +.I to-file +are directories, +.I diff +compares corresponding files in both directories, in +alphabetical order; this comparison is not recursive unless the +.B \-r +or +.B \-\-recursive +option is given. +.I diff +never +compares the actual contents of a directory as if it were a file. The +file that is fully specified may not be standard input, because standard +input is nameless and the notion of ``file with the same name'' does not +apply. + +.B diff +options begin with +.BR \- , +so normally +.I from-file +and +.I to-file +may not begin with +.BR \- . +However, +.B \-\- +as an +argument by itself treats the remaining arguments as file names even if +they begin with +.BR \- . +.SS Options +Below is a summary of all of the options that GNU +.I diff +accepts. +Most options have two equivalent names, one of which is a single letter +preceded by +.BR \- , +and the other of which is a long name preceded by +.BR \-\- . +Multiple single letter options (unless they take an +argument) can be combined into a single command line word: +.B \-ac +is +equivalent to +.BR "\-a \-c" . +Long named options can be abbreviated to +any unique prefix of their name. Brackets +.RB ( [ +and +.BR ] ) +indicate that an +option takes an optional argument. +.TP +.BI \- lines +Show +.I lines +(an integer) lines of context. This option does not +specify an output format by itself; it has no effect unless it is +combined with +.B \-c +or +.BR \-u . +This option is obsolete. For proper +operation, +.I patch +typically needs at least two lines of context. +.TP +.B \-a +Treat all files as text and compare them line-by-line, even if they +do not seem to be text. +.TP +.B \-b +Ignore changes in amount of white space. +.TP +.B \-B +Ignore changes that just insert or delete blank lines. +.TP +.B \-\-brief +Report only whether the files differ, not the details of the +differences. +.TP +.B \-c +Use the context output format. +.TP +.BI "\-C " lines +.br +.ns +.TP +.BI \-\-context[= lines ] +Use the context output format, showing +.I lines +(an integer) lines of +context, or three if +.I lines +is not given. +For proper operation, +.I patch +typically needs at least two lines of +context. +.TP +.BI \-\-changed\-group\-format= format +Use +.I format +to output a line group containing differing lines from +both files in if-then-else format. +.TP +.B \-d +Change the algorithm to perhaps find a smaller set of changes. This makes +.I diff +slower (sometimes much slower). +.TP +.BI "\-D " name +Make merged if-then-else format output, conditional on the preprocessor +macro +.IR name . +.TP +.B \-e +.br +.ns +.TP +.B \-\-ed +Make output that is a valid +.I ed +script. +.TP +.BI \-\-exclude= pattern +When comparing directories, ignore files and subdirectories whose basenames +match +.IR pattern . +.TP +.BI \-\-exclude\-from= file +When comparing directories, ignore files and subdirectories whose basenames +match any pattern contained in +.IR file . +.TP +.B \-\-expand\-tabs +Expand tabs to spaces in the output, to preserve the alignment of tabs +in the input files. +.TP +.B \-f +Make output that looks vaguely like an +.I ed +script but has changes +in the order they appear in the file. +.TP +.BI "\-F " regexp +In context and unified format, for each hunk of differences, show some +of the last preceding line that matches +.IR regexp . +.TP +.B \-\-forward\-ed +Make output that looks vaguely like an +.B ed +script but has changes +in the order they appear in the file. +.TP +.B \-h +This option currently has no effect; it is present for Unix +compatibility. +.TP +.B \-H +Use heuristics to speed handling of large files that have numerous +scattered small changes. +.TP +.BI \-\-horizon\-lines= lines +Do not discard the last +.I lines +lines of the common prefix +and the first +.I lines +lines of the common suffix. +.TP +.B \-i +Ignore changes in case; consider upper- and lower-case letters +equivalent. +.TP +.BI "\-I " regexp +Ignore changes that just insert or delete lines that match +.IR regexp . +.TP +.BI \-\-ifdef= name +Make merged if-then-else format output, conditional on the preprocessor +macro +.IR name . +.TP +.B \-\-ignore\-all\-space +Ignore white space when comparing lines. +.TP +.B \-\-ignore\-blank\-lines +Ignore changes that just insert or delete blank lines. +.TP +.B \-\-ignore\-case +Ignore changes in case; consider upper- and lower-case to be the same. +.TP +.BI \-\-ignore\-matching\-lines= regexp +Ignore changes that just insert or delete lines that match +.IR regexp . +.TP +.B \-\-ignore\-space\-change +Ignore changes in amount of white space. +.TP +.B \-\-initial\-tab +Output a tab rather than a space before the text of a line in normal or +context format. This causes the alignment of tabs in the line to look +normal. +.TP +.B \-l +Pass the output through +.I pr +to paginate it. +.TP +.BI "\-L " label +.br +.ns +.TP +.BI \-\-label= label +Use +.I label +instead of the file name in the context format +and unified format +headers. +.TP +.B \-\-left\-column +Print only the left column of two common lines in side by side format. +.TP +.BI \-\-line\-format= format +Use +.I format +to output all input lines in in-then-else format. +.TP +.B \-\-minimal +Change the algorithm to perhaps find a smaller set of changes. This +makes +.I diff +slower (sometimes much slower). +.TP +.B \-n +Output RCS-format diffs; like +.B \-f +except that each command +specifies the number of lines affected. +.TP +.B \-N +.br +.ns +.TP +.B \-\-new\-file +In directory comparison, if a file is found in only one directory, +treat it as present but empty in the other directory. +.TP +.BI \-\-new\-group\-format= format +Use +.I format +to output a group of lines taken from just the second +file in if-then-else format. +.TP +.BI \-\-new\-line\-format= format +Use +.I format +to output a line taken from just the second file in +if-then-else format. +.TP +.BI \-\-old\-group\-format= format +Use +.I format +to output a group of lines taken from just the first +file in if-then-else format. +.TP +.BI \-\-old\-line\-format= format +Use +.I format +to output a line taken from just the first file in +if-then-else format. +.TP +.B \-p +Show which C function each change is in. +.TP +.B \-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. +.TP +.B \-\-paginate +Pass the output through +.I pr +to paginate it. +.TP +.B \-q +Report only whether the files differ, not the details of the +differences. +.TP +.B \-r +When comparing directories, recursively compare any subdirectories +found. +.TP +.B \-\-rcs +Output RCS-format diffs; like +.B \-f +except that each command +specifies the number of lines affected. +.TP +.B \-\-recursive +When comparing directories, recursively compare any subdirectories +found. +.TP +.B \-\-report\-identical\-files +.br +.ns +.TP +.B \-s +Report when two files are the same. +.TP +.BI "\-S " file +When comparing directories, start with the file +.IR file . +This is +used for resuming an aborted comparison. +.TP +.B \-\-sdiff\-merge\-assist +Print extra information to help +.IR sdiff . +.I sdiff +uses this +option when it runs +.IR diff . +This option is not intended for users +to use directly. +.TP +.B \-\-show\-c\-function +Show which C function each change is in. +.TP +.BI \-\-show\-function\-line= regexp +In context and unified format, for each hunk of differences, show some +of the last preceding line that matches +.IR regexp . +.TP +.B \-\-side\-by\-side +Use the side by side output format. +.TP +.B \-\-speed\-large\-files +Use heuristics to speed handling of large files that have numerous +scattered small changes. +.TP +.BI \-\-starting\-file= file +When comparing directories, start with the file +.IR file . +This is +used for resuming an aborted comparison. +.TP +.B \-\-suppress\-common\-lines +Do not print common lines in side by side format. +.TP +.B \-t +Expand tabs to spaces in the output, to preserve the alignment of tabs +in the input files. +.TP +.B \-T +Output a tab rather than a space before the text of a line in normal or +context format. This causes the alignment of tabs in the line to look +normal. +.TP +.B \-\-text +Treat all files as text and compare them line-by-line, even if they +do not appear to be text. +.TP +.B \-u +Use the unified output format. +.TP +.BI \-\-unchanged\-group\-format= format +Use +.I format +to output a group of common lines taken from both files +in if-then-else format. +.TP +.BI \-\-unchanged\-line\-format= format +Use +.I format +to output a line common to both files in if-then-else +format. +.TP +.B \-\-unidirectional\-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. +.TP +.BI "\-U " lines +.br +.ns +.TP +.BI \-\-unified[= lines ] +Use the unified output format, showing +.I lines +(an integer) lines of +context, or three if +.I lines +is not given. +For proper operation, +.I patch +typically needs at least two lines of +context. +.TP +.B \-v +.br +.ns +.TP +.B \-\-version +Output the version number of +.IR diff . +.TP +.B \-w +Ignore white space when comparing lines. +.TP +.BI "\-W " columns +.br +.ns +.TP +.BI \-\-width= columns +Use an output width of +.I columns +in side by side format. +.TP +.BI "\-x " pattern +When comparing directories, ignore files and subdirectories whose basenames +match +.IR pattern . +.TP +.BI "\-X " file +When comparing directories, ignore files and subdirectories whose basenames +match any pattern contained in +.IR file . +.TP +.B \-y +Use the side by side output format. +.SH SEE ALSO +cmp(1), comm(1), diff3(1), ed(1), patch(1), pr(1), sdiff(1). +.SH DIAGNOSTICS +An exit status of 0 means no differences were found, 1 means some +differences were found, and 2 means trouble. diff --git a/gnu/usr.bin/diff/diff.c b/gnu/usr.bin/diff/diff.c index ab1549b..6004f84 100644 --- a/gnu/usr.bin/diff/diff.c +++ b/gnu/usr.bin/diff/diff.c @@ -1,5 +1,5 @@ /* GNU DIFF main routine. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -22,7 +22,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define GDIFF_MAIN #include "diff.h" -#include <signal.h> #include "getopt.h" #include "fnmatch.h" @@ -43,9 +42,7 @@ 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)); +static void usage PARAMS((char const *)); /* Nonzero for -r: if comparing two directories, compare their common subdirectories recursively. */ @@ -56,11 +53,6 @@ static int recursive; 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. @@ -197,6 +189,7 @@ static struct option const longopts[] = {"print", 0, 0, 'l'}, /* An alias, no longer recommended */ {"rcs", 0, 0, 'n'}, {"show-c-function", 0, 0, 'p'}, + {"binary", 0, 0, 'q'}, /* An alias, no longer recommended */ {"brief", 0, 0, 'q'}, {"recursive", 0, 0, 'r'}, {"report-identical-files", 0, 0, 's'}, @@ -220,7 +213,6 @@ static struct option const longopts[] = {"changed-group-format", 1, 0, 139}, {"horizon-lines", 1, 0, 140}, {"help", 0, 0, 141}, - {"binary", 0, 0, 142}, {0, 0, 0, 0} }; @@ -233,13 +225,12 @@ main (argc, argv) int c; int prev = -1; int width = DEFAULT_WIDTH; - int show_c_function = 0; /* Do our initializations. */ - initialize_main (&argc, &argv); - program_name = argv[0]; + program = argv[0]; output_style = OUTPUT_NORMAL; context = -1; + line_end_char = '\n'; /* Decode the options. */ @@ -279,8 +270,8 @@ main (argc, argv) case 'b': /* Ignore changes in amount of white space. */ ignore_space_change_flag = 1; + length_varies = 1; ignore_some_changes = 1; - ignore_some_line_changes = 1; break; case 'B': @@ -371,7 +362,6 @@ main (argc, argv) /* Ignore changes in case. */ ignore_case_flag = 1; ignore_some_changes = 1; - ignore_some_line_changes = 1; break; case 'I': @@ -384,14 +374,6 @@ main (argc, argv) 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': @@ -418,7 +400,7 @@ main (argc, argv) case 'p': /* Make context-style output and show name of last C function. */ - show_c_function = 1; + specify_style (OUTPUT_CONTEXT); add_regexp (&function_regexp_list, "^[_a-zA-Z$]"); break; @@ -469,14 +451,14 @@ main (argc, argv) break; case 'v': - printf ("diff - GNU diffutils version %s\n", version_string); + printf ("GNU diff 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; + length_varies = 1; break; case 'x': @@ -547,27 +529,16 @@ main (argc, argv) 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; + usage (0); default: - try_help (0); + usage (""); } prev = c; } - if (argc - optind != 2) - try_help (argc - optind < 2 ? "missing operand" : "extra operand"); + if (optind != argc - 2) + usage (optind < argc - 2 ? "extra operand" : "missing operand"); { @@ -587,9 +558,6 @@ main (argc, argv) 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) @@ -598,10 +566,6 @@ main (argc, argv) 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]) @@ -633,7 +597,8 @@ main (argc, argv) /* Print any messages that were saved up for last. */ print_message_queue (); - check_stdout (); + if (ferror (stdout) || fclose (stdout) != 0) + fatal ("write error"); exit (val); return val; } @@ -661,96 +626,37 @@ add_regexp (reglist, pattern) } static void -try_help (reason) +usage (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"); + if (reason && *reason) + fprintf (stderr, "%s: %s\n", program, reason); + fflush (stderr); + printf ("Usage: %s [options] from-file to-file\n", program); + printf ("Options:\n\ + [-abBcdefhHilnNpPqrstTuvwy] [-C lines] [-D name] [-F regexp]\n\ + [-I regexp] [-L from-label [-L to-label]] [-S starting-file] [-U lines]\n\ + [-W columns] [-x pattern] [-X pattern-file]\n"); + printf ("\ + [--brief] [--changed-group-format=format] [--context[=lines]] [--ed]\n\ + [--exclude=pattern] [--exclude-from=pattern-file] [--expand-tabs]\n\ + [--forward-ed] [--help] [--horizon-lines=lines] [--ifdef=name]\n\ + [--ignore-all-space] [--ignore-blank-lines] [--ignore-case]\n"); + printf ("\ + [--ignore-matching-lines=regexp] [--ignore-space-change]\n\ + [--initial-tab] [--label=from-label [--label=to-label]]\n\ + [--left-column] [--minimal] [--new-file] [--new-group-format=format]\n\ + [--new-line-format=format] [--old-group-format=format]\n"); + printf ("\ + [--old-line-format=format] [--paginate] [--rcs] [--recursive]\n\ + [--report-identical-files] [--sdiff-merge-assist] [--show-c-function]\n\ + [--show-function-line=regexp] [--side-by-side] [--speed-large-files]\n\ + [--starting-file=starting-file] [--suppress-common-lines] [--text]\n"); + printf ("\ + [--unchanged-group-format=format] [--unchanged-line-format=format]\n\ + [--unidirectional-new-file] [--unified[=lines]] [--version]\n\ + [--width=columns]\n"); + exit (reason ? 2 : 0); } static int @@ -804,19 +710,8 @@ filetype (st) 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'. */ + /* S_ISLNK is impossible with `stat'. */ #ifdef S_ISSOCK if (S_ISSOCK (st->st_mode)) return "socket"; #endif @@ -886,7 +781,7 @@ compare_files (dir0, name0, dir1, name1, depth) { int stat_result; - if (i && filename_cmp (inf[i].name, inf[0].name) == 0) + if (i && strcmp (inf[i].name, inf[0].name) == 0) { inf[i].stat = inf[0].stat; stat_result = 0; @@ -940,7 +835,7 @@ compare_files (dir0, name0, dir1, name1, depth) 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 *p = strrchr (fnm, '/'); char const *filename = inf[dir_arg].name = dir_file_pathname (dir, p ? p + 1 : fnm); @@ -964,8 +859,11 @@ compare_files (dir0, name0, dir1, name1, depth) val = 2; } - else if ((same_files = inf[0].desc != -1 && inf[1].desc != -1 - && 0 < same_file (&inf[0].stat, &inf[1].stat)) + else if ((same_files = inf[0].stat.st_ino == inf[1].stat.st_ino + && inf[0].stat.st_dev == inf[1].stat.st_dev + && inf[0].stat.st_size == inf[1].stat.st_size + && inf[0].desc != -1 + && inf[1].desc != -1) && no_diff_means_no_output) { /* The two named files are actually the same physical file. @@ -1059,13 +957,6 @@ compare_files (dir0, name0, dir1, name1, depth) 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); diff --git a/gnu/usr.bin/diff/diff.h b/gnu/usr.bin/diff/diff.h index 66c6940..9d51ffc 100644 --- a/gnu/usr.bin/diff/diff.h +++ b/gnu/usr.bin/diff/diff.h @@ -18,8 +18,13 @@ along with GNU DIFF; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "system.h" +#include <ctype.h> #include <stdio.h> -#include "regex.h" +#include "gnuregex.h" + +#ifndef PR_FILE_NAME +#define PR_FILE_NAME "/bin/pr" +#endif #define TAB_WIDTH 8 @@ -79,9 +84,9 @@ 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. +/* 1 if lines may match even if their lengths are different. This depends on various options. */ -EXTERN int ignore_some_line_changes; +EXTERN int length_varies; /* 1 if files may match even if their contents are not byte-for-byte identical. This depends on various options. */ @@ -112,6 +117,9 @@ EXTERN int no_details_flag; Normally nothing is output when that happens. */ EXTERN int print_file_same_flag; +/* character that ends a line. Currently this is always `\n'. */ +EXTERN char line_end_char; + /* 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; @@ -176,7 +184,7 @@ EXTERN char * switch_string; EXTERN int heuristic; /* Name of program the user invoked (for error messages). */ -EXTERN char *program_name; +EXTERN char * program; /* The result of comparison is an "edit script": a chain of `struct change'. Each `struct change' represents one place where some lines are deleted @@ -314,7 +322,7 @@ 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 line_cmp PARAMS((char const *, size_t, char const *, size_t)); 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 *)); diff --git a/gnu/usr.bin/diff/diff3.c b/gnu/usr.bin/diff/diff3.c index 5d94ab8..50cb88d 100644 --- a/gnu/usr.bin/diff/diff3.c +++ b/gnu/usr.bin/diff/diff3.c @@ -1,5 +1,5 @@ /* Three way file comparison program (diff3) for Project GNU. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1992, 1993 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 @@ -19,7 +19,7 @@ #include "system.h" #include <stdio.h> -#include <signal.h> +#include <ctype.h> #include "getopt.h" extern char const version_string[]; @@ -163,7 +163,9 @@ static int simple_only; /* If nonzero, do not output information for non-overlapping diffs. */ static int overlap_only; -/* If nonzero, show information for DIFF_2ND diffs. */ +/* If nonzero, show information for 3_way and DIFF_2ND diffs. + 1= show 2nd only when 1st and 3rd differ + 2= show 2nd when DIFF_2ND (1 and 3 have same change relative to 2) */ static int show_2nd; /* If nonzero, include `:wq' at the end of the script @@ -173,7 +175,7 @@ static int finalwrite; /* If nonzero, output a merged file. */ static int merge; -static char *program_name; +static char *argv0; static VOID *xmalloc PARAMS((size_t)); static VOID *xrealloc PARAMS((VOID *, size_t)); @@ -192,13 +194,11 @@ static struct diff3_block *make_3way_diff PARAMS((struct diff_block *, struct di static struct diff3_block *reverse_diff3_blocklist PARAMS((struct diff3_block *)); static struct diff3_block *using_to_diff3_block PARAMS((struct diff_block *[2], struct diff_block *[2], int, int, struct diff3_block const *)); static struct diff_block *process_diff PARAMS((char const *, char const *, struct diff_block **)); -static void check_stdout PARAMS((void)); static void fatal PARAMS((char const *)); static void output_diff3 PARAMS((FILE *, struct diff3_block *, int const[3], int const[3])); static void perror_with_exit PARAMS((char const *)); -static void try_help PARAMS((char const *)); static void undotlines PARAMS((FILE *, int, int, int)); -static void usage PARAMS((void)); +static void usage PARAMS((int)); static char const diff_program[] = DIFF_PROGRAM; @@ -206,6 +206,7 @@ static struct option const longopts[] = { {"text", 0, 0, 'a'}, {"show-all", 0, 0, 'A'}, + {"show-bogus-conflicts", 0, 0, 'B'}, {"ed", 0, 0, 'e'}, {"show-overlap", 0, 0, 'E'}, {"label", 1, 0, 'L'}, @@ -230,7 +231,7 @@ main (argc, argv) int c, i; int mapping[3]; int rev_mapping[3]; - int incompat = 0; + int incompat; int conflicts_found; struct diff_block *thread0, *thread1, *last_block; struct diff3_block *diff3; @@ -240,18 +241,22 @@ main (argc, argv) char **file; struct stat statb; - initialize_main (&argc, &argv); - program_name = argv[0]; + incompat = 0; - while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != EOF) + argv0 = argv[0]; + + while ((c = getopt_long (argc, argv, "aeimvx3ABEL:TX", longopts, 0)) != EOF) { switch (c) { case 'a': always_text = 1; break; + case 'B': + ++show_2nd; + /* Falls through */ case 'A': - show_2nd = 1; + ++show_2nd; flagging = 1; incompat++; break; @@ -282,12 +287,10 @@ main (argc, argv) tab_align_flag = 1; break; case 'v': - printf ("diff3 - GNU diffutils version %s\n", version_string); + printf ("GNU diff3 version %s\n", version_string); exit (0); case 129: - usage (); - check_stdout (); - exit (0); + usage (0); case 'L': /* Handle up to three -L options. */ if (tag_count < 3) @@ -295,9 +298,9 @@ main (argc, argv) tag_strings[tag_count++] = optarg; break; } - try_help ("Too many labels were given. The limit is 3."); + /* Falls through */ default: - try_help (0); + usage (2); } } @@ -307,11 +310,9 @@ main (argc, argv) if (incompat > 1 /* Ensure at most one of -AeExX3. */ || finalwrite & merge /* -i -m would rewrite input file. */ - || (tag_count && ! flagging)) /* -L requires one of -AEX. */ - try_help ("incompatible options"); - - if (argc - optind != 3) - try_help (argc - optind < 3 ? "missing operand" : "extra operand"); + || (tag_count && ! flagging) /* -L requires one of -AEX. */ + || argc - optind != 3) + usage (2); file = &argv[optind]; @@ -354,20 +355,11 @@ main (argc, argv) perror_with_exit (file[i]); else if (S_ISDIR(statb.st_mode)) { - fprintf (stderr, "%s: %s: Is a directory\n", - program_name, file[i]); + fprintf (stderr, "%s: %s: Is a directory\n", argv0, file[i]); exit (2); } } -#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 - commonname = file[rev_mapping[FILEC]]; thread1 = process_diff (file[rev_mapping[FILE1]], commonname, &last_block); if (thread1) @@ -398,54 +390,30 @@ main (argc, argv) conflicts_found = 0; } - check_stdout (); - exit (conflicts_found); - return conflicts_found; -} - -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 -check_stdout () -{ if (ferror (stdout) || fclose (stdout) != 0) fatal ("write error"); + exit (conflicts_found); + return conflicts_found; } /* - * Explain, patiently and kindly, how to use this program. + * Explain, patiently and kindly, how to use this program. Then exit. */ static void -usage () +usage (status) + int status; { - printf ("Usage: %s [OPTION]... MYFILE OLDFILE YOURFILE\n\n", program_name); - - printf ("%s", "\ - -e --ed Output unmerged changes from OLDFILE to YOURFILE into MYFILE.\n\ - -E --show-overlap Output unmerged changes, bracketing conflicts.\n\ - -A --show-all Output all changes, bracketing conflicts.\n\ - -x --overlap-only Output overlapping changes.\n\ - -X Output overlapping changes, bracketing them.\n\ - -3 --easy-only Output unmerged nonoverlapping changes.\n\n"); - printf ("%s", "\ - -m --merge Output merged file instead of ed script (default -A).\n\ - -L LABEL --label=LABEL Use LABEL instead of file name.\n\ - -i Append `w' and `q' commands to ed scripts.\n\ - -a --text Treat all files as text.\n\ - -T --initial-tab Make tabs line up by prepending a tab.\n\n"); - printf ("%s", "\ - -v --version Output version info.\n\ - --help Output this help.\n\n"); - printf ("If a FILE is `-', read standard input.\n"); + fflush (stderr); + printf ("\ +Usage: %s [options] my-file older-file your-file\n\ +Options:\n\ + [-exABEX3aTv] [-i|-m] [-L label1 [-L label2 [-L label3]]]\n\ + [--easy-only] [--ed] [--help] [--initial-tab]\n\ + [--label=label1 [--label=label2 [--label=label3]]] [--merge]\n\ + [--overlap-only] [--show-all] [ --show-bogus-conflicts ]\n\ + [--show-overlap] [--text] [--version]\n\ + Only one of [exABEX3] is allowed\n", argv0); + exit (status); } /* @@ -935,6 +903,8 @@ compare_line_list (list1, lengths1, list2, lengths2, nl) extern char **environ; +#define DIFF_CHUNK_SIZE 10000 + static struct diff_block * process_diff (filea, fileb, last_block) char const *filea, *fileb; @@ -961,7 +931,7 @@ process_diff (filea, fileb, last_block) dt = process_diff_control (&scan_diff, bptr); if (dt == ERROR || *scan_diff != '\n') { - fprintf (stderr, "%s: diff error: ", program_name); + fprintf (stderr, "%s: diff error: ", argv0); do { putc (*scan_diff, stderr); @@ -1069,9 +1039,9 @@ process_diff_control (string, db) #define SKIPWHITE(s) { while (*s == ' ' || *s == '\t') s++; } #define READNUM(s, num) \ - { unsigned char c = *s; if (!ISDIGIT (c)) return ERROR; holdnum = 0; \ + { unsigned char c = *s; if (!isdigit (c)) return ERROR; holdnum = 0; \ do { holdnum = (c - '0' + holdnum * 10); } \ - while (ISDIGIT (c = *++s)); (num) = holdnum; } + while (isdigit (c = *++s)); (num) = holdnum; } /* Read first set of digits */ SKIPWHITE (s); @@ -1133,20 +1103,12 @@ read_diff (filea, fileb, output_placement) { char *diff_result; size_t bytes, current_chunk_size, total; - int fd, wstatus; - struct stat pipestat; - - /* 302 / 1000 is log10(2.0) rounded up. Subtract 1 for the sign bit; - add 1 for integer division truncation; add 1 more for a minus sign. */ -#define INT_STRLEN_BOUND(type) ((sizeof(type)*CHAR_BIT - 1) * 302 / 1000 + 2) - -#if HAVE_FORK - char const *argv[7]; - char horizon_arg[17 + INT_STRLEN_BOUND (int)]; + char horizon_arg[256]; char const **ap; int fds[2]; pid_t pid; + int wstatus; ap = argv; *ap++ = diff_program; @@ -1159,8 +1121,8 @@ read_diff (filea, fileb, output_placement) *ap++ = fileb; *ap = 0; - if (pipe (fds) != 0) - perror_with_exit ("pipe"); + if (pipe (fds) < 0) + perror_with_exit ("pipe failed"); pid = vfork (); if (pid == 0) @@ -1183,37 +1145,11 @@ read_diff (filea, fileb, output_placement) perror_with_exit ("fork failed"); close (fds[1]); /* Prevent erroneous lack of EOF */ - fd = fds[0]; - -#else /* ! HAVE_FORK */ - - FILE *fpipe; - char *command = xmalloc (sizeof (diff_program) + 30 + INT_STRLEN_BOUND (int) - + 4 * (strlen (filea) + strlen (fileb))); - char *p; - sprintf (command, "%s -a --horizon-lines=%d -- ", - diff_program, horizon_lines); - p = command + strlen (command); - SYSTEM_QUOTE_ARG (p, filea); - *p++ = ' '; - SYSTEM_QUOTE_ARG (p, fileb); - *p = '\0'; - fpipe = popen (command, "r"); - if (!fpipe) - perror_with_exit (command); - free (command); - fd = fileno (fpipe); - -#endif /* ! HAVE_FORK */ - - current_chunk_size = 8 * 1024; - if (fstat (fd, &pipestat) == 0) - current_chunk_size = max (current_chunk_size, STAT_BLOCKSIZE (pipestat)); - + current_chunk_size = DIFF_CHUNK_SIZE; diff_result = xmalloc (current_chunk_size); total = 0; do { - bytes = myread (fd, + bytes = myread (fds[0], diff_result + total, current_chunk_size - total); total += bytes; @@ -1234,18 +1170,18 @@ read_diff (filea, fileb, output_placement) *output_placement = diff_result; -#if ! HAVE_FORK - - wstatus = pclose (fpipe); - -#else /* HAVE_FORK */ - - if (close (fd) != 0) - perror_with_exit ("pipe close"); +#if HAVE_WAITPID if (waitpid (pid, &wstatus, 0) < 0) perror_with_exit ("waitpid failed"); - -#endif /* HAVE_FORK */ +#else + for (;;) { + pid_t w = wait (&wstatus); + if (w < 0) + perror_with_exit ("wait failed"); + if (w == pid) + break; + } +#endif if (! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 2)) fatal ("subsidiary diff failed"); @@ -1262,15 +1198,15 @@ read_diff (filea, fileb, output_placement) * are used as call-by-reference values. */ static char * -scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar) +scan_diff_line (scan_ptr, set_start, set_length, limit, firstchar) char *scan_ptr, **set_start; size_t *set_length; char *limit; - int leadingchar; + char firstchar; { char *line_ptr; - if (!(scan_ptr[0] == leadingchar + if (!(scan_ptr[0] == (firstchar) && scan_ptr[1] == ' ')) fatal ("invalid diff format; incorrect leading line chars"); @@ -1287,7 +1223,7 @@ scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar) if (line_ptr < limit && *line_ptr == '\\') { if (edscript) - fprintf (stderr, "%s:", program_name); + fprintf (stderr, "%s:", argv0); else --*set_length; line_ptr++; @@ -1494,7 +1430,7 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping, switch (type) { default: continue; - case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; + case DIFF_2ND: if (show_2nd < 2) continue; conflict = 1; break; case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; case DIFF_ALL: if (simple_only) continue; conflict = flagging; break; } @@ -1623,7 +1559,7 @@ output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping, switch (type) { default: continue; - case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break; + case DIFF_2ND: if (show_2nd < 2) continue; conflict = 1; break; case DIFF_3RD: if (overlap_only) continue; conflict = 0; break; case DIFF_ALL: if (simple_only) continue; conflict = flagging; format_2nd = "||||||| %s\n"; @@ -1762,7 +1698,7 @@ static void fatal (string) char const *string; { - fprintf (stderr, "%s: %s\n", program_name, string); + fprintf (stderr, "%s: %s\n", argv0, string); exit (2); } @@ -1771,7 +1707,7 @@ perror_with_exit (string) char const *string; { int e = errno; - fprintf (stderr, "%s: ", program_name); + fprintf (stderr, "%s: ", argv0); errno = e; perror (string); exit (2); diff --git a/gnu/usr.bin/diff/dir.c b/gnu/usr.bin/diff/dir.c index 036a86f..baadfbf 100644 --- a/gnu/usr.bin/diff/dir.c +++ b/gnu/usr.bin/diff/dir.c @@ -1,5 +1,5 @@ /* Read, sort and compare two directories. Used for GNU DIFF. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -75,7 +75,7 @@ dir_sort (dir, dirdata) while ((errno = 0, (next = readdir (reading)) != 0)) { char *d_name = next->d_name; - size_t d_size = NAMLEN (next) + 1; + size_t d_size; /* Ignore the files `.' and `..' */ if (d_name[0] == '.' @@ -85,6 +85,7 @@ dir_sort (dir, dirdata) if (excluded_filename (d_name)) continue; + d_size = strlen (d_name) + 1; while (data_alloc < data_used + d_size) dirdata->data = data = xrealloc (data, data_alloc *= 2); memcpy (data + data_used, d_name, d_size); @@ -98,7 +99,7 @@ dir_sort (dir, dirdata) errno = e; return -1; } -#if CLOSEDIR_VOID +#if VOID_CLOSEDIR closedir (reading); #else if (closedir (reading) != 0) @@ -128,8 +129,7 @@ static int compare_names (file1, file2) void const *file1, *file2; { - return filename_cmp (* (char const *const *) file1, - * (char const *const *) file2); + return strcmp (* (char const *const *) file1, * (char const *const *) file2); } /* Compare the contents of two directories named in FILEVEC[0] and FILEVEC[1]. @@ -182,9 +182,9 @@ diff_dirs (filevec, handle_file, depth) if (dir_start_file && depth == 0) { - while (*names0 && filename_cmp (*names0, dir_start_file) < 0) + while (*names0 && strcmp (*names0, dir_start_file) < 0) names0++; - while (*names1 && filename_cmp (*names1, dir_start_file) < 0) + while (*names1 && strcmp (*names1, dir_start_file) < 0) names1++; } @@ -195,7 +195,7 @@ diff_dirs (filevec, handle_file, depth) At the end of a dir, pretend the "next name" in that dir is very large. */ int nameorder = (!*names0 ? 1 : !*names1 ? -1 - : filename_cmp (*names0, *names1)); + : strcmp (*names0, *names1)); int v1 = (*handle_file) (name0, 0 < nameorder ? 0 : *names0++, name1, nameorder < 0 ? 0 : *names1++, depth + 1); diff --git a/gnu/usr.bin/diff/ed.c b/gnu/usr.bin/diff/ed.c index 717ef35..24f7270 100644 --- a/gnu/usr.bin/diff/ed.c +++ b/gnu/usr.bin/diff/ed.c @@ -36,7 +36,7 @@ print_ed_script (script) static void print_ed_hunk (hunk) - struct change *hunk; + struct change *hunk; { int f0, l0, f1, l1; int deletes, inserts; @@ -180,7 +180,7 @@ print_rcs_hunk (hunk) and the number of lines deleted. */ fprintf (outfile, "%d %d\n", tf0, - (tl0 >= tf0 ? tl0 - tf0 + 1 : 1)); + (tl0 >= tf0 ? tl0 - tf0 + 1 : 1)); } if (inserts) @@ -191,7 +191,7 @@ print_rcs_hunk (hunk) translate_range (&files[1], f1, l1, &tf1, &tl1); fprintf (outfile, "%d %d\n", tl0, - (tl1 >= tf1 ? tl1 - tf1 + 1 : 1)); + (tl1 >= tf1 ? tl1 - tf1 + 1 : 1)); /* Print the inserted lines. */ for (i = f1; i <= l1; i++) diff --git a/gnu/usr.bin/diff/getopt.c b/gnu/usr.bin/diff/getopt.c index 964189d..7a4673b 100644 --- a/gnu/usr.bin/diff/getopt.c +++ b/gnu/usr.bin/diff/getopt.c @@ -3,7 +3,7 @@ "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! - Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it @@ -20,14 +20,15 @@ along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. - Ditto for AIX 3.2 and <stdlib.h>. */ -#ifndef _NO_PROTO -#define _NO_PROTO -#endif - #ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ #include <config.h> +#else +#include "config.h" +#endif #endif #ifndef __STDC__ @@ -38,6 +39,11 @@ #endif #endif +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + #include <stdio.h> /* Comment out all this code if we are using the GNU C Library, and are not @@ -59,6 +65,11 @@ #include <stdlib.h> #endif /* GNU C library. */ +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. @@ -81,7 +92,7 @@ Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ -char *optarg = NULL; +char *optarg = 0; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller @@ -151,9 +162,6 @@ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; - -/* Value of POSIXLY_CORRECT environment variable. */ -static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries @@ -184,18 +192,19 @@ my_index (str, chr) } /* If using GCC, we can safely declare strlen this way. - If not using GCC, it is ok not to declare it. */ + If not using GCC, it is ok not to declare it. + (Supposedly there are some machines where it might get a warning, + but changing this conditional to __STDC__ is too risky.) */ #ifdef __GNUC__ -/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. - That was relevant to code that was here before. */ -#ifndef __STDC__ -/* gcc with -traditional declares the built-in strlen to return int, - and has done so at least since version 2.4.5. -- rms. */ -extern int strlen (const char *); -#endif /* not __STDC__ */ -#endif /* __GNUC__ */ +#ifdef IN_GCC +#include "gstddef.h" +#else +#include <stddef.h> +#endif +extern size_t strlen (const char *); +#endif -#endif /* not __GNU_LIBRARY__ */ +#endif /* GNU C library. */ /* Handle permutation of arguments. */ @@ -270,42 +279,6 @@ exchange (argv) first_nonopt += (optind - last_nonopt); last_nonopt = optind; } - -/* Initialize the internal data when the first call is made. */ - -static const char * -_getopt_initialize (optstring) - const char *optstring; -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - first_nonopt = last_nonopt = optind = 1; - - nextchar = NULL; - - posixly_correct = getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - - return optstring; -} /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. @@ -372,15 +345,41 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int *longind; int long_only; { - optarg = NULL; + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ if (optind == 0) - optstring = _getopt_initialize (optstring); + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } if (nextchar == NULL || *nextchar == '\0') { - /* Advance to the next ARGV-element. */ - if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, @@ -391,16 +390,21 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) else if (last_nonopt != optind) first_nonopt = optind; - /* Skip any additional non-options + /* Now skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc - && (argv[optind][0] != '-' || argv[optind][1] == '\0')) + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) optind++; last_nonopt = optind; } - /* The special ARGV-element `--' means premature end of options. + /* Special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ @@ -433,7 +437,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ - if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) { if (ordering == REQUIRE_ORDER) return EOF; @@ -442,48 +451,36 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } /* We have found another option-ARGV-element. - Skip the initial punctuation. */ + Start decoding its characters. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) { - char *nameend; const struct option *p; - const struct option *pfound = NULL; + char *s = nextchar; int exact = 0; int ambig = 0; + const struct option *pfound = NULL; int indfound; - int option_index; - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; + while (*s && *s != '=') + s++; - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) { - if (nameend - nextchar == strlen (p->name)) + if (s - nextchar == strlen (p->name)) { /* Exact match found. */ pfound = p; @@ -498,7 +495,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) indfound = option_index; } else - /* Second or later nonexact match found. */ + /* Second nonexact match found. */ ambig = 1; } @@ -516,12 +513,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { option_index = indfound; optind++; - if (*nameend) + if (*s) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) - optarg = nameend + 1; + optarg = s + 1; else { if (opterr) @@ -564,12 +561,14 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } return pfound->val; } - /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ || my_index (optstring, *nextchar) == NULL) { if (opterr) @@ -589,7 +588,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } } - /* Look at and handle the next short option-character. */ + /* Look at and handle the next option-character. */ { char c = *nextchar++; @@ -603,11 +602,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { if (opterr) { - if (posixly_correct) - /* 1003.2 specifies the format of this message. */ - fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); else - fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif } optopt = c; return '?'; @@ -623,7 +627,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) optind++; } else - optarg = NULL; + optarg = 0; nextchar = NULL; } else @@ -640,9 +644,14 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { if (opterr) { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); +#endif } optopt = c; if (optstring[0] == ':') diff --git a/gnu/usr.bin/diff/getopt1.c b/gnu/usr.bin/diff/getopt1.c index 725c653..f784b57 100644 --- a/gnu/usr.bin/diff/getopt1.c +++ b/gnu/usr.bin/diff/getopt1.c @@ -17,7 +17,14 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H +#if defined (emacs) || defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ #include <config.h> +#else +#include "config.h" +#endif #endif #include "getopt.h" diff --git a/gnu/usr.bin/diff/ifdef.c b/gnu/usr.bin/diff/ifdef.c index 2834cbd..0dbfd43 100644 --- a/gnu/usr.bin/diff/ifdef.c +++ b/gnu/usr.bin/diff/ifdef.c @@ -1,5 +1,5 @@ /* #ifdef-format output routines for GNU DIFF. - Copyright (C) 1989, 1991, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1989, 91, 92, 93 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -27,10 +27,10 @@ struct group int from, upto; /* start and limit lines for this group of lines */ }; -static char *format_group PARAMS((FILE *, char *, int, struct group const *)); +static char *format_group PARAMS((FILE *, char *, int, struct group const[])); static char *scan_char_literal PARAMS((char *, int *)); static char *scan_printf_spec PARAMS((char *)); -static int groups_letter_value PARAMS((struct group const *, int)); +static int groups_letter_value PARAMS((struct group const[], int)); static void format_ifdef PARAMS((char *, int, int, int, int)); static void print_ifdef_hunk PARAMS((struct change *)); static void print_ifdef_lines PARAMS((FILE *, char *, struct group const *)); @@ -117,7 +117,7 @@ format_group (out, format, endchar, groups) register FILE *out; char *format; int endchar; - struct group const *groups; + struct group const groups[]; { register char c; register char *f = format; @@ -142,10 +142,10 @@ format_group (out, format, endchar, groups) for (i = 0; i < 2; i++) { unsigned char f0 = f[0]; - if (ISDIGIT (f0)) + if (isdigit (f0)) { value[i] = atoi (f); - while (ISDIGIT ((unsigned char) *++f)) + while (isdigit ((unsigned char) *++f)) continue; } else @@ -238,10 +238,10 @@ format_group (out, format, endchar, groups) Return -1 if LETTER is not a group format letter. */ static int groups_letter_value (g, letter) - struct group const *g; + struct group const g[]; int letter; { - if (ISUPPER (letter)) + if (isupper (letter)) { g++; letter = tolower (letter); @@ -333,7 +333,7 @@ print_ifdef_lines (out, format, group) goto bad_format; break; - case 'n': + case 'n': value = translate_line_number (file, from); break; @@ -412,10 +412,10 @@ scan_printf_spec (spec) while ((c = *spec++) == '-') continue; - while (ISDIGIT (c)) + while (isdigit (c)) c = *spec++; if (c == '.') - while (ISDIGIT (c = *spec++)) + while (isdigit (c = *spec++)) continue; switch (c) { diff --git a/gnu/usr.bin/diff/io.c b/gnu/usr.bin/diff/io.c index 6605915..81d0260 100644 --- a/gnu/usr.bin/diff/io.c +++ b/gnu/usr.bin/diff/io.c @@ -1,5 +1,5 @@ /* File I/O for GNU DIFF. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -31,9 +31,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define GUESS_LINES(n,s,t) (((t) - (s)) / ((n) < 10 ? 32 : (s) / ((n)-1)) + 5) /* Type used for fast prefix comparison in find_identical_ends. */ -#ifndef word -#define word int -#endif +typedef int word; /* Lines are put into equivalence classes (of lines that match in line_cmp). Each equivalence class is represented by one of these structures, @@ -44,14 +42,13 @@ struct equivclass int next; /* Next item in this bucket. */ unsigned hash; /* Hash of lines in this class. */ char const *line; /* A line that fits this class. */ - size_t length; /* That line's length, not counting its newline. */ + size_t length; /* The length of that line. */ }; -/* Hash-table: array of buckets, each being a chain of equivalence classes. - buckets[-1] is reserved for incomplete lines. */ +/* Hash-table: array of buckets, each being a chain of equivalence classes. */ static int *buckets; -/* Number of buckets in the hash table array, not counting buckets[-1]. */ +/* Number of buckets in the hash table array. */ static int nbuckets; /* Array in which the equivalence classes are allocated. @@ -74,7 +71,7 @@ static void prepare_text_end PARAMS((struct file_data *)); /* Return 1 if BUF contains a non text character. SIZE is the number of characters in BUF. */ -#define binary_file_p(buf, size) (memchr (buf, '\0', size) != 0) +#define binary_file_p(buf, size) (size != 0 && memchr (buf, '\0', size) != 0) /* Get ready to read the current file. Return nonzero if SKIP_TEST is zero, @@ -100,23 +97,12 @@ sip (current, skip_test) if (! skip_test) { /* Check first part of file to see if it's a binary file. */ -#if HAVE_SETMODE - int oldmode = setmode (current->desc, O_BINARY); -#endif - size_t n = read (current->desc, current->buffer, current->bufsize); - if (n == -1) + current->buffered_chars = read (current->desc, + current->buffer, + current->bufsize); + if (current->buffered_chars == -1) pfatal_with_name (current->name); - current->buffered_chars = n; -#if HAVE_SETMODE - if (oldmode != O_BINARY) - { - if (lseek (current->desc, - (off_t) n, SEEK_CUR) == -1) - pfatal_with_name (current->name); - setmode (current->desc, oldmode); - current->buffered_chars = 0; - } -#endif - return binary_file_p (current->buffer, n); + return binary_file_p (current->buffer, current->buffered_chars); } } @@ -207,7 +193,10 @@ find_and_hash_each_line (current) int eqs_alloc = equivs_alloc; char const *suffix_begin = current->suffix_begin; char const *bufend = current->buffer + current->buffered_chars; - int use_line_cmp = ignore_some_line_changes; + char const *incomplete_tail + = current->missing_newline && ROBUST_OUTPUT_STYLE (output_style) + ? bufend : (char const *) 0; + int varies = length_varies; while ((char const *) p < suffix_begin) { @@ -223,52 +212,42 @@ find_and_hash_each_line (current) if (ignore_all_space_flag) while ((c = *p++) != '\n') { - if (! ISSPACE (c)) - h = HASH (h, ISUPPER (c) ? tolower (c) : c); + if (! isspace (c)) + h = HASH (h, isupper (c) ? tolower (c) : c); } else if (ignore_space_change_flag) while ((c = *p++) != '\n') { - if (ISSPACE (c)) + if (isspace (c)) { - for (;;) - { - c = *p++; - if (!ISSPACE (c)) - break; - if (c == '\n') - goto hashing_done; - } + while (isspace (c = *p++)) + if (c == '\n') + goto hashing_done; h = HASH (h, ' '); } /* C is now the first non-space. */ - h = HASH (h, ISUPPER (c) ? tolower (c) : c); + h = HASH (h, isupper (c) ? tolower (c) : c); } else while ((c = *p++) != '\n') - h = HASH (h, ISUPPER (c) ? tolower (c) : c); + h = HASH (h, isupper (c) ? tolower (c) : c); } else { if (ignore_all_space_flag) while ((c = *p++) != '\n') { - if (! ISSPACE (c)) + if (! isspace (c)) h = HASH (h, c); } else if (ignore_space_change_flag) while ((c = *p++) != '\n') { - if (ISSPACE (c)) + if (isspace (c)) { - for (;;) - { - c = *p++; - if (!ISSPACE (c)) - break; - if (c == '\n') - goto hashing_done; - } + while (isspace (c = *p++)) + if (c == '\n') + goto hashing_done; h = HASH (h, ' '); } /* C is now the first non-space. */ @@ -281,22 +260,7 @@ find_and_hash_each_line (current) hashing_done:; bucket = &buckets[h % nbuckets]; - length = (char const *) p - ip - 1; - - if ((char const *) p == bufend - && current->missing_newline - && ROBUST_OUTPUT_STYLE (output_style)) - { - /* This line is incomplete. If this is significant, - put the line into bucket[-1]. */ - if (! (ignore_space_change_flag | ignore_all_space_flag)) - bucket = &buckets[-1]; - - /* Omit the inserted newline when computing linbuf later. */ - p--; - bufend = suffix_begin = (char const *) p; - } - + length = (char const *) p - ip - ((char const *) p == incomplete_tail); for (i = *bucket; ; i = eqs[i].next) if (!i) { @@ -312,20 +276,11 @@ find_and_hash_each_line (current) *bucket = i; break; } - else if (eqs[i].hash == h) - { - char const *eqline = eqs[i].line; - - /* Reuse existing equivalence class if the lines are identical. - This detects the common case of exact identity - faster than complete comparison would. */ - if (eqs[i].length == length && memcmp (eqline, ip, length) == 0) - break; - - /* Reuse existing class if line_cmp reports the lines equal. */ - if (use_line_cmp && line_cmp (eqline, ip) == 0) - break; - } + else if (eqs[i].hash == h + && (eqs[i].length == length || varies) + && ! line_cmp (eqs[i].line, eqs[i].length, ip, length)) + /* Reuse existing equivalence class. */ + break; /* Maybe increase the size of the line table. */ if (line == alloc_lines) @@ -348,7 +303,7 @@ find_and_hash_each_line (current) for (i = 0; ; i++) { /* Record the line start for lines in the suffix that we care about. - Record one more line start than lines, + Record one more line start than lines, so that we can compute the length of any buffered line. */ if (line == alloc_lines) { @@ -362,7 +317,10 @@ find_and_hash_each_line (current) linbuf[line] = (char const *) p; if ((char const *) p == bufend) - break; + { + linbuf[line] -= (char const *) p == incomplete_tail; + break; + } if (context <= i && no_diff_means_no_output) break; @@ -385,7 +343,7 @@ find_and_hash_each_line (current) /* Prepare the end of the text. Make sure it's initialized. Make sure text ends in a newline, - but remember that we had to add one. */ + but remember that we had to add one unless -B is in effect. */ static void prepare_text_end (current) @@ -400,7 +358,7 @@ prepare_text_end (current) { p[buffered_chars++] = '\n'; current->buffered_chars = buffered_chars; - current->missing_newline = 1; + current->missing_newline = ! ignore_blank_lines_flag; } /* Don't use uninitialized storage when planting or using sentinels. */ @@ -678,13 +636,7 @@ read_files (filevec, pretend_binary) filevec[1].buffered_chars = filevec[0].buffered_chars; } if (appears_binary) - { -#if HAVE_SETMODE - setmode (filevec[0].desc, O_BINARY); - setmode (filevec[1].desc, O_BINARY); -#endif - return 1; - } + return 1; find_identical_ends (filevec); @@ -699,16 +651,16 @@ read_files (filevec, pretend_binary) abort (); nbuckets = primes[i]; - buckets = (int *) xmalloc ((nbuckets + 1) * sizeof (*buckets)); - bzero (buckets++, (nbuckets + 1) * sizeof (*buckets)); + buckets = (int *) xmalloc (nbuckets * sizeof (*buckets)); + bzero (buckets, nbuckets * sizeof (*buckets)); - for (i = 0; i < 2; i++) + for (i = 0; i < 2; ++i) find_and_hash_each_line (&filevec[i]); filevec[0].equiv_max = filevec[1].equiv_max = equivs_index; free (equivs); - free (buckets - 1); + free (buckets); return 0; } diff --git a/gnu/usr.bin/diff/regex.c b/gnu/usr.bin/diff/regex.c index e8b5882..81b06ff 100644 --- a/gnu/usr.bin/diff/regex.c +++ b/gnu/usr.bin/diff/regex.c @@ -26,6 +26,17 @@ #define _GNU_SOURCE +#ifdef HAVE_CONFIG_H +#if defined (CONFIG_BROKETS) +/* We use <config.h> instead of "config.h" so that a compilation + using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h + (which it would do because it found this file in $srcdir). */ +#include <config.h> +#else +#include "config.h" +#endif +#endif + /* We need this for `regex.h', and perhaps for the Emacs include files. */ #include <sys/types.h> @@ -46,6 +57,14 @@ #else /* not emacs */ +#ifdef STDC_HEADERS +#include <stdlib.h> +#else +char *malloc (); +char *realloc (); +#endif + + /* We used to test for `BSTRING' here, but only GCC and Emacs define `BSTRING', as far as I know, and neither of them use this code. */ #if HAVE_STRING_H || STDC_HEADERS @@ -63,14 +82,6 @@ #include <strings.h> #endif -#ifdef STDC_HEADERS -#include <stdlib.h> -#else -char *malloc (); -char *realloc (); -#endif - - /* Define the syntax stuff for \<, \>, etc. */ /* This must be nonzero for the wordchar and notwordchar pattern @@ -235,6 +246,8 @@ char *alloca (); /* (Re)Allocate N items of type T using malloc, or fail. */ #define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) #define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +#define RETALLOC_IF(addr, n, t) \ + if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) #define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) #define BYTEWIDTH 8 /* In bits. */ @@ -871,6 +884,387 @@ static const char *re_error_msg[] = "Unmatched ) or \\)", /* REG_ERPAREN */ }; +/* Avoiding alloca during matching, to placate r_alloc. */ + +/* Define MATCH_MAY_ALLOCATE if we need to make sure that the + searching and matching functions should not call alloca. On some + systems, alloca is implemented in terms of malloc, and if we're + using the relocating allocator routines, then malloc could cause a + relocation, which might (if the strings being searched are in the + ralloc heap) shift the data out from underneath the regexp + routines. + + Here's another reason to avoid allocation: Emacs insists on + processing input from X in a signal handler; processing X input may + call malloc; if input arrives while a matching routine is calling + malloc, then we're scrod. But Emacs can't just block input while + calling matching routines; then we don't notice interrupts when + they come in. So, Emacs blocks input around all regexp calls + except the matching calls, which it leaves unprotected, in the + faith that they will not malloc. */ + +/* Normally, this is fine. */ +#define MATCH_MAY_ALLOCATE + +/* But under some circumstances, it's not. */ +#if defined (emacs) || (defined (REL_ALLOC) && defined (C_ALLOCA)) +#undef MATCH_MAY_ALLOCATE +#endif + + +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +#ifndef INIT_FAILURE_ALLOC +#define INIT_FAILURE_ALLOC 5 +#endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_SPACE each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ +int re_max_failures = 2000; + +typedef unsigned char *fail_stack_elt_t; + +typedef struct +{ + fail_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} fail_stack_type; + +#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) + + +/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ + +#ifdef MATCH_MAY_ALLOCATE +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (fail_stack_elt_t *) \ + REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) +#else +#define INIT_FAIL_STACK() \ + do { \ + fail_stack.avail = 0; \ + } while (0) +#endif + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE requires `destination' be declared. */ + +#define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ + ? 0 \ + : ((fail_stack).stack = (fail_stack_elt_t *) \ + REGEX_REALLOCATE ((fail_stack).stack, \ + (fail_stack).size * sizeof (fail_stack_elt_t), \ + ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push PATTERN_OP on FAIL_STACK. + + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (fail_stack)) \ + ? 0 \ + : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ + 1)) + +/* This pushes an item onto the failure stack. Must be a four-byte + value. Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +#define PUSH_FAILURE_ITEM(item) \ + fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item + +/* The complement operation. Assumes `fail_stack' is nonempty. */ +#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +#ifdef DEBUG +#define DEBUG_PUSH PUSH_FAILURE_ITEM +#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () +#else +#define DEBUG_PUSH(item) +#define DEBUG_POP(item_addr) +#endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be + declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + int this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + PUSH_FAILURE_ITEM (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + PUSH_FAILURE_ITEM (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ + PUSH_FAILURE_ITEM (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ + PUSH_FAILURE_ITEM (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_ITEM (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_ITEM (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +/* This is the number of items that are pushed and popped on the stack + for each register. */ +#define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +#ifdef DEBUG +#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +#else +#define NUM_NONREG_ITEMS 4 +#endif + +/* We push at most this many items on the stack. */ +#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +#define NUM_FAILURE_ITEMS \ + ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ + +#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ + int this_reg; \ + const unsigned char *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_ITEM (); \ + if (string_temp != NULL) \ + str = (const char *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (unsigned char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ + \ + low_reg = (unsigned) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ + \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ + \ + regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ + DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ + } \ + \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + + + +/* Structure for per-register (a.k.a. per-group) information. + This must not be longer than one word, because we push this value + onto the failure stack. Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ +typedef union +{ + fail_stack_elt_t word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +#define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} register_info_type; + +#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +#define IS_ACTIVE(R) ((R).bits.is_active) +#define MATCHED_SOMETHING(R) ((R).bits.matched_something) +#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +#define SET_REGS_MATCHED() \ + do \ + { \ + unsigned r; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + while (0) + + +/* Registers are set to a sentinel when they haven't yet matched. */ +#define REG_UNSET_VALUE ((char *) -1) +#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + + + +/* How do we implement a missing MATCH_MAY_ALLOCATE? + We make the fail stack a global thing, and then grow it to + re_max_failures when we compile. */ +#ifndef MATCH_MAY_ALLOCATE +static fail_stack_type fail_stack; + +static const char ** regstart, ** regend; +static const char ** old_regstart, ** old_regend; +static const char **best_regstart, **best_regend; +static register_info_type *reg_info; +static const char **reg_dummy; +static register_info_type *reg_info_dummy; +#endif + + /* Subroutine declarations and macros for regex_compile. */ static void store_op1 (), store_op2 (); @@ -2086,6 +2480,40 @@ regex_compile (pattern, size, syntax, bufp) } #endif /* DEBUG */ +#ifndef MATCH_MAY_ALLOCATE + /* Initialize the failure stack to the largest possible stack. This + isn't necessary unless we're trying to avoid calling alloca in + the search and match routines. */ + { + int num_regs = bufp->re_nsub + 1; + + /* Since DOUBLE_FAIL_STACK refuses to double only if the current size + is strictly greater than re_max_failures, the largest possible stack + is 2 * re_max_failures failure points. */ + fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); + if (fail_stack.stack) + fail_stack.stack = + (fail_stack_elt_t *) realloc (fail_stack.stack, + (fail_stack.size + * sizeof (fail_stack_elt_t))); + else + fail_stack.stack = + (fail_stack_elt_t *) malloc (fail_stack.size + * sizeof (fail_stack_elt_t)); + + /* Initialize some other variables the matcher uses. */ + RETALLOC_IF (regstart, num_regs, const char *); + RETALLOC_IF (regend, num_regs, const char *); + RETALLOC_IF (old_regstart, num_regs, const char *); + RETALLOC_IF (old_regend, num_regs, const char *); + RETALLOC_IF (best_regstart, num_regs, const char *); + RETALLOC_IF (best_regend, num_regs, const char *); + RETALLOC_IF (reg_info, num_regs, register_info_type); + RETALLOC_IF (reg_dummy, num_regs, const char *); + RETALLOC_IF (reg_info_dummy, num_regs, register_info_type); + } +#endif + return REG_NOERROR; } /* regex_compile */ @@ -2275,280 +2703,6 @@ compile_range (p_ptr, pend, translate, syntax, b) return REG_NOERROR; } -/* Failure stack declarations and macros; both re_compile_fastmap and - re_match_2 use a failure stack. These have to be macros because of - REGEX_ALLOCATE. */ - - -/* Number of failure points for which to initially allocate space - when matching. If this number is exceeded, we allocate more - space, so it is not a hard limit. */ -#ifndef INIT_FAILURE_ALLOC -#define INIT_FAILURE_ALLOC 5 -#endif - -/* Roughly the maximum number of failure points on the stack. Would be - exactly that if always used MAX_FAILURE_SPACE each time we failed. - This is a variable only so users of regex can assign to it; we never - change it ourselves. */ -int re_max_failures = 2000; - -typedef const unsigned char *fail_stack_elt_t; - -typedef struct -{ - fail_stack_elt_t *stack; - unsigned size; - unsigned avail; /* Offset of next open position. */ -} fail_stack_type; - -#define FAIL_STACK_EMPTY() (fail_stack.avail == 0) -#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) -#define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) -#define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) - - -/* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ - -#define INIT_FAIL_STACK() \ - do { \ - fail_stack.stack = (fail_stack_elt_t *) \ - REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ - \ - if (fail_stack.stack == NULL) \ - return -2; \ - \ - fail_stack.size = INIT_FAILURE_ALLOC; \ - fail_stack.avail = 0; \ - } while (0) - - -/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. - - Return 1 if succeeds, and 0 if either ran out of memory - allocating space for it or it was already too large. - - REGEX_REALLOCATE requires `destination' be declared. */ - -#define DOUBLE_FAIL_STACK(fail_stack) \ - ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ - ? 0 \ - : ((fail_stack).stack = (fail_stack_elt_t *) \ - REGEX_REALLOCATE ((fail_stack).stack, \ - (fail_stack).size * sizeof (fail_stack_elt_t), \ - ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ - \ - (fail_stack).stack == NULL \ - ? 0 \ - : ((fail_stack).size <<= 1, \ - 1))) - - -/* Push PATTERN_OP on FAIL_STACK. - - Return 1 if was able to do so and 0 if ran out of memory allocating - space to do so. */ -#define PUSH_PATTERN_OP(pattern_op, fail_stack) \ - ((FAIL_STACK_FULL () \ - && !DOUBLE_FAIL_STACK (fail_stack)) \ - ? 0 \ - : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ - 1)) - -/* This pushes an item onto the failure stack. Must be a four-byte - value. Assumes the variable `fail_stack'. Probably should only - be called from within `PUSH_FAILURE_POINT'. */ -#define PUSH_FAILURE_ITEM(item) \ - fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item - -/* The complement operation. Assumes `fail_stack' is nonempty. */ -#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] - -/* Used to omit pushing failure point id's when we're not debugging. */ -#ifdef DEBUG -#define DEBUG_PUSH PUSH_FAILURE_ITEM -#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () -#else -#define DEBUG_PUSH(item) -#define DEBUG_POP(item_addr) -#endif - - -/* Push the information about the state we will need - if we ever fail back to it. - - Requires variables fail_stack, regstart, regend, reg_info, and - num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be - declared. - - Does `return FAILURE_CODE' if runs out of memory. */ - -#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ - do { \ - char *destination; \ - /* Must be int, so when we don't save any registers, the arithmetic \ - of 0 + -1 isn't done as unsigned. */ \ - int this_reg; \ - \ - DEBUG_STATEMENT (failure_id++); \ - DEBUG_STATEMENT (nfailure_points_pushed++); \ - DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ - DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ - DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ - \ - DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ - DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ - \ - /* Ensure we have enough space allocated for what we will push. */ \ - while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ - { \ - if (!DOUBLE_FAIL_STACK (fail_stack)) \ - return failure_code; \ - \ - DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ - (fail_stack).size); \ - DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ - } \ - \ - /* Push the info, starting with the registers. */ \ - DEBUG_PRINT1 ("\n"); \ - \ - for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ - this_reg++) \ - { \ - DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ - DEBUG_STATEMENT (num_regs_pushed++); \ - \ - DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ - PUSH_FAILURE_ITEM (regstart[this_reg]); \ - \ - DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ - PUSH_FAILURE_ITEM (regend[this_reg]); \ - \ - DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ - DEBUG_PRINT2 (" match_null=%d", \ - REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ - DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ - DEBUG_PRINT2 (" matched_something=%d", \ - MATCHED_SOMETHING (reg_info[this_reg])); \ - DEBUG_PRINT2 (" ever_matched=%d", \ - EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ - DEBUG_PRINT1 ("\n"); \ - PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ - } \ - \ - DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ - PUSH_FAILURE_ITEM (lowest_active_reg); \ - \ - DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ - PUSH_FAILURE_ITEM (highest_active_reg); \ - \ - DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ - PUSH_FAILURE_ITEM (pattern_place); \ - \ - DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ - DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ - size2); \ - DEBUG_PRINT1 ("'\n"); \ - PUSH_FAILURE_ITEM (string_place); \ - \ - DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ - DEBUG_PUSH (failure_id); \ - } while (0) - -/* This is the number of items that are pushed and popped on the stack - for each register. */ -#define NUM_REG_ITEMS 3 - -/* Individual items aside from the registers. */ -#ifdef DEBUG -#define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ -#else -#define NUM_NONREG_ITEMS 4 -#endif - -/* We push at most this many items on the stack. */ -#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) - -/* We actually push this many items. */ -#define NUM_FAILURE_ITEMS \ - ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ - + NUM_NONREG_ITEMS) - -/* How many items can still be added to the stack without overflowing it. */ -#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) - - -/* Pops what PUSH_FAIL_STACK pushes. - - We restore into the parameters, all of which should be lvalues: - STR -- the saved data position. - PAT -- the saved pattern position. - LOW_REG, HIGH_REG -- the highest and lowest active registers. - REGSTART, REGEND -- arrays of string positions. - REG_INFO -- array of information about each subexpression. - - Also assumes the variables `fail_stack' and (if debugging), `bufp', - `pend', `string1', `size1', `string2', and `size2'. */ - -#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ -{ \ - DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ - int this_reg; \ - const unsigned char *string_temp; \ - \ - assert (!FAIL_STACK_EMPTY ()); \ - \ - /* Remove failure points and point to how many regs pushed. */ \ - DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ - DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ - DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ - \ - assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ - \ - DEBUG_POP (&failure_id); \ - DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ - \ - /* If the saved string location is NULL, it came from an \ - on_failure_keep_string_jump opcode, and we want to throw away the \ - saved NULL, thus retaining our current position in the string. */ \ - string_temp = POP_FAILURE_ITEM (); \ - if (string_temp != NULL) \ - str = (const char *) string_temp; \ - \ - DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ - DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ - DEBUG_PRINT1 ("'\n"); \ - \ - pat = (unsigned char *) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ - DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ - \ - /* Restore register info. */ \ - high_reg = (unsigned) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ - \ - low_reg = (unsigned) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ - \ - for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ - { \ - DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ - \ - reg_info[this_reg].word = POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ - \ - regend[this_reg] = (const char *) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ - \ - regstart[this_reg] = (const char *) POP_FAILURE_ITEM (); \ - DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ - } \ - \ - DEBUG_STATEMENT (nfailure_points_popped++); \ -} /* POP_FAILURE_POINT */ - /* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible characters can start a string that matches the pattern. This fastmap @@ -2567,7 +2721,9 @@ re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { int j, k; +#ifdef MATCH_MAY_ALLOCATE fail_stack_type fail_stack; +#endif #ifndef REGEX_MALLOC char *destination; #endif @@ -2577,7 +2733,7 @@ re_compile_fastmap (bufp) register char *fastmap = bufp->fastmap; unsigned char *pattern = bufp->buffer; unsigned long size = bufp->used; - const unsigned char *p = pattern; + unsigned char *p = pattern; register unsigned char *pend = pattern + size; /* Assume that each path through the pattern can be null until @@ -3030,64 +3186,12 @@ static boolean alt_match_null_string_p (), common_op_match_null_string_p (), group_match_null_string_p (); -/* Structure for per-register (a.k.a. per-group) information. - This must not be longer than one word, because we push this value - onto the failure stack. Other register information, such as the - starting and ending positions (which are addresses), and the list of - inner groups (which is a bits list) are maintained in separate - variables. - - We are making a (strictly speaking) nonportable assumption here: that - the compiler will pack our bit fields into something that fits into - the type of `word', i.e., is something that fits into one item on the - failure stack. */ -typedef union -{ - fail_stack_elt_t word; - struct - { - /* This field is one if this group can match the empty string, - zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ -#define MATCH_NULL_UNSET_VALUE 3 - unsigned match_null_string_p : 2; - unsigned is_active : 1; - unsigned matched_something : 1; - unsigned ever_matched_something : 1; - } bits; -} register_info_type; - -#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) -#define IS_ACTIVE(R) ((R).bits.is_active) -#define MATCHED_SOMETHING(R) ((R).bits.matched_something) -#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) - - -/* Call this when have matched a real character; it sets `matched' flags - for the subexpressions which we are currently inside. Also records - that those subexprs have matched. */ -#define SET_REGS_MATCHED() \ - do \ - { \ - unsigned r; \ - for (r = lowest_active_reg; r <= highest_active_reg; r++) \ - { \ - MATCHED_SOMETHING (reg_info[r]) \ - = EVER_MATCHED_SOMETHING (reg_info[r]) \ - = 1; \ - } \ - } \ - while (0) - - /* This converts PTR, a pointer into one of the search strings `string1' and `string2' into an offset from the beginning of that string. */ -#define POINTER_TO_OFFSET(ptr) \ - (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1) - -/* Registers are set to a sentinel when they haven't yet matched. */ -#define REG_UNSET_VALUE ((char *) -1) -#define REG_UNSET(e) ((e) == REG_UNSET_VALUE) - +#define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t) ((ptr) - string1)) \ + : ((regoff_t) ((ptr) - string2 + size1))) /* Macros for dealing with the split strings in re_match_2. */ @@ -3130,6 +3234,7 @@ typedef union /* Free everything we malloc. */ +#ifdef MATCH_MAY_ALLOCATE #ifdef REGEX_MALLOC #define FREE_VAR(var) if (var) free (var); var = NULL #define FREE_VARIABLES() \ @@ -3149,7 +3254,9 @@ typedef union /* Some MIPS systems (at least) want this to free alloca'd storage. */ #define FREE_VARIABLES() alloca (0) #endif /* not REGEX_MALLOC */ - +#else +#define FREE_VARIABLES() /* Do nothing! */ +#endif /* not MATCH_MAY_ALLOCATE */ /* These values must meet several constraints. They must not be valid register values; since we have a limit of 255 registers (because @@ -3230,7 +3337,9 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) scanning the strings. If the latter is zero, the failure point is a ``dummy''; if a failure happens and the failure point is a dummy, it gets discarded and the next next one is tried. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ fail_stack_type fail_stack; +#endif #ifdef DEBUG static unsigned failure_id = 0; unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; @@ -3252,14 +3361,18 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) matching and the regnum-th regend points to right after where we stopped matching the regnum-th subexpression. (The zeroth register keeps track of what the whole pattern matches.) */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **regstart, **regend; +#endif /* If a group that's operated upon by a repetition operator fails to match anything, then the register for its start will need to be restored because it will have been set to wherever in the string we are when we last see its open-group operator. Similarly for a register's end. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **old_regstart, **old_regend; +#endif /* The is_active field of reg_info helps us keep track of which (possibly nested) subexpressions we are currently in. The matched_something @@ -3267,14 +3380,18 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) matched any of the pattern so far this time through the reg_num-th subexpression. These two fields get reset each time through any loop their register is in. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ register_info_type *reg_info; +#endif /* The following record the register info as found in the above variables when we find a match better than any we've seen before. This happens as we backtrack through the failure points, which in turn happens only if we have not yet matched the entire string. */ unsigned best_regs_set = false; +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **best_regstart, **best_regend; +#endif /* Logically, this is `best_regend[0]'. But we don't want to have to allocate space for that if we're not allocating space for anything @@ -3287,8 +3404,10 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) const char *match_end = NULL; /* Used when we pop values we don't care about. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ const char **reg_dummy; register_info_type *reg_info_dummy; +#endif #ifdef DEBUG /* Counts the total number of registers pushed. */ @@ -3299,6 +3418,7 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) INIT_FAIL_STACK (); +#ifdef MATCH_MAY_ALLOCATE /* Do not bother to initialize all the register variables if there are no groups in the pattern, as it takes a fair amount of time. If there are groups, we include space for register 0 (the whole @@ -3323,7 +3443,7 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) return -2; } } -#ifdef REGEX_MALLOC +#if defined (REGEX_MALLOC) else { /* We must initialize all our variables to NULL, so that @@ -3333,6 +3453,7 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) reg_info = reg_info_dummy = (register_info_type *) NULL; } #endif /* REGEX_MALLOC */ +#endif /* MATCH_MAY_ALLOCATE */ /* The starting position is bogus. */ if (pos < 0 || pos > size1 + size2) @@ -3509,8 +3630,9 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) if (regs->num_regs > 0) { regs->start[0] = pos; - regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1 - : d - string2 + size1); + regs->end[0] = (MATCHING_IN_FIRST_STRING + ? ((regoff_t) (d - string1)) + : ((regoff_t) (d - string2 + size1))); } /* Go through the first `min (num_regs, regs->num_regs)' @@ -3521,8 +3643,10 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) regs->start[mcnt] = regs->end[mcnt] = -1; else { - regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); - regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); + regs->start[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); } } @@ -4031,11 +4155,27 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) detect that here, the alternative has put on a dummy failure point which is what we will end up popping. */ - /* Skip over open/close-group commands. */ - while (p2 + 2 < pend - && ((re_opcode_t) *p2 == stop_memory - || (re_opcode_t) *p2 == start_memory)) - p2 += 3; /* Skip over args, too. */ + /* Skip over open/close-group commands. + If what follows this loop is a ...+ construct, + look at what begins its body, since we will have to + match at least one of that. */ + while (1) + { + if (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; + else if (p2 + 6 < pend + && (re_opcode_t) *p2 == dummy_failure_jump) + p2 += 6; + else + break; + } + + p1 = p + mcnt; + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ /* If we're at the end of the pattern, we can change. */ if (p2 == pend) @@ -4053,11 +4193,7 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) { register unsigned char c = *p2 == (unsigned char) endline ? '\n' : p2[2]; - p1 = p + mcnt; - /* p1[0] ... p1[2] are the `on_failure_jump' corresponding - to the `maybe_finalize_jump' of this case. Examine what - follows. */ if ((re_opcode_t) p1[3] == exactn && p1[5] != c) { p[-3] = (unsigned char) pop_failure_jump; @@ -4083,6 +4219,54 @@ re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) } } } + else if ((re_opcode_t) *p2 == charset) + { + register unsigned char c + = *p2 == (unsigned char) endline ? '\n' : p2[2]; + + if ((re_opcode_t) p1[3] == exactn + && ! (p2[1] * BYTEWIDTH > p1[4] + && (p2[1 + p1[4] / BYTEWIDTH] + & (1 << (p1[4] % BYTEWIDTH))))) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + c, p1[5]); + } + + else if ((re_opcode_t) p1[3] == charset_not) + { + int idx; + /* We win if the charset_not inside the loop + lists every character listed in the charset after. */ + for (idx = 0; idx < p2[1]; idx++) + if (! (p2[2 + idx] == 0 + || (idx < p1[4] + && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) + break; + + if (idx == p2[1]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + else if ((re_opcode_t) p1[3] == charset) + { + int idx; + /* We win if the charset inside the loop + has no overlap with the one after the loop. */ + for (idx = 0; idx < p2[1] && idx < p1[4]; idx++) + if ((p2[2 + idx] & p1[5 + idx]) != 0) + break; + + if (idx == p2[1] || idx == p1[4]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } } p -= 2; /* Point at relative address again. */ if ((re_opcode_t) p[-1] != pop_failure_jump) diff --git a/gnu/usr.bin/diff/regex.h b/gnu/usr.bin/diff/regex.h index 408dd21..a495005 100644 --- a/gnu/usr.bin/diff/regex.h +++ b/gnu/usr.bin/diff/regex.h @@ -1,7 +1,7 @@ /* Definitions for data structures and routines for the regular expression library, version 0.12. - Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1985, 89, 90, 91, 92, 1993 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 diff --git a/gnu/usr.bin/diff/sdiff.c b/gnu/usr.bin/diff/sdiff.c index b64f1d0..783f101 100644 --- a/gnu/usr.bin/diff/sdiff.c +++ b/gnu/usr.bin/diff/sdiff.c @@ -1,5 +1,5 @@ /* SDIFF -- interactive merge front end to diff - Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1992, 1993 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -21,6 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "system.h" #include <stdio.h> +#include <ctype.h> #include <signal.h> #include "getopt.h" @@ -33,25 +34,22 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #endif /* Users' editor of nonchoice */ -#ifndef DEFAULT_EDITOR_PROGRAM -#define DEFAULT_EDITOR_PROGRAM "ed" +#ifndef DEFAULT_EDITOR +#define DEFAULT_EDITOR "ed" #endif extern char version_string[]; -static char const *program_name; +static char const *prog; static char const *diffbin = DIFF_PROGRAM; -static char const *edbin = DEFAULT_EDITOR_PROGRAM; -static char const **diffargv; +static char const *edbin = DEFAULT_EDITOR; static char *tmpname; static int volatile tmpmade; - -#if HAVE_FORK static pid_t volatile diffpid; -#endif struct line_filter; +static FILE *ck_fdopen PARAMS((int, char const *)); static FILE *ck_fopen PARAMS((char const *, char const *)); static RETSIGTYPE catchsig PARAMS((int)); static VOID *xmalloc PARAMS((size_t)); @@ -68,7 +66,7 @@ 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 execdiff PARAMS((int, char const *, char const *, char const *)); static void exiterr PARAMS((void)); static void fatal PARAMS((char const *)); static void flush_line PARAMS((void)); @@ -78,24 +76,14 @@ 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 void usage PARAMS((int)); /* this lossage until the gnu libc conquers the universe */ -#if HAVE_TMPNAM -#define private_tempnam() tmpnam ((char *) 0) -#else -#ifndef PVT_tmpdir #define PVT_tmpdir "/tmp" -#endif -#ifndef TMPDIR_ENV -#define TMPDIR_ENV "TMPDIR" -#endif -static char *private_tempnam PARAMS((void)); -static int exists PARAMS((char const *)); -#endif +static char *private_tempnam PARAMS((char const *, char const *, int, size_t *)); static int diraccess PARAMS((char const *)); +static int exists PARAMS((char const *)); /* Options: */ @@ -125,52 +113,27 @@ static struct option const longopts[] = {0, 0, 0, 0} }; +/* prints usage message and quits */ static void -try_help (reason) - char const *reason; +usage (status) + int status; { - 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"); + printf ("Usage: %s [options] from-file to-file\n", prog); + printf ("Options:\n\ + [-abBdHilstv] [-I regexp] [-o outfile] [-w columns]\n\ + [--expand-tabs] [--help] [--ignore-all-space] [--ignore-blank-lines]\n\ + [--ignore-case] [--ignore-matching-lines=regexp]\n\ + [--ignore-space-change] [--left-column] [--minimal]\n\ + [--output=outfile] [--speed-large-files] [--suppress-common-lines]\n\ + [--text] [--version] [--width=columns]\n"); + exit (status); } static void cleanup () { -#if HAVE_FORK if (0 < diffpid) kill (diffpid, SIGPIPE); -#endif if (tmpmade) unlink (tmpname); } @@ -188,7 +151,7 @@ static void fatal (msg) char const *msg; { - fprintf (stderr, "%s: %s\n", program_name, msg); + fprintf (stderr, "%s: %s\n", prog, msg); exiterr (); } @@ -198,7 +161,7 @@ perror_fatal (msg) { int e = errno; checksigs (); - fprintf (stderr, "%s: ", program_name); + fprintf (stderr, "%s: ", prog); errno = e; perror (msg); exiterr (); @@ -226,6 +189,18 @@ ck_fopen (fname, type) return r; } + +static FILE * +ck_fdopen (fd, type) + int fd; + char const *type; +{ + FILE *r = fdopen (fd, type); + if (!r) + perror_fatal ("fdopen"); + return r; +} + static void ck_fclose (f) FILE *f; @@ -264,21 +239,67 @@ ck_fflush (f) perror_fatal ("output error"); } +#if !HAVE_MEMCHR +char * +memchr (s, c, n) + char const *s; + int c; + size_t n; +{ + unsigned char const *p = (unsigned char const *) s, *lim = p + n; + for (; p < lim; p++) + if (*p == c) + return (char *) p; + return 0; +} +#endif + +#ifndef HAVE_WAITPID +/* Emulate waitpid well enough for sdiff, which has at most two children. */ +static pid_t +waitpid (pid, stat_loc, options) + pid_t pid; + int *stat_loc; + int options; +{ + static int ostatus; + static pid_t opid; + int npid, status; + + if (pid == opid) + { + opid = 0; + status = ostatus; + } + else + while ((npid = wait (&status)) != pid) + { + if (npid < 0) + return npid; + opid = npid; + ostatus = status; + } + *stat_loc = status; + return pid; +} +#endif + static char const * -expand_name (name, is_dir, other_name) +expand_name (name, isdir, other_name) char *name; - int is_dir; + int isdir; char const *other_name; { if (strcmp (name, "-") == 0) fatal ("cannot interactively merge standard input"); - if (!is_dir) + if (!isdir) 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; + char const + *p = strrchr (other_name, '/'), + *base = p ? p+1 : other_name; size_t namelen = strlen (name), baselen = strlen (base); char *r = xmalloc (namelen + baselen + 2); memcpy (r, name, namelen); @@ -409,16 +430,12 @@ main (argc, argv) char *argv[]; { int opt; - char *editor; - char *differ; - - initialize_main (&argc, &argv); - program_name = argv[0]; + char *editor = getenv ("EDITOR"); + char *differ = getenv ("DIFF"); - editor = getenv ("EDITOR"); + prog = argv[0]; if (editor) edbin = editor; - differ = getenv ("DIFF"); if (differ) diffbin = differ; @@ -476,7 +493,7 @@ main (argc, argv) break; case 'v': - printf ("sdiff - GNU diffutils version %s\n", version_string); + printf ("GNU sdiff version %s\n", version_string); exit (0); case 'w': @@ -489,35 +506,25 @@ main (argc, argv) break; case 129: - usage (); - if (ferror (stdout) || fclose (stdout) != 0) - fatal ("write error"); - exit (0); + usage (0); default: - try_help (0); + usage (2); } } if (argc - optind != 2) - try_help (argc - optind < 2 ? "missing operand" : "extra operand"); + usage (2); 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 (); - } + /* easy case: diff does everything for us */ + execdiff (suppress_common_flag, "-y", argv[optind], argv[optind + 1]); else { FILE *left, *right, *out, *diffout; + int diff_fds[2]; int interact_ok; + pid_t pid; struct line_filter lfilt; struct line_filter rfilt; struct line_filter diff_filt; @@ -532,66 +539,33 @@ main (argc, argv) 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); + if (pipe (diff_fds)) + perror_fatal ("pipe"); 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]; + diffpid = pid = vfork (); - if (pipe (diff_fds) != 0) - perror_fatal ("pipe"); + if (pid == 0) + { + signal (SIGINT, SIG_IGN); /* in case user interrupts editor */ + signal (SIGPIPE, SIG_DFL); - 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]); + } - close (diff_fds[0]); - if (diff_fds[1] != STDOUT_FILENO) - { - dup2 (diff_fds[1], STDOUT_FILENO); - close (diff_fds[1]); - } + execdiff (0, "--sdiff-merge-assist", argv[optind], argv[optind + 1]); + } - execdiff (); - } + if (pid < 0) + perror_fatal ("fork failed"); - close (diff_fds[1]); - diffout = fdopen (diff_fds[0], "r"); - if (!diffout) - perror_fatal ("fdopen"); - } -#endif /* HAVE_FORK */ + close (diff_fds[1]); + diffout = ck_fdopen (diff_fds[0], "r"); lf_init (&diff_filt, diffout); lf_init (&lfilt, left); @@ -599,6 +573,7 @@ main (argc, argv) interact_ok = interact (&diff_filt, &lfilt, &rfilt, out); + ck_fclose (diffout); ck_fclose (left); ck_fclose (right); ck_fclose (out); @@ -606,17 +581,12 @@ main (argc, argv) { int wstatus; -#if ! HAVE_FORK - wstatus = pclose (diffout); -#else - ck_fclose (diffout); - while (waitpid (diffpid, &wstatus, 0) < 0) + while (waitpid (pid, &wstatus, 0) < 0) if (errno == EINTR) checksigs (); else perror_fatal ("wait failed"); diffpid = 0; -#endif if (tmpmade) { @@ -638,6 +608,8 @@ main (argc, argv) return 0; /* Fool -Wall . . . */ } +static char const **diffargv; + static void diffarg (a) char const *a; @@ -661,8 +633,18 @@ diffarg (a) } static void -execdiff () +execdiff (differences_only, option, file1, file2) + int differences_only; + char const *option, *file1, *file2; { + if (differences_only) + diffarg ("--suppress-common-lines"); + diffarg (option); + diffarg ("--"); + diffarg (file1); + diffarg (file2); + diffarg (0); + execvp (diffbin, (char **) diffargv); write (STDERR_FILENO, diffbin, strlen (diffbin)); write (STDERR_FILENO, ": not found\n", 12); @@ -752,15 +734,6 @@ trapsigs () 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; } @@ -819,13 +792,8 @@ static int skip_white () { int c; - for (;;) - { - c = getchar (); - if (!ISSPACE (c) || c == '\n') - break; - checksigs (); - } + while (isspace (c = getchar ()) && c != '\n') + checksigs (); if (ferror (stdin)) perror_fatal ("input error"); return c; @@ -935,7 +903,7 @@ edit (left, lenl, right, lenr, outfile) case 'q': return 0; case 'e': - if (! tmpname && ! (tmpname = private_tempnam ())) + if (! tmpname && ! (tmpname = private_tempnam (0, "sdiff", 1, 0))) perror_fatal ("temporary file name"); tmpmade = 1; @@ -956,14 +924,8 @@ edit (left, lenl, right, lenr, outfile) 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; + int wstatus; ignore_SIGINT = 1; checksigs (); @@ -994,9 +956,8 @@ edit (left, lenl, right, lenr, outfile) perror_fatal ("wait failed"); ignore_SIGINT = 0; -#endif /* HAVE_FORK */ - if (wstatus != 0) + if (! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 1)) fatal ("Subsidiary editor failed"); } @@ -1102,79 +1063,131 @@ diraccess (dir) return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode); } -#if ! HAVE_TMPNAM - -/* Return zero if we know that FILE does not exist. */ +/* Return nonzero if FILE exists. */ static int exists (file) char const *file; { struct stat buf; - return stat (file, &buf) == 0 || errno != ENOENT; + return stat (file, &buf) == 0; } /* These are the characters used in temporary filenames. */ static char const letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; -/* Generate a temporary filename and return it (in a newly allocated buffer). - Use the prefix "dif" as in tempnam. - This goes through a cyclic pattern of all possible - filenames consisting of five decimal digits of the current pid and three - of the characters in `letters'. Each potential filename is - tested for an already-existing file of the same name, and no name of an - existing file will be returned. When the cycle reaches its end - return 0. */ +/* Generate a temporary filename. + If DIR_SEARCH is nonzero, DIR and PFX are used as + described for tempnam. If not, a temporary filename + in P_tmpdir with no special prefix is generated. If LENPTR + is not 0, *LENPTR is set the to length (including the + terminating '\0') of the resultant filename, which is returned. + This goes through a cyclic pattern of all possible filenames + consisting of five decimal digits of the current pid and three + of the characters in `letters'. Data for tempnam and tmpnam + is kept separate, but when tempnam is using P_tmpdir and no + prefix (i.e, it is identical to tmpnam), the same data is used. + Each potential filename is tested for an already-existing file of + the same name, and no name of an existing file will be returned. + When the cycle reaches its end (12345ZZZ), 0 is returned. */ + + static char * -private_tempnam () +private_tempnam (dir, pfx, dir_search, lenptr) + char const *dir; + char const *pfx; + int dir_search; + size_t *lenptr; { - char const *dir = getenv (TMPDIR_ENV); static char const tmpdir[] = PVT_tmpdir; - size_t index; - char *buf; + static struct + { + char buf[3]; + char *s; + size_t i; + } infos[2], *info; + static char *buf; + static size_t bufsize = 1; + static pid_t oldpid = 0; pid_t pid = getpid (); - size_t dlen; + register size_t len, plen; - if (!dir) + if (dir_search) + { + register char const *d = getenv ("TMPDIR"); + if (d && !diraccess (d)) + d = 0; + if (!d && dir && diraccess (dir)) + d = dir; + if (!d && diraccess (tmpdir)) + d = tmpdir; + if (!d && diraccess ("/tmp")) + d = "/tmp"; + if (!d) + { + errno = ENOENT; + return 0; + } + dir = d; + } + else dir = tmpdir; - dlen = strlen (dir); + if (pfx && *pfx) + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + else + plen = 0; - /* Remove trailing slashes from the directory name. */ - while (dlen && dir[dlen - 1] == '/') - --dlen; + if (dir != tmpdir && !strcmp (dir, tmpdir)) + dir = tmpdir; + info = &infos[(plen == 0 && dir == tmpdir) ? 1 : 0]; - buf = xmalloc (dlen + 1 + 3 + 5 + 1 + 3 + 1); + if (pid != oldpid) + { + oldpid = pid; + info->buf[0] = info->buf[1] = info->buf[2] = '0'; + info->s = &info->buf[0]; + info->i = 0; + } - sprintf (buf, "%.*s/.", (int) dlen, dir); - if (diraccess (buf)) + len = strlen (dir) + 1 + plen + 8; + if (bufsize <= len) { - for (index = 0; - index < ((sizeof (letters) - 1) * (sizeof (letters) - 1) - * (sizeof (letters) - 1)); - ++index) + do { - /* Construct a file name and see if it already exists. - - We use a single counter in INDEX to cycle each of three - character positions through each of 62 possible letters. */ - - sprintf (buf, "%.*s/dif%.5lu.%c%c%c", (int) dlen, dir, - (unsigned long) pid % 100000, - letters[index % (sizeof (letters) - 1)], - letters[(index / (sizeof (letters) - 1)) - % (sizeof (letters) - 1)], - letters[index / ((sizeof (letters) - 1) * - (sizeof (letters) - 1))]); + bufsize *= 2; + } + while (bufsize <= len); - if (!exists (buf)) - return buf; + if (buf) + free (buf); + buf = xmalloc (bufsize); + } + for (;;) + { + *info->s = letters[info->i]; + sprintf (buf, "%s/%.*s%.5lu%.3s", dir, (int) plen, pfx, + (unsigned long) pid % 100000, info->buf); + if (!exists (buf)) + break; + ++info->i; + if (info->i > sizeof (letters) - 1) + { + info->i = 0; + if (info->s == &info->buf[2]) + { + errno = EEXIST; + return 0; + } + ++info->s; } - errno = EEXIST; } - /* Don't free buf; `free' might change errno. We'll exit soon anyway. */ - return 0; + if (lenptr) + *lenptr = len; + return buf; } - -#endif /* ! HAVE_TMPNAM */ diff --git a/gnu/usr.bin/diff/side.c b/gnu/usr.bin/diff/side.c index a150b5e..59943f2 100644 --- a/gnu/usr.bin/diff/side.c +++ b/gnu/usr.bin/diff/side.c @@ -139,7 +139,7 @@ print_half_line (line, indent, out_bound) break; default: - if (! ISPRINT (c)) + if (! isprint (c)) goto control_char; /* falls through */ case ' ': diff --git a/gnu/usr.bin/diff/system.h b/gnu/usr.bin/diff/system.h index d60af60..2da6247 100644 --- a/gnu/usr.bin/diff/system.h +++ b/gnu/usr.bin/diff/system.h @@ -1,5 +1,5 @@ /* System dependent declarations. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -24,7 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define volatile #endif #endif -#include <config.h> +#include "config.h" #include <sys/types.h> #include <sys/stat.h> @@ -64,6 +64,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) #endif +#ifndef S_IXOTH +#define S_IXOTH 1 +#endif +#ifndef S_IXGRP +#define S_IXGRP (S_IXOTH << 3) +#endif +#ifndef S_IXUSR +#define S_IXUSR (S_IXGRP << 3) +#endif + #if HAVE_UNISTD_H #include <unistd.h> #endif @@ -94,10 +104,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #if HAVE_FCNTL_H #include <fcntl.h> #else -#if HAVE_SYS_FILE_H #include <sys/file.h> #endif -#endif #if !HAVE_DUP2 #define dup2(f,t) (close (t), fcntl (f,F_DUPFD,t)) @@ -108,39 +116,47 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #endif #if HAVE_SYS_WAIT_H +#ifndef _POSIX_VERSION +/* Prevent the NeXT prototype using union wait from causing problems. */ +#define wait system_wait +#endif #include <sys/wait.h> +#ifndef _POSIX_VERSION +#undef wait #endif +#endif /* HAVE_SYS_WAIT_H */ + #ifndef WEXITSTATUS -#define WEXITSTATUS(stat_val) ((unsigned) (stat_val) >> 8) +#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) +#undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */ #endif #ifndef WIFEXITED #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif -#ifndef STAT_BLOCKSIZE #if HAVE_ST_BLKSIZE #define STAT_BLOCKSIZE(s) (s).st_blksize #else #define STAT_BLOCKSIZE(s) (8 * 1024) #endif -#endif -#if HAVE_DIRENT_H -# include <dirent.h> -# define NAMLEN(dirent) strlen((dirent)->d_name) +#if DIRENT || defined (_POSIX_VERSION) +#include <dirent.h> +#else /* ! (DIRENT || defined (_POSIX_VERSION)) */ +#if SYSNDIR +#include <sys/ndir.h> #else -# define dirent direct -# define NAMLEN(dirent) ((dirent)->d_namlen) -# if HAVE_SYS_NDIR_H -# include <sys/ndir.h> -# endif -# if HAVE_SYS_DIR_H -# include <sys/dir.h> -# endif -# if HAVE_NDIR_H -# include <ndir.h> -# endif +#if SYSDIR +#include <sys/dir.h> +#else +#include <ndir.h> +#endif #endif +#ifdef dirent +#undef dirent +#endif +#define dirent direct +#endif /* ! (DIRENT || defined (_POSIX_VERSION)) */ #if HAVE_VFORK_H #include <vfork.h> @@ -166,44 +182,28 @@ char *getenv (); #define CHAR_BIT 8 #endif -#if STDC_HEADERS || HAVE_STRING_H -# include <string.h> -# ifndef bzero -# define bzero(s, n) memset (s, 0, n) -# endif -#else -# if !HAVE_STRCHR -# define strchr index -# define strrchr rindex -# endif -char *strchr (), *strrchr (); -# if !HAVE_MEMCHR -# define memcmp(s1, s2, n) bcmp (s1, s2, n) -# define memcpy(d, s, n) bcopy (s, d, n) -void *memchr (); -# endif +#if HAVE_STRING_H +#include <string.h> +#ifndef bzero +#define bzero(s,n) memset (s,0,n) #endif - -#include <ctype.h> -/* CTYPE_DOMAIN (C) is nonzero if the unsigned char C can safely be given - as an argument to <ctype.h> macros like `isspace'. */ -#if STDC_HEADERS -#define CTYPE_DOMAIN(c) 1 -#else -#define CTYPE_DOMAIN(c) ((unsigned) (c) <= 0177) +#else /* !HAVE_STRING_H */ +#include <strings.h> +#ifndef strchr +#define strchr index #endif -#ifndef ISPRINT -#define ISPRINT(c) (CTYPE_DOMAIN (c) && isprint (c)) +#ifndef strrchr +#define strrchr rindex #endif -#ifndef ISSPACE -#define ISSPACE(c) (CTYPE_DOMAIN (c) && isspace (c)) +#ifndef memcpy +#define memcpy(d,s,n) bcopy (s,d,n) #endif -#ifndef ISUPPER -#define ISUPPER(c) (CTYPE_DOMAIN (c) && isupper (c)) +#ifndef memcmp +#define memcmp(s1,s2,n) bcmp (s1,s2,n) #endif - -#ifndef ISDIGIT -#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) +#endif /* !HAVE_STRING_H */ +#if !HAVE_MEMCHR +char *memchr (); #endif #include <errno.h> @@ -211,57 +211,5 @@ void *memchr (); extern int errno; #endif -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif #define min(a,b) ((a) <= (b) ? (a) : (b)) #define max(a,b) ((a) >= (b) ? (a) : (b)) - -/* This section contains Posix-compliant defaults for macros - that are meant to be overridden by hand in config.h as needed. */ - -#ifndef filename_cmp -#define filename_cmp(a, b) strcmp (a, b) -#endif - -#ifndef filename_lastdirchar -#define filename_lastdirchar(filename) strrchr (filename, '/') -#endif - -#ifndef HAVE_FORK -#define HAVE_FORK 1 -#endif - -#ifndef HAVE_SETMODE -#define HAVE_SETMODE 0 -#endif - -#ifndef initialize_main -#define initialize_main(argcp, argvp) -#endif - -/* Do struct stat *S, *T describe the same file? Answer -1 if unknown. */ -#ifndef same_file -#define same_file(s,t) ((s)->st_ino==(t)->st_ino && (s)->st_dev==(t)->st_dev) -#endif - -/* Place into Q a quoted version of A suitable for `popen' or `system', - incrementing Q and junking A. - Do not increment Q by more than 4 * strlen (A) + 2. */ -#ifndef SYSTEM_QUOTE_ARG -#define SYSTEM_QUOTE_ARG(q, a) \ - { \ - *(q)++ = '\''; \ - for (; *(a); *(q)++ = *(a)++) \ - if (*(a) == '\'') \ - { \ - *(q)++ = '\''; \ - *(q)++ = '\\'; \ - *(q)++ = '\''; \ - } \ - *(q)++ = '\''; \ - } -#endif diff --git a/gnu/usr.bin/diff/util.c b/gnu/usr.bin/diff/util.c index bbc3bff..38e20f4 100644 --- a/gnu/usr.bin/diff/util.c +++ b/gnu/usr.bin/diff/util.c @@ -1,5 +1,5 @@ /* Support routines for GNU DIFF. - Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1989, 1992, 1993 Free Software Foundation, Inc. This file is part of GNU DIFF. @@ -19,10 +19,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #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'. */ @@ -52,7 +48,7 @@ perror_with_name (text) char const *text; { int e = errno; - fprintf (stderr, "%s: ", program_name); + fprintf (stderr, "%s: ", program); errno = e; perror (text); } @@ -65,7 +61,7 @@ pfatal_with_name (text) { int e = errno; print_message_queue (); - fprintf (stderr, "%s: ", program_name); + fprintf (stderr, "%s: ", program); errno = e; perror (text); exit (2); @@ -78,7 +74,7 @@ void error (format, arg, arg1) char const *format, *arg, *arg1; { - fprintf (stderr, "%s: ", program_name); + fprintf (stderr, "%s: ", program); fprintf (stderr, format, arg, arg1); fprintf (stderr, "\n"); } @@ -161,9 +157,7 @@ setup_output (name0, name1, depth) outfile = 0; } -#if HAVE_FORK static pid_t pr_pid; -#endif void begin_output () @@ -176,20 +170,19 @@ begin_output () /* 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. */ + /* Posix.2 section 4.17.6.1.1 specifies this format. But there are some + bugs 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, + and it requires two spaces after "diff" if there are no options. + These requirements are silly and do 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) + /* Fork a `pr' and make OUTFILE a pipe to it. */ + if (pipe (pipes) < 0) pfatal_with_name ("pipe"); fflush (stdout); @@ -208,29 +201,14 @@ begin_output () close (pipes[0]); } - execl (PR_PROGRAM, PR_PROGRAM, "-f", "-h", name, 0); - pfatal_with_name (PR_PROGRAM); + execl (PR_FILE_NAME, PR_FILE_NAME, "-f", "-h", name, 0); + pfatal_with_name (PR_FILE_NAME); } 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 { @@ -274,15 +252,21 @@ finish_output () 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 HAVE_WAITPID if (waitpid (pr_pid, &wstatus, 0) < 0) pfatal_with_name ("waitpid"); -#endif /* HAVE_FORK */ - if (wstatus != 0) +#else + for (;;) { + pid_t w = wait (&wstatus); + if (w < 0) + pfatal_with_name ("wait"); + if (w == pr_pid) + break; + } +#endif + if (! WIFEXITED (wstatus) || WEXITSTATUS (wstatus) != 0) fatal ("subsidiary pr failed"); } @@ -291,44 +275,56 @@ finish_output () /* 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. */ + Return 1 if the lines differ, like `memcmp'. */ int -line_cmp (s1, s2) +line_cmp (s1, len1, s2, len2) char const *s1, *s2; + size_t len1, len2; { - register unsigned char const *t1 = (unsigned char const *) s1; - register unsigned char const *t2 = (unsigned char const *) s2; + register unsigned char const *t1, *t2; + register unsigned char end_char = line_end_char; + + /* Check first for exact identity. + If that is true, return 0 immediately. + This detects the common case of exact identity + faster than complete comparison would. */ - while (1) + if (len1 == len2 && memcmp (s1, s2, len1) == 0) + return 0; + + /* Not exactly identical, but perhaps they match anyway + when case or white space is ignored. */ + + if (ignore_case_flag | ignore_space_change_flag | ignore_all_space_flag) { - register unsigned char c1 = *t1++; - register unsigned char c2 = *t2++; + t1 = (unsigned char const *) s1; + t2 = (unsigned char const *) s2; - /* Test for exact char equality first, since it's a common case. */ - if (c1 != c2) + while (1) { + register unsigned char c1 = *t1++; + register unsigned char c2 = *t2++; + /* 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++; + while (isspace (c1) && c1 != end_char) c1 = *t1++; + while (isspace (c2) && c2 != end_char) 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)) + if (isspace (c1)) { - while (c1 != '\n') + while (c1 != end_char) { c1 = *t1++; - if (! ISSPACE (c1)) + if (! isspace (c1)) { --t1; c1 = ' '; @@ -338,12 +334,12 @@ line_cmp (s1, s2) } /* Likewise for line 2. */ - if (ISSPACE (c2)) + if (isspace (c2)) { - while (c2 != '\n') + while (c2 != end_char) { c2 = *t2++; - if (! ISSPACE (c2)) + if (! isspace (c2)) { --t2; c2 = ' '; @@ -351,44 +347,23 @@ line_cmp (s1, s2) } } } - - 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. */ + /* Upcase all letters if -i is specified. */ if (ignore_case_flag) { - if (ISUPPER (c1)) - c1 = tolower (c1); - if (ISUPPER (c2)) - c2 = tolower (c2); + if (islower (c1)) + c1 = toupper (c1); + if (islower (c2)) + c2 = toupper (c2); } if (c1 != c2) break; + if (c1 == end_char) + return 0; } - if (c1 == '\n') - return 0; } return (1); @@ -479,7 +454,8 @@ print_1_line (line_flag, line) output_1_line (text, limit, flag_format, line_flag); - if ((!line_flag || line_flag[0]) && limit[-1] != '\n') + if ((!line_flag || line_flag[0]) && limit[-1] != '\n' + && line_end_char == '\n') fprintf (out, "\n\\ No newline at end of file\n"); } @@ -529,7 +505,7 @@ output_1_line (text, limit, flag_format, line_flag) break; default: - if (ISPRINT (c)) + if (isprint (c)) column++; putc (c, out); break; @@ -582,7 +558,7 @@ translate_range (file, a, b, aptr, bptr) void print_number_range (sepchar, file, a, b) - int sepchar; + char sepchar; struct file_data *file; int a, b; { @@ -738,8 +714,7 @@ char * dir_file_pathname (dir, file) char const *dir, *file; { - char const *p = filename_lastdirchar (dir); - return concat (dir, "/" + (p && !p[1]), file); + return concat (dir, "/" + (*dir && dir[strlen (dir) - 1] == '/'), file); } void @@ -752,3 +727,18 @@ debug_script (sp) sp->line0, sp->line1, sp->deleted, sp->inserted); fflush (stderr); } + +#if !HAVE_MEMCHR +char * +memchr (s, c, n) + char const *s; + int c; + size_t n; +{ + unsigned char const *p = (unsigned char const *) s, *lim = p + n; + for (; p < lim; p++) + if (*p == c) + return (char *) p; + return 0; +} +#endif diff --git a/gnu/usr.bin/diff/version.c b/gnu/usr.bin/diff/version.c index 0299397..234ec29 100644 --- a/gnu/usr.bin/diff/version.c +++ b/gnu/usr.bin/diff/version.c @@ -1,5 +1,5 @@ /* Version number of GNU diff. */ -#include <config.h> +#include "config.h" -char const version_string[] = "2.7"; +char const version_string[] = "2.6"; |