summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/diff
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1995-10-28 19:11:01 +0000
committerpeter <peter@FreeBSD.org>1995-10-28 19:11:01 +0000
commitc37ff62e9be62a7cd6340caca3316bb40062ac2d (patch)
tree987fcf998a10323a27da08d8512088fb01e8396f /gnu/usr.bin/diff
parent72fa7ec057bc2d7930e60d59f3936afe1de4bc11 (diff)
downloadFreeBSD-src-c37ff62e9be62a7cd6340caca3316bb40062ac2d.zip
FreeBSD-src-c37ff62e9be62a7cd6340caca3316bb40062ac2d.tar.gz
Merge in/out comflicts caused by Diffutils-2.7 import...
In future, it should be as easy as "update -j ....", but this time I had to go over it by hand. Not nice..
Diffstat (limited to 'gnu/usr.bin/diff')
-rw-r--r--gnu/usr.bin/diff/config.h56
-rw-r--r--gnu/usr.bin/diff/context.c12
-rw-r--r--gnu/usr.bin/diff/diff.c213
-rw-r--r--gnu/usr.bin/diff/diff.h16
-rw-r--r--gnu/usr.bin/diff/diff3.c204
-rw-r--r--gnu/usr.bin/diff/dir.c16
-rw-r--r--gnu/usr.bin/diff/fnmatch.c209
-rw-r--r--gnu/usr.bin/diff/getopt.c215
-rw-r--r--gnu/usr.bin/diff/getopt1.c7
-rw-r--r--gnu/usr.bin/diff/ifdef.c22
-rw-r--r--gnu/usr.bin/diff/io.c140
-rw-r--r--gnu/usr.bin/diff/sdiff.c463
-rw-r--r--gnu/usr.bin/diff/side.c2
-rw-r--r--gnu/usr.bin/diff/system.h158
-rw-r--r--gnu/usr.bin/diff/util.c174
-rw-r--r--gnu/usr.bin/diff/version.c2
16 files changed, 978 insertions, 931 deletions
diff --git a/gnu/usr.bin/diff/config.h b/gnu/usr.bin/diff/config.h
index ed8e8ef..3d7e65b 100644
--- a/gnu/usr.bin/diff/config.h
+++ b/gnu/usr.bin/diff/config.h
@@ -1,9 +1,12 @@
/* config.h. Generated automatically by configure. */
-/* config.h.in. Generated automatically from configure.in by autoheader. */
+/* config.hin. 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 */
@@ -11,10 +14,7 @@
This function is required for alloca.c support on those systems. */
/* #undef CRAY_STACKSEG_END */
-/* Define if you have dirent.h. */
-#define DIRENT 1
-
-/* Define if you have alloca.h and it should be used (not Ultrix). */
+/* Define if you have <alloca.h> and it should be used (not on 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,9 +32,6 @@
/* 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 */
@@ -63,32 +60,32 @@
/* Define if you have the ANSI C header files. */
#define STDC_HEADERS 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 if <sys/wait.h> is compatible with Posix applications. */
+#define HAVE_SYS_WAIT_H 1
/* Define vfork as fork if vfork does not work. */
/* #undef vfork */
-/* Define if the closedir function returns void instead of int. */
-/* #undef VOID_CLOSEDIR */
-
-/* Define if you have dup2. */
+/* Define if you have the dup2 function. */
#define HAVE_DUP2 1
-/* Define if you have memchr. */
+/* Define if you have the memchr function. */
#define HAVE_MEMCHR 1
-/* Define if you have sigaction. */
+/* Define if you have the sigaction function. */
#define HAVE_SIGACTION 1
-/* Define if you have strerror. */
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strerror function. */
#define HAVE_STRERROR 1
-/* Define if you have waitpid. */
-#define HAVE_WAITPID 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 the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
@@ -96,14 +93,23 @@
/* 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/wait.h> header file. */
-#define HAVE_SYS_WAIT_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 <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 5b4b73f..14f950c 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, 89, 91, 92, 93 Free Software Foundation, Inc.
+ Copyright (C) 1988,1989,1991,1992,1993,1994 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -45,9 +45,13 @@ print_context_label (mark, inf, label)
if (label)
fprintf (outfile, "%s %s\n", mark, label);
else
- /* 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));
+ {
+ 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);
+ }
}
/* Print a header for a context diff, with the file names and dates. */
diff --git a/gnu/usr.bin/diff/diff.c b/gnu/usr.bin/diff/diff.c
index 6004f84..ab1549b 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 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -22,6 +22,7 @@ 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"
@@ -42,7 +43,9 @@ 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 usage PARAMS((char const *));
+static void try_help PARAMS((char const *));
+static void check_stdout PARAMS((void));
+static void usage PARAMS((void));
/* Nonzero for -r: if comparing two directories,
compare their common subdirectories recursively. */
@@ -53,6 +56,11 @@ 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.
@@ -189,7 +197,6 @@ 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'},
@@ -213,6 +220,7 @@ 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}
};
@@ -225,12 +233,13 @@ main (argc, argv)
int c;
int prev = -1;
int width = DEFAULT_WIDTH;
+ int show_c_function = 0;
/* Do our initializations. */
- program = argv[0];
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
output_style = OUTPUT_NORMAL;
context = -1;
- line_end_char = '\n';
/* Decode the options. */
@@ -270,8 +279,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':
@@ -362,6 +371,7 @@ main (argc, argv)
/* Ignore changes in case. */
ignore_case_flag = 1;
ignore_some_changes = 1;
+ ignore_some_line_changes = 1;
break;
case 'I':
@@ -374,6 +384,14 @@ 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':
@@ -400,7 +418,7 @@ main (argc, argv)
case 'p':
/* Make context-style output and show name of last C function. */
- specify_style (OUTPUT_CONTEXT);
+ show_c_function = 1;
add_regexp (&function_regexp_list, "^[_a-zA-Z$]");
break;
@@ -451,14 +469,14 @@ main (argc, argv)
break;
case 'v':
- printf ("GNU diff version %s\n", version_string);
+ printf ("diff - GNU diffutils version %s\n", version_string);
exit (0);
case 'w':
/* Ignore horizontal white space when comparing lines. */
ignore_all_space_flag = 1;
ignore_some_changes = 1;
- length_varies = 1;
+ ignore_some_line_changes = 1;
break;
case 'x':
@@ -529,16 +547,27 @@ main (argc, argv)
break;
case 141:
- usage (0);
+ usage ();
+ check_stdout ();
+ exit (0);
+
+ case 142:
+ /* Use binary I/O when reading and writing data.
+ On Posix hosts, this has no effect. */
+#if HAVE_SETMODE
+ binary_I_O = 1;
+ setmode (STDOUT_FILENO, O_BINARY);
+#endif
+ break;
default:
- usage ("");
+ try_help (0);
}
prev = c;
}
- if (optind != argc - 2)
- usage (optind < argc - 2 ? "extra operand" : "missing operand");
+ if (argc - optind != 2)
+ try_help (argc - optind < 2 ? "missing operand" : "extra operand");
{
@@ -558,6 +587,9 @@ 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)
@@ -566,6 +598,10 @@ 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])
@@ -597,8 +633,7 @@ main (argc, argv)
/* Print any messages that were saved up for last. */
print_message_queue ();
- if (ferror (stdout) || fclose (stdout) != 0)
- fatal ("write error");
+ check_stdout ();
exit (val);
return val;
}
@@ -626,37 +661,96 @@ add_regexp (reglist, pattern)
}
static void
-usage (reason)
+try_help (reason)
char const *reason;
{
- 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);
+ if (reason)
+ error ("%s", reason, 0);
+ error ("Try `%s --help' for more information.", program_name, 0);
+ exit (2);
+}
+
+static void
+check_stdout ()
+{
+ if (ferror (stdout) || fclose (stdout) != 0)
+ fatal ("write error");
+}
+
+static char const * const option_help[] = {
+"-i --ignore-case Consider upper- and lower-case to be the same.",
+"-w --ignore-all-space Ignore all white space.",
+"-b --ignore-space-change Ignore changes in the amount of white space.",
+"-B --ignore-blank-lines Ignore changes whose lines are all blank.",
+"-I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.",
+#if HAVE_SETMODE
+"--binary Read and write data in binary mode.",
+#endif
+"-a --text Treat all files as text.\n",
+"-c -C NUM --context[=NUM] Output NUM (default 2) lines of copied context.",
+"-u -U NUM --unified[=NUM] Output NUM (default 2) lines of unified context.",
+" -NUM Use NUM context lines.",
+" -L LABEL --label LABEL Use LABEL instead of file name.",
+" -p --show-c-function Show which C function each change is in.",
+" -F RE --show-function-line=RE Show the most recent line matching RE.",
+"-q --brief Output only whether files differ.",
+"-e --ed Output an ed script.",
+"-n --rcs Output an RCS format diff.",
+"-y --side-by-side Output in two columns.",
+" -w NUM --width=NUM Output at most NUM (default 130) characters per line.",
+" --left-column Output only the left column of common lines.",
+" --suppress-common-lines Do not output common lines.",
+"-DNAME --ifdef=NAME Output merged file to show `#ifdef NAME' diffs.",
+"--GTYPE-group-format=GFMT Similar, but format GTYPE input groups with GFMT.",
+"--line-format=LFMT Similar, but format all input lines with LFMT.",
+"--LTYPE-line-format=LFMT Similar, but format LTYPE input lines with LFMT.",
+" LTYPE is `old', `new', or `unchanged'. GTYPE is LTYPE or `changed'.",
+" GFMT may contain:",
+" %< lines from FILE1",
+" %> lines from FILE2",
+" %= lines common to FILE1 and FILE2",
+" %[-][WIDTH][.[PREC]]{doxX}LETTER printf-style spec for LETTER",
+" LETTERs are as follows for new group, lower case for old group:",
+" F first line number",
+" L last line number",
+" N number of lines = L-F+1",
+" E F-1",
+" M L+1",
+" LFMT may contain:",
+" %L contents of line",
+" %l contents of line, excluding any trailing newline",
+" %[-][WIDTH][.[PREC]]{doxX}n printf-style spec for input line number",
+" Either GFMT or LFMT may contain:",
+" %% %",
+" %c'C' the single character C",
+" %c'\\OOO' the character with octal code OOO\n",
+"-l --paginate Pass the output through `pr' to paginate it.",
+"-t --expand-tabs Expand tabs to spaces in output.",
+"-T --initial-tab Make tabs line up by prepending a tab.\n",
+"-r --recursive Recursively compare any subdirectories found.",
+"-N --new-file Treat absent files as empty.",
+"-P --unidirectional-new-file Treat absent first files as empty.",
+"-s --report-identical-files Report when two files are the same.",
+"-x PAT --exclude=PAT Exclude files that match PAT.",
+"-X FILE --exclude-from=FILE Exclude files that match any pattern in FILE.",
+"-S FILE --starting-file=FILE Start with FILE when comparing directories.\n",
+"--horizon-lines=NUM Keep NUM lines of the common prefix and suffix.",
+"-d --minimal Try hard to find a smaller set of changes.",
+"-H --speed-large-files Assume large files and many scattered small changes.\n",
+"-v --version Output version info.",
+"--help Output this help.",
+0
+};
+
+static void
+usage ()
+{
+ char const * const *p;
+
+ printf ("Usage: %s [OPTION]... FILE1 FILE2\n\n", program_name);
+ for (p = option_help; *p; p++)
+ printf (" %s\n", *p);
+ printf ("\nIf FILE1 or FILE2 is `-', read standard input.\n");
}
static int
@@ -710,8 +804,19 @@ 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 `stat'. */
+ /* S_ISLNK is impossible with `fstat' and `stat'. */
#ifdef S_ISSOCK
if (S_ISSOCK (st->st_mode)) return "socket";
#endif
@@ -781,7 +886,7 @@ compare_files (dir0, name0, dir1, name1, depth)
{
int stat_result;
- if (i && strcmp (inf[i].name, inf[0].name) == 0)
+ if (i && filename_cmp (inf[i].name, inf[0].name) == 0)
{
inf[i].stat = inf[0].stat;
stat_result = 0;
@@ -835,7 +940,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 = strrchr (fnm, '/');
+ char const *p = filename_lastdirchar (fnm);
char const *filename = inf[dir_arg].name
= dir_file_pathname (dir, p ? p + 1 : fnm);
@@ -859,11 +964,8 @@ compare_files (dir0, name0, dir1, name1, depth)
val = 2;
}
- 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)
+ else if ((same_files = inf[0].desc != -1 && inf[1].desc != -1
+ && 0 < same_file (&inf[0].stat, &inf[1].stat))
&& no_diff_means_no_output)
{
/* The two named files are actually the same physical file.
@@ -957,6 +1059,13 @@ 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 9d51ffc..7a0644d 100644
--- a/gnu/usr.bin/diff/diff.h
+++ b/gnu/usr.bin/diff/diff.h
@@ -18,14 +18,9 @@ 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 "gnuregex.h"
-#ifndef PR_FILE_NAME
-#define PR_FILE_NAME "/bin/pr"
-#endif
-
#define TAB_WIDTH 8
/* Variables for command line options */
@@ -84,9 +79,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 lengths are different.
+/* 1 if lines may match even if their contents do not match exactly.
This depends on various options. */
-EXTERN int length_varies;
+EXTERN int ignore_some_line_changes;
/* 1 if files may match even if their contents are not byte-for-byte identical.
This depends on various options. */
@@ -117,9 +112,6 @@ 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;
@@ -184,7 +176,7 @@ EXTERN char * switch_string;
EXTERN int heuristic;
/* Name of program the user invoked (for error messages). */
-EXTERN char * program;
+EXTERN char *program_name;
/* The result of comparison is an "edit script": a chain of `struct change'.
Each `struct change' represents one place where some lines are deleted
@@ -322,7 +314,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 *, size_t, char const *, size_t));
+int line_cmp PARAMS((char const *, char const *));
int translate_line_number PARAMS((struct file_data const *, int));
struct change *find_change PARAMS((struct change *));
struct change *find_reverse_change PARAMS((struct change *));
diff --git a/gnu/usr.bin/diff/diff3.c b/gnu/usr.bin/diff/diff3.c
index 50cb88d..5d94ab8 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 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994 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 <ctype.h>
+#include <signal.h>
#include "getopt.h"
extern char const version_string[];
@@ -163,9 +163,7 @@ static int simple_only;
/* If nonzero, do not output information for non-overlapping diffs. */
static int overlap_only;
-/* 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) */
+/* If nonzero, show information for DIFF_2ND diffs. */
static int show_2nd;
/* If nonzero, include `:wq' at the end of the script
@@ -175,7 +173,7 @@ static int finalwrite;
/* If nonzero, output a merged file. */
static int merge;
-static char *argv0;
+static char *program_name;
static VOID *xmalloc PARAMS((size_t));
static VOID *xrealloc PARAMS((VOID *, size_t));
@@ -194,11 +192,13 @@ 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((int));
+static void usage PARAMS((void));
static char const diff_program[] = DIFF_PROGRAM;
@@ -206,7 +206,6 @@ 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'},
@@ -231,7 +230,7 @@ main (argc, argv)
int c, i;
int mapping[3];
int rev_mapping[3];
- int incompat;
+ int incompat = 0;
int conflicts_found;
struct diff_block *thread0, *thread1, *last_block;
struct diff3_block *diff3;
@@ -241,22 +240,18 @@ main (argc, argv)
char **file;
struct stat statb;
- incompat = 0;
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
- argv0 = argv[0];
-
- while ((c = getopt_long (argc, argv, "aeimvx3ABEL:TX", longopts, 0)) != EOF)
+ while ((c = getopt_long (argc, argv, "aeimvx3AEL:TX", longopts, 0)) != EOF)
{
switch (c)
{
case 'a':
always_text = 1;
break;
- case 'B':
- ++show_2nd;
- /* Falls through */
case 'A':
- ++show_2nd;
+ show_2nd = 1;
flagging = 1;
incompat++;
break;
@@ -287,10 +282,12 @@ main (argc, argv)
tab_align_flag = 1;
break;
case 'v':
- printf ("GNU diff3 version %s\n", version_string);
+ printf ("diff3 - GNU diffutils version %s\n", version_string);
exit (0);
case 129:
- usage (0);
+ usage ();
+ check_stdout ();
+ exit (0);
case 'L':
/* Handle up to three -L options. */
if (tag_count < 3)
@@ -298,9 +295,9 @@ main (argc, argv)
tag_strings[tag_count++] = optarg;
break;
}
- /* Falls through */
+ try_help ("Too many labels were given. The limit is 3.");
default:
- usage (2);
+ try_help (0);
}
}
@@ -310,9 +307,11 @@ 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. */
- || argc - optind != 3)
- usage (2);
+ || (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");
file = &argv[optind];
@@ -355,11 +354,20 @@ main (argc, argv)
perror_with_exit (file[i]);
else if (S_ISDIR(statb.st_mode))
{
- fprintf (stderr, "%s: %s: Is a directory\n", argv0, file[i]);
+ fprintf (stderr, "%s: %s: Is a directory\n",
+ program_name, 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)
@@ -390,30 +398,54 @@ main (argc, argv)
conflicts_found = 0;
}
- if (ferror (stdout) || fclose (stdout) != 0)
- fatal ("write error");
+ 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");
+}
+
/*
- * Explain, patiently and kindly, how to use this program. Then exit.
+ * Explain, patiently and kindly, how to use this program.
*/
static void
-usage (status)
- int status;
+usage ()
{
- 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);
+ 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");
}
/*
@@ -903,8 +935,6 @@ 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;
@@ -931,7 +961,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: ", argv0);
+ fprintf (stderr, "%s: diff error: ", program_name);
do
{
putc (*scan_diff, stderr);
@@ -1039,9 +1069,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);
@@ -1103,12 +1133,20 @@ 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[256];
+ char horizon_arg[17 + INT_STRLEN_BOUND (int)];
char const **ap;
int fds[2];
pid_t pid;
- int wstatus;
ap = argv;
*ap++ = diff_program;
@@ -1121,8 +1159,8 @@ read_diff (filea, fileb, output_placement)
*ap++ = fileb;
*ap = 0;
- if (pipe (fds) < 0)
- perror_with_exit ("pipe failed");
+ if (pipe (fds) != 0)
+ perror_with_exit ("pipe");
pid = vfork ();
if (pid == 0)
@@ -1145,11 +1183,37 @@ read_diff (filea, fileb, output_placement)
perror_with_exit ("fork failed");
close (fds[1]); /* Prevent erroneous lack of EOF */
- current_chunk_size = DIFF_CHUNK_SIZE;
+ 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));
+
diff_result = xmalloc (current_chunk_size);
total = 0;
do {
- bytes = myread (fds[0],
+ bytes = myread (fd,
diff_result + total,
current_chunk_size - total);
total += bytes;
@@ -1170,18 +1234,18 @@ read_diff (filea, fileb, output_placement)
*output_placement = diff_result;
-#if HAVE_WAITPID
+#if ! HAVE_FORK
+
+ wstatus = pclose (fpipe);
+
+#else /* HAVE_FORK */
+
+ if (close (fd) != 0)
+ perror_with_exit ("pipe close");
if (waitpid (pid, &wstatus, 0) < 0)
perror_with_exit ("waitpid failed");
-#else
- for (;;) {
- pid_t w = wait (&wstatus);
- if (w < 0)
- perror_with_exit ("wait failed");
- if (w == pid)
- break;
- }
-#endif
+
+#endif /* HAVE_FORK */
if (! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 2))
fatal ("subsidiary diff failed");
@@ -1198,15 +1262,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, firstchar)
+scan_diff_line (scan_ptr, set_start, set_length, limit, leadingchar)
char *scan_ptr, **set_start;
size_t *set_length;
char *limit;
- char firstchar;
+ int leadingchar;
{
char *line_ptr;
- if (!(scan_ptr[0] == (firstchar)
+ if (!(scan_ptr[0] == leadingchar
&& scan_ptr[1] == ' '))
fatal ("invalid diff format; incorrect leading line chars");
@@ -1223,7 +1287,7 @@ scan_diff_line (scan_ptr, set_start, set_length, limit, firstchar)
if (line_ptr < limit && *line_ptr == '\\')
{
if (edscript)
- fprintf (stderr, "%s:", argv0);
+ fprintf (stderr, "%s:", program_name);
else
--*set_length;
line_ptr++;
@@ -1430,7 +1494,7 @@ output_diff3_edscript (outputfile, diff, mapping, rev_mapping,
switch (type)
{
default: continue;
- case DIFF_2ND: if (show_2nd < 2) continue; conflict = 1; break;
+ case DIFF_2ND: if (!show_2nd) continue; conflict = 1; break;
case DIFF_3RD: if (overlap_only) continue; conflict = 0; break;
case DIFF_ALL: if (simple_only) continue; conflict = flagging; break;
}
@@ -1559,7 +1623,7 @@ output_diff3_merge (infile, outputfile, diff, mapping, rev_mapping,
switch (type)
{
default: continue;
- case DIFF_2ND: if (show_2nd < 2) continue; conflict = 1; break;
+ case DIFF_2ND: if (!show_2nd) 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";
@@ -1698,7 +1762,7 @@ static void
fatal (string)
char const *string;
{
- fprintf (stderr, "%s: %s\n", argv0, string);
+ fprintf (stderr, "%s: %s\n", program_name, string);
exit (2);
}
@@ -1707,7 +1771,7 @@ perror_with_exit (string)
char const *string;
{
int e = errno;
- fprintf (stderr, "%s: ", argv0);
+ fprintf (stderr, "%s: ", program_name);
errno = e;
perror (string);
exit (2);
diff --git a/gnu/usr.bin/diff/dir.c b/gnu/usr.bin/diff/dir.c
index baadfbf..036a86f 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 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994 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;
+ size_t d_size = NAMLEN (next) + 1;
/* Ignore the files `.' and `..' */
if (d_name[0] == '.'
@@ -85,7 +85,6 @@ 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);
@@ -99,7 +98,7 @@ dir_sort (dir, dirdata)
errno = e;
return -1;
}
-#if VOID_CLOSEDIR
+#if CLOSEDIR_VOID
closedir (reading);
#else
if (closedir (reading) != 0)
@@ -129,7 +128,8 @@ static int
compare_names (file1, file2)
void const *file1, *file2;
{
- return strcmp (* (char const *const *) file1, * (char const *const *) file2);
+ return filename_cmp (* (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 && strcmp (*names0, dir_start_file) < 0)
+ while (*names0 && filename_cmp (*names0, dir_start_file) < 0)
names0++;
- while (*names1 && strcmp (*names1, dir_start_file) < 0)
+ while (*names1 && filename_cmp (*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
- : strcmp (*names0, *names1));
+ : filename_cmp (*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/fnmatch.c b/gnu/usr.bin/diff/fnmatch.c
deleted file mode 100644
index 22fa9df..0000000
--- a/gnu/usr.bin/diff/fnmatch.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
-
-NOTE: The canonical source of this file is maintained with the GNU C Library.
-Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#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
-
-#include <errno.h>
-#include <fnmatch.h>
-#include <ctype.h>
-
-
-/* Comment out all this code if we are using the GNU C Library, and are not
- actually compiling the library itself. This code is part of the GNU C
- Library, but also included in many other GNU distributions. Compiling
- and linking in this code is a waste when using the GNU C library
- (especially if it is a shared library). Rather than having every GNU
- program understand `configure --with-gnu-libc' and omit the object files,
- it is simpler to just do this in the source for each such file. */
-
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
-#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
-extern int errno;
-#endif
-
-/* Match STRING against the filename pattern PATTERN, returning zero if
- it matches, nonzero if not. */
-int
-fnmatch (pattern, string, flags)
- const char *pattern;
- const char *string;
- int flags;
-{
- register const char *p = pattern, *n = string;
- register char c;
-
-/* Note that this evalutes C many times. */
-#define FOLD(c) ((flags & FNM_CASEFOLD) && isupper (c) ? tolower (c) : (c))
-
- while ((c = *p++) != '\0')
- {
- c = FOLD (c);
-
- switch (c)
- {
- case '?':
- if (*n == '\0')
- return FNM_NOMATCH;
- else if ((flags & FNM_FILE_NAME) && *n == '/')
- return FNM_NOMATCH;
- else if ((flags & FNM_PERIOD) && *n == '.' &&
- (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
- return FNM_NOMATCH;
- break;
-
- case '\\':
- if (!(flags & FNM_NOESCAPE))
- {
- c = *p++;
- c = FOLD (c);
- }
- if (FOLD (*n) != c)
- return FNM_NOMATCH;
- break;
-
- case '*':
- if ((flags & FNM_PERIOD) && *n == '.' &&
- (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
- return FNM_NOMATCH;
-
- for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
- if (((flags & FNM_FILE_NAME) && *n == '/') ||
- (c == '?' && *n == '\0'))
- return FNM_NOMATCH;
-
- if (c == '\0')
- return 0;
-
- {
- char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
- c1 = FOLD (c1);
- for (--p; *n != '\0'; ++n)
- if ((c == '[' || FOLD (*n) == c1) &&
- fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
- return 0;
- return FNM_NOMATCH;
- }
-
- case '[':
- {
- /* Nonzero if the sense of the character class is inverted. */
- register int not;
-
- if (*n == '\0')
- return FNM_NOMATCH;
-
- if ((flags & FNM_PERIOD) && *n == '.' &&
- (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
- return FNM_NOMATCH;
-
- not = (*p == '!' || *p == '^');
- if (not)
- ++p;
-
- c = *p++;
- for (;;)
- {
- register char cstart = c, cend = c;
-
- if (!(flags & FNM_NOESCAPE) && c == '\\')
- cstart = cend = *p++;
-
- cstart = cend = FOLD (cstart);
-
- if (c == '\0')
- /* [ (unterminated) loses. */
- return FNM_NOMATCH;
-
- c = *p++;
- c = FOLD (c);
-
- if ((flags & FNM_FILE_NAME) && c == '/')
- /* [/] can never match. */
- return FNM_NOMATCH;
-
- if (c == '-' && *p != ']')
- {
- cend = *p++;
- if (!(flags & FNM_NOESCAPE) && cend == '\\')
- cend = *p++;
- if (cend == '\0')
- return FNM_NOMATCH;
- cend = FOLD (cend);
-
- c = *p++;
- }
-
- if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
- goto matched;
-
- if (c == ']')
- break;
- }
- if (!not)
- return FNM_NOMATCH;
- break;
-
- matched:;
- /* Skip the rest of the [...] that already matched. */
- while (c != ']')
- {
- if (c == '\0')
- /* [... (unterminated) loses. */
- return FNM_NOMATCH;
-
- c = *p++;
- if (!(flags & FNM_NOESCAPE) && c == '\\')
- /* XXX 1003.2d11 is unclear if this is right. */
- ++p;
- }
- if (not)
- return FNM_NOMATCH;
- }
- break;
-
- default:
- if (c != FOLD (*n))
- return FNM_NOMATCH;
- }
-
- ++n;
- }
-
- if (*n == '\0')
- return 0;
-
- if ((flags & FNM_LEADING_DIR) && *n == '/')
- /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
- return 0;
-
- return FNM_NOMATCH;
-}
-
-#endif /* _LIBC or not __GNU_LIBRARY__. */
diff --git a/gnu/usr.bin/diff/getopt.c b/gnu/usr.bin/diff/getopt.c
index 7a4673b..c951bd4 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, 1993
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -20,16 +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__
/* This is a separate conditional since some stdc systems
@@ -39,11 +38,6 @@
#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
@@ -65,11 +59,6 @@
#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.
@@ -92,7 +81,7 @@
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
-char *optarg = 0;
+char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
@@ -162,6 +151,9 @@ 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
@@ -192,19 +184,18 @@ 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.
- (Supposedly there are some machines where it might get a warning,
- but changing this conditional to __STDC__ is too risky.) */
+ If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
-#ifdef IN_GCC
-#include "gstddef.h"
-#else
-#include <stddef.h>
-#endif
-extern size_t strlen (const char *);
-#endif
+/* 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__ */
-#endif /* GNU C library. */
+#endif /* not __GNU_LIBRARY__ */
/* Handle permutation of arguments. */
@@ -279,6 +270,42 @@ 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.
@@ -345,41 +372,15 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int *longind;
int long_only;
{
- 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. */
+ optarg = NULL;
if (optind == 0)
- {
- 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;
- }
+ optstring = _getopt_initialize (optstring);
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,
@@ -390,21 +391,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else if (last_nonopt != optind)
first_nonopt = optind;
- /* Now skip any additional non-options
+ /* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
- && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
- /* Special ARGV-element `--' means premature end of options.
+ /* The 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. */
@@ -437,12 +433,7 @@ _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')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
@@ -451,36 +442,48 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
/* We have found another option-ARGV-element.
- Start decoding its characters. */
+ Skip the initial punctuation. */
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][0] == '-'
- && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
- ))
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{
+ char *nameend;
const struct option *p;
- char *s = nextchar;
+ const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
- const struct option *pfound = NULL;
int indfound;
+ int option_index;
- while (*s && *s != '=')
- s++;
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
- /* 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))
+ /* 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))
{
- if (s - nextchar == strlen (p->name))
+ if (nameend - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
@@ -495,7 +498,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
indfound = option_index;
}
else
- /* Second nonexact match found. */
+ /* Second or later nonexact match found. */
ambig = 1;
}
@@ -513,12 +516,12 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
option_index = indfound;
optind++;
- if (*s)
+ if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
- optarg = s + 1;
+ optarg = nameend + 1;
else
{
if (opterr)
@@ -561,14 +564,12 @@ _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)
@@ -588,7 +589,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
}
- /* Look at and handle the next option-character. */
+ /* Look at and handle the next short option-character. */
{
char c = *nextchar++;
@@ -602,16 +603,11 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (opterr)
{
-#if 0
- if (c < 040 || c >= 0177)
- fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
- argv[0], c);
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
else
- 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
+ fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
}
optopt = c;
return '?';
@@ -627,7 +623,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
optind++;
}
else
- optarg = 0;
+ optarg = NULL;
nextchar = NULL;
}
else
@@ -644,14 +640,9 @@ _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 f784b57..17ab331 100644
--- a/gnu/usr.bin/diff/getopt1.c
+++ b/gnu/usr.bin/diff/getopt1.c
@@ -17,15 +17,8 @@
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 0dbfd43..2834cbd 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, 91, 92, 93 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1991, 1992, 1993, 1994 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 81d0260..6605915 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 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -31,7 +31,9 @@ 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. */
-typedef int word;
+#ifndef word
+#define word int
+#endif
/* Lines are put into equivalence classes (of lines that match in line_cmp).
Each equivalence class is represented by one of these structures,
@@ -42,13 +44,14 @@ 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; /* The length of that line. */
+ size_t length; /* That line's length, not counting its newline. */
};
-/* Hash-table: array of buckets, each being a chain of equivalence classes. */
+/* Hash-table: array of buckets, each being a chain of equivalence classes.
+ buckets[-1] is reserved for incomplete lines. */
static int *buckets;
-/* Number of buckets in the hash table array. */
+/* Number of buckets in the hash table array, not counting buckets[-1]. */
static int nbuckets;
/* Array in which the equivalence classes are allocated.
@@ -71,7 +74,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) (size != 0 && memchr (buf, '\0', size) != 0)
+#define binary_file_p(buf, size) (memchr (buf, '\0', size) != 0)
/* Get ready to read the current file.
Return nonzero if SKIP_TEST is zero,
@@ -97,12 +100,23 @@ sip (current, skip_test)
if (! skip_test)
{
/* Check first part of file to see if it's a binary file. */
- current->buffered_chars = read (current->desc,
- current->buffer,
- current->bufsize);
- if (current->buffered_chars == -1)
+#if HAVE_SETMODE
+ int oldmode = setmode (current->desc, O_BINARY);
+#endif
+ size_t n = read (current->desc, current->buffer, current->bufsize);
+ if (n == -1)
pfatal_with_name (current->name);
- return binary_file_p (current->buffer, current->buffered_chars);
+ 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);
}
}
@@ -193,10 +207,7 @@ 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;
- char const *incomplete_tail
- = current->missing_newline && ROBUST_OUTPUT_STYLE (output_style)
- ? bufend : (char const *) 0;
- int varies = length_varies;
+ int use_line_cmp = ignore_some_line_changes;
while ((char const *) p < suffix_begin)
{
@@ -212,42 +223,52 @@ 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))
{
- while (isspace (c = *p++))
- if (c == '\n')
- goto hashing_done;
+ for (;;)
+ {
+ c = *p++;
+ if (!ISSPACE (c))
+ break;
+ 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))
{
- while (isspace (c = *p++))
- if (c == '\n')
- goto hashing_done;
+ for (;;)
+ {
+ c = *p++;
+ if (!ISSPACE (c))
+ break;
+ if (c == '\n')
+ goto hashing_done;
+ }
h = HASH (h, ' ');
}
/* C is now the first non-space. */
@@ -260,7 +281,22 @@ find_and_hash_each_line (current)
hashing_done:;
bucket = &buckets[h % nbuckets];
- length = (char const *) p - ip - ((char const *) p == incomplete_tail);
+ 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;
+ }
+
for (i = *bucket; ; i = eqs[i].next)
if (!i)
{
@@ -276,11 +312,20 @@ find_and_hash_each_line (current)
*bucket = i;
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;
+ 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;
+ }
/* Maybe increase the size of the line table. */
if (line == alloc_lines)
@@ -303,7 +348,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)
{
@@ -317,10 +362,7 @@ find_and_hash_each_line (current)
linbuf[line] = (char const *) p;
if ((char const *) p == bufend)
- {
- linbuf[line] -= (char const *) p == incomplete_tail;
- break;
- }
+ break;
if (context <= i && no_diff_means_no_output)
break;
@@ -343,7 +385,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 unless -B is in effect. */
+ but remember that we had to add one. */
static void
prepare_text_end (current)
@@ -358,7 +400,7 @@ prepare_text_end (current)
{
p[buffered_chars++] = '\n';
current->buffered_chars = buffered_chars;
- current->missing_newline = ! ignore_blank_lines_flag;
+ current->missing_newline = 1;
}
/* Don't use uninitialized storage when planting or using sentinels. */
@@ -636,7 +678,13 @@ read_files (filevec, pretend_binary)
filevec[1].buffered_chars = filevec[0].buffered_chars;
}
if (appears_binary)
- return 1;
+ {
+#if HAVE_SETMODE
+ setmode (filevec[0].desc, O_BINARY);
+ setmode (filevec[1].desc, O_BINARY);
+#endif
+ return 1;
+ }
find_identical_ends (filevec);
@@ -651,16 +699,16 @@ read_files (filevec, pretend_binary)
abort ();
nbuckets = primes[i];
- buckets = (int *) xmalloc (nbuckets * sizeof (*buckets));
- bzero (buckets, nbuckets * sizeof (*buckets));
+ buckets = (int *) xmalloc ((nbuckets + 1) * sizeof (*buckets));
+ bzero (buckets++, (nbuckets + 1) * 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);
+ free (buckets - 1);
return 0;
}
diff --git a/gnu/usr.bin/diff/sdiff.c b/gnu/usr.bin/diff/sdiff.c
index 783f101..b64f1d0 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 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -21,7 +21,6 @@ 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"
@@ -34,22 +33,25 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#endif
/* Users' editor of nonchoice */
-#ifndef DEFAULT_EDITOR
-#define DEFAULT_EDITOR "ed"
+#ifndef DEFAULT_EDITOR_PROGRAM
+#define DEFAULT_EDITOR_PROGRAM "ed"
#endif
extern char version_string[];
-static char const *prog;
+static char const *program_name;
static char const *diffbin = DIFF_PROGRAM;
-static char const *edbin = DEFAULT_EDITOR;
+static char const *edbin = DEFAULT_EDITOR_PROGRAM;
+static char const **diffargv;
static char *tmpname;
static int volatile tmpmade;
+
+#if HAVE_FORK
static pid_t volatile diffpid;
+#endif
struct line_filter;
-static FILE *ck_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));
@@ -66,7 +68,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((int, char const *, char const *, char const *));
+static void execdiff PARAMS((void));
static void exiterr PARAMS((void));
static void fatal PARAMS((char const *));
static void flush_line PARAMS((void));
@@ -76,14 +78,24 @@ 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((int));
+static void usage PARAMS((void));
/* 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"
-static char *private_tempnam PARAMS((char const *, char const *, int, size_t *));
-static int diraccess PARAMS((char const *));
+#endif
+#ifndef TMPDIR_ENV
+#define TMPDIR_ENV "TMPDIR"
+#endif
+static char *private_tempnam PARAMS((void));
static int exists PARAMS((char const *));
+#endif
+static int diraccess PARAMS((char const *));
/* Options: */
@@ -113,27 +125,52 @@ static struct option const longopts[] =
{0, 0, 0, 0}
};
-/* prints usage message and quits */
static void
-usage (status)
- int status;
+try_help (reason)
+ char const *reason;
{
- 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);
+ if (reason)
+ fprintf (stderr, "%s: %s\n", program_name, reason);
+ fprintf (stderr, "%s: Try `%s --help' for more information.\n",
+ program_name, program_name);
+ exit (2);
+}
+
+static void
+usage ()
+{
+ printf ("Usage: %s [OPTIONS]... FILE1 FILE2\n\n", program_name);
+ printf ("%s", "\
+ -o FILE --output=FILE Operate interactively, sending output to FILE.\n\n");
+ printf ("%s", "\
+ -i --ignore-case Consider upper- and lower-case to be the same.\n\
+ -W --ignore-all-space Ignore all white space.\n\
+ -b --ignore-space-change Ignore changes in the amount of white space.\n\
+ -B --ignore-blank-lines Ignore changes whose lines are all blank.\n\
+ -I RE --ignore-matching-lines=RE Ignore changes whose lines all match RE.\n\
+ -a --text Treat all files as text.\n\n");
+ printf ("%s", "\
+ -w NUM --width=NUM Output at most NUM (default 130) characters per line.\n\
+ -l --left-column Output only the left column of common lines.\n\
+ -s --suppress-common-lines Do not output common lines.\n\n");
+ printf ("\
+ -t --expand-tabs Expand tabs to spaces in output.\n\n");
+ printf ("%s", "\
+ -d --minimal Try hard to find a smaller set of changes.\n\
+ -H --speed-large-files Assume large files and many scattered small changes.\n\n");
+ printf ("%s", "\
+ -v --version Output version info.\n\
+ --help Output this help.\n\n\
+If FILE1 or FILE2 is `-', read standard input.\n");
}
static void
cleanup ()
{
+#if HAVE_FORK
if (0 < diffpid)
kill (diffpid, SIGPIPE);
+#endif
if (tmpmade)
unlink (tmpname);
}
@@ -151,7 +188,7 @@ static void
fatal (msg)
char const *msg;
{
- fprintf (stderr, "%s: %s\n", prog, msg);
+ fprintf (stderr, "%s: %s\n", program_name, msg);
exiterr ();
}
@@ -161,7 +198,7 @@ perror_fatal (msg)
{
int e = errno;
checksigs ();
- fprintf (stderr, "%s: ", prog);
+ fprintf (stderr, "%s: ", program_name);
errno = e;
perror (msg);
exiterr ();
@@ -189,18 +226,6 @@ 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;
@@ -239,67 +264,21 @@ 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, isdir, other_name)
+expand_name (name, is_dir, other_name)
char *name;
- int isdir;
+ int is_dir;
char const *other_name;
{
if (strcmp (name, "-") == 0)
fatal ("cannot interactively merge standard input");
- if (!isdir)
+ if (!is_dir)
return name;
else
{
/* Yield NAME/BASE, where BASE is OTHER_NAME's basename. */
- char const
- *p = strrchr (other_name, '/'),
- *base = p ? p+1 : other_name;
+ char const *p = filename_lastdirchar (other_name);
+ char const *base = p ? p+1 : other_name;
size_t namelen = strlen (name), baselen = strlen (base);
char *r = xmalloc (namelen + baselen + 2);
memcpy (r, name, namelen);
@@ -430,12 +409,16 @@ main (argc, argv)
char *argv[];
{
int opt;
- char *editor = getenv ("EDITOR");
- char *differ = getenv ("DIFF");
+ char *editor;
+ char *differ;
+
+ initialize_main (&argc, &argv);
+ program_name = argv[0];
- prog = argv[0];
+ editor = getenv ("EDITOR");
if (editor)
edbin = editor;
+ differ = getenv ("DIFF");
if (differ)
diffbin = differ;
@@ -493,7 +476,7 @@ main (argc, argv)
break;
case 'v':
- printf ("GNU sdiff version %s\n", version_string);
+ printf ("sdiff - GNU diffutils version %s\n", version_string);
exit (0);
case 'w':
@@ -506,25 +489,35 @@ main (argc, argv)
break;
case 129:
- usage (0);
+ usage ();
+ if (ferror (stdout) || fclose (stdout) != 0)
+ fatal ("write error");
+ exit (0);
default:
- usage (2);
+ try_help (0);
}
}
if (argc - optind != 2)
- usage (2);
+ try_help (argc - optind < 2 ? "missing operand" : "extra operand");
if (! out_file)
- /* easy case: diff does everything for us */
- execdiff (suppress_common_flag, "-y", argv[optind], argv[optind + 1]);
+ {
+ /* easy case: diff does everything for us */
+ if (suppress_common_flag)
+ diffarg ("--suppress-common-lines");
+ diffarg ("-y");
+ diffarg ("--");
+ diffarg (argv[optind]);
+ diffarg (argv[optind + 1]);
+ diffarg (0);
+ execdiff ();
+ }
else
{
FILE *left, *right, *out, *diffout;
- int diff_fds[2];
int interact_ok;
- pid_t pid;
struct line_filter lfilt;
struct line_filter rfilt;
struct line_filter diff_filt;
@@ -539,33 +532,66 @@ main (argc, argv)
right = ck_fopen (expand_name (argv[optind + 1], rightdir, argv[optind]), "r");
out = ck_fopen (out_file, "w");
- if (pipe (diff_fds))
- perror_fatal ("pipe");
+ diffarg ("--sdiff-merge-assist");
+ diffarg ("--");
+ diffarg (argv[optind]);
+ diffarg (argv[optind + 1]);
+ diffarg (0);
trapsigs ();
- diffpid = pid = vfork ();
+#if ! HAVE_FORK
+ {
+ size_t cmdsize = 1;
+ char *p, *command;
+ int i;
+
+ for (i = 0; diffargv[i]; i++)
+ cmdsize += 4 * strlen (diffargv[i]) + 3;
+ command = p = xmalloc (cmdsize);
+ for (i = 0; diffargv[i]; i++)
+ {
+ char const *a = diffargv[i];
+ SYSTEM_QUOTE_ARG (p, a);
+ *p++ = ' ';
+ }
+ p[-1] = '\0';
+ diffout = popen (command, "r");
+ if (!diffout)
+ perror_fatal (command);
+ free (command);
+ }
+#else /* HAVE_FORK */
+ {
+ int diff_fds[2];
- if (pid == 0)
- {
- signal (SIGINT, SIG_IGN); /* in case user interrupts editor */
- signal (SIGPIPE, SIG_DFL);
+ if (pipe (diff_fds) != 0)
+ perror_fatal ("pipe");
- close (diff_fds[0]);
- if (diff_fds[1] != STDOUT_FILENO)
- {
- dup2 (diff_fds[1], STDOUT_FILENO);
- close (diff_fds[1]);
- }
+ diffpid = vfork ();
+ if (diffpid < 0)
+ perror_fatal ("fork failed");
+ if (!diffpid)
+ {
+ signal (SIGINT, SIG_IGN); /* in case user interrupts editor */
+ signal (SIGPIPE, SIG_DFL);
- execdiff (0, "--sdiff-merge-assist", argv[optind], argv[optind + 1]);
- }
+ close (diff_fds[0]);
+ if (diff_fds[1] != STDOUT_FILENO)
+ {
+ dup2 (diff_fds[1], STDOUT_FILENO);
+ close (diff_fds[1]);
+ }
- if (pid < 0)
- perror_fatal ("fork failed");
+ execdiff ();
+ }
- close (diff_fds[1]);
- diffout = ck_fdopen (diff_fds[0], "r");
+ close (diff_fds[1]);
+ diffout = fdopen (diff_fds[0], "r");
+ if (!diffout)
+ perror_fatal ("fdopen");
+ }
+#endif /* HAVE_FORK */
lf_init (&diff_filt, diffout);
lf_init (&lfilt, left);
@@ -573,7 +599,6 @@ main (argc, argv)
interact_ok = interact (&diff_filt, &lfilt, &rfilt, out);
- ck_fclose (diffout);
ck_fclose (left);
ck_fclose (right);
ck_fclose (out);
@@ -581,12 +606,17 @@ main (argc, argv)
{
int wstatus;
- while (waitpid (pid, &wstatus, 0) < 0)
+#if ! HAVE_FORK
+ wstatus = pclose (diffout);
+#else
+ ck_fclose (diffout);
+ while (waitpid (diffpid, &wstatus, 0) < 0)
if (errno == EINTR)
checksigs ();
else
perror_fatal ("wait failed");
diffpid = 0;
+#endif
if (tmpmade)
{
@@ -608,8 +638,6 @@ main (argc, argv)
return 0; /* Fool -Wall . . . */
}
-static char const **diffargv;
-
static void
diffarg (a)
char const *a;
@@ -633,18 +661,8 @@ diffarg (a)
}
static void
-execdiff (differences_only, option, file1, file2)
- int differences_only;
- char const *option, *file1, *file2;
+execdiff ()
{
- 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);
@@ -734,6 +752,15 @@ 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;
}
@@ -792,8 +819,13 @@ static int
skip_white ()
{
int c;
- while (isspace (c = getchar ()) && c != '\n')
- checksigs ();
+ for (;;)
+ {
+ c = getchar ();
+ if (!ISSPACE (c) || c == '\n')
+ break;
+ checksigs ();
+ }
if (ferror (stdin))
perror_fatal ("input error");
return c;
@@ -903,7 +935,7 @@ edit (left, lenl, right, lenr, outfile)
case 'q':
return 0;
case 'e':
- if (! tmpname && ! (tmpname = private_tempnam (0, "sdiff", 1, 0)))
+ if (! tmpname && ! (tmpname = private_tempnam ()))
perror_fatal ("temporary file name");
tmpmade = 1;
@@ -924,8 +956,14 @@ edit (left, lenl, right, lenr, outfile)
ck_fflush (tmp);
{
- pid_t pid;
int wstatus;
+#if ! HAVE_FORK
+ char *command = xmalloc (strlen (edbin) + strlen (tmpname) + 2);
+ sprintf (command, "%s %s", edbin, tmpname);
+ wstatus = system (command);
+ free (command);
+#else /* HAVE_FORK */
+ pid_t pid;
ignore_SIGINT = 1;
checksigs ();
@@ -956,8 +994,9 @@ edit (left, lenl, right, lenr, outfile)
perror_fatal ("wait failed");
ignore_SIGINT = 0;
+#endif /* HAVE_FORK */
- if (! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 1))
+ if (wstatus != 0)
fatal ("Subsidiary editor failed");
}
@@ -1063,131 +1102,79 @@ diraccess (dir)
return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode);
}
-/* Return nonzero if FILE exists. */
+#if ! HAVE_TMPNAM
+
+/* Return zero if we know that FILE does not exist. */
static int
exists (file)
char const *file;
{
struct stat buf;
- return stat (file, &buf) == 0;
+ return stat (file, &buf) == 0 || errno != ENOENT;
}
/* These are the characters used in temporary filenames. */
static char const letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-/* 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. */
-
-
+/* 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. */
static char *
-private_tempnam (dir, pfx, dir_search, lenptr)
- char const *dir;
- char const *pfx;
- int dir_search;
- size_t *lenptr;
+private_tempnam ()
{
+ char const *dir = getenv (TMPDIR_ENV);
static char const tmpdir[] = PVT_tmpdir;
- 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;
+ size_t index;
+ char *buf;
pid_t pid = getpid ();
- register size_t len, plen;
+ size_t dlen;
- 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
+ if (!dir)
dir = tmpdir;
- if (pfx && *pfx)
- {
- plen = strlen (pfx);
- if (plen > 5)
- plen = 5;
- }
- else
- plen = 0;
+ dlen = strlen (dir);
- if (dir != tmpdir && !strcmp (dir, tmpdir))
- dir = tmpdir;
- info = &infos[(plen == 0 && dir == tmpdir) ? 1 : 0];
+ /* Remove trailing slashes from the directory name. */
+ while (dlen && dir[dlen - 1] == '/')
+ --dlen;
- if (pid != oldpid)
- {
- oldpid = pid;
- info->buf[0] = info->buf[1] = info->buf[2] = '0';
- info->s = &info->buf[0];
- info->i = 0;
- }
+ buf = xmalloc (dlen + 1 + 3 + 5 + 1 + 3 + 1);
- len = strlen (dir) + 1 + plen + 8;
- if (bufsize <= len)
+ sprintf (buf, "%.*s/.", (int) dlen, dir);
+ if (diraccess (buf))
{
- do
+ for (index = 0;
+ index < ((sizeof (letters) - 1) * (sizeof (letters) - 1)
+ * (sizeof (letters) - 1));
+ ++index)
{
- bufsize *= 2;
- }
- while (bufsize <= len);
+ /* Construct a file name and see if it already exists.
- 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;
+ 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))]);
+
+ if (!exists (buf))
+ return buf;
}
+ errno = EEXIST;
}
- if (lenptr)
- *lenptr = len;
- return buf;
+ /* Don't free buf; `free' might change errno. We'll exit soon anyway. */
+ return 0;
}
+
+#endif /* ! HAVE_TMPNAM */
diff --git a/gnu/usr.bin/diff/side.c b/gnu/usr.bin/diff/side.c
index 59943f2..a150b5e 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 2da6247..47db287 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 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -64,16 +64,6 @@ 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
@@ -104,8 +94,10 @@ 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))
@@ -116,47 +108,39 @@ 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)
-#undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix. */
+#define WEXITSTATUS(stat_val) ((unsigned) (stat_val) >> 8)
#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 DIRENT || defined (_POSIX_VERSION)
-#include <dirent.h>
-#else /* ! (DIRENT || defined (_POSIX_VERSION)) */
-#if SYSNDIR
-#include <sys/ndir.h>
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
-#if SYSDIR
-#include <sys/dir.h>
-#else
-#include <ndir.h>
-#endif
+# 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
#endif
-#ifdef dirent
-#undef dirent
-#endif
-#define dirent direct
-#endif /* ! (DIRENT || defined (_POSIX_VERSION)) */
#if HAVE_VFORK_H
#include <vfork.h>
@@ -182,28 +166,44 @@ char *getenv ();
#define CHAR_BIT 8
#endif
-#if HAVE_STRING_H
-#include <string.h>
-#ifndef bzero
-#define bzero(s,n) memset (s,0,n)
+#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
#endif
-#else /* !HAVE_STRING_H */
-#include <strings.h>
-#ifndef strchr
-#define strchr index
+
+#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)
#endif
-#ifndef strrchr
-#define strrchr rindex
+#ifndef ISPRINT
+#define ISPRINT(c) (CTYPE_DOMAIN (c) && isprint (c))
#endif
-#ifndef memcpy
-#define memcpy(d,s,n) bcopy (s,d,n)
+#ifndef ISSPACE
+#define ISSPACE(c) (CTYPE_DOMAIN (c) && isspace (c))
#endif
-#ifndef memcmp
-#define memcmp(s1,s2,n) bcmp (s1,s2,n)
+#ifndef ISUPPER
+#define ISUPPER(c) (CTYPE_DOMAIN (c) && isupper (c))
#endif
-#endif /* !HAVE_STRING_H */
-#if !HAVE_MEMCHR
-char *memchr ();
+
+#ifndef ISDIGIT
+#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
#endif
#include <errno.h>
@@ -211,5 +211,57 @@ char *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 38e20f4..bbc3bff 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 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
This file is part of GNU DIFF.
@@ -19,6 +19,10 @@ 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'. */
@@ -48,7 +52,7 @@ perror_with_name (text)
char const *text;
{
int e = errno;
- fprintf (stderr, "%s: ", program);
+ fprintf (stderr, "%s: ", program_name);
errno = e;
perror (text);
}
@@ -61,7 +65,7 @@ pfatal_with_name (text)
{
int e = errno;
print_message_queue ();
- fprintf (stderr, "%s: ", program);
+ fprintf (stderr, "%s: ", program_name);
errno = e;
perror (text);
exit (2);
@@ -74,7 +78,7 @@ void
error (format, arg, arg1)
char const *format, *arg, *arg1;
{
- fprintf (stderr, "%s: ", program);
+ fprintf (stderr, "%s: ", program_name);
fprintf (stderr, format, arg, arg1);
fprintf (stderr, "\n");
}
@@ -157,7 +161,9 @@ setup_output (name0, name1, depth)
outfile = 0;
}
+#if HAVE_FORK
static pid_t pr_pid;
+#endif
void
begin_output ()
@@ -170,19 +176,20 @@ 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 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. */
+ /* Posix.2 section 4.17.6.1.1 specifies this format. But there is a
+ bug in the first printing (IEEE Std 1003.2-1992 p 251 l 3304):
+ it says that we must print only the last component of the pathnames.
+ This requirement is silly and does not match historical practice. */
sprintf (name, "diff%s %s %s", switch_string, current_name0, current_name1);
if (paginate_flag)
{
+ /* Make OUTFILE a pipe to a subsidiary `pr'. */
+
+#if HAVE_FORK
int pipes[2];
- /* Fork a `pr' and make OUTFILE a pipe to it. */
- if (pipe (pipes) < 0)
+ if (pipe (pipes) != 0)
pfatal_with_name ("pipe");
fflush (stdout);
@@ -201,14 +208,29 @@ begin_output ()
close (pipes[0]);
}
- execl (PR_FILE_NAME, PR_FILE_NAME, "-f", "-h", name, 0);
- pfatal_with_name (PR_FILE_NAME);
+ execl (PR_PROGRAM, PR_PROGRAM, "-f", "-h", name, 0);
+ pfatal_with_name (PR_PROGRAM);
}
else
{
close (pipes[0]);
outfile = fdopen (pipes[1], "w");
+ if (!outfile)
+ pfatal_with_name ("fdopen");
}
+#else /* ! HAVE_FORK */
+ char *command = xmalloc (4 * strlen (name) + strlen (PR_PROGRAM) + 10);
+ char *p;
+ char const *a = name;
+ sprintf (command, "%s -f -h ", PR_PROGRAM);
+ p = command + strlen (command);
+ SYSTEM_QUOTE_ARG (p, a);
+ *p = 0;
+ outfile = popen (command, "w");
+ if (!outfile)
+ pfatal_with_name (command);
+ free (command);
+#endif /* ! HAVE_FORK */
}
else
{
@@ -252,21 +274,15 @@ 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");
-#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)
+#endif /* HAVE_FORK */
+ if (wstatus != 0)
fatal ("subsidiary pr failed");
}
@@ -275,56 +291,44 @@ finish_output ()
/* Compare two lines (typically one from each input file)
according to the command line options.
- Return 1 if the lines differ, like `memcmp'. */
+ For efficiency, this is invoked only when the lines do not match exactly
+ but an option like -i might cause us to ignore the difference.
+ Return nonzero if the lines differ. */
int
-line_cmp (s1, len1, s2, len2)
+line_cmp (s1, s2)
char const *s1, *s2;
- size_t len1, len2;
{
- 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. */
+ register unsigned char const *t1 = (unsigned char const *) s1;
+ register unsigned char const *t2 = (unsigned char const *) s2;
- 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)
+ while (1)
{
- t1 = (unsigned char const *) s1;
- t2 = (unsigned char const *) s2;
+ register unsigned char c1 = *t1++;
+ register unsigned char c2 = *t2++;
- while (1)
+ /* Test for exact char equality first, since it's a common case. */
+ if (c1 != c2)
{
- 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 != end_char) c1 = *t1++;
- while (isspace (c2) && c2 != end_char) c2 = *t2++;
+ while (ISSPACE (c1) && c1 != '\n') c1 = *t1++;
+ while (ISSPACE (c2) && c2 != '\n') c2 = *t2++;
}
else if (ignore_space_change_flag)
{
/* For -b, advance past any sequence of white space in line 1
and consider it just one Space, or nothing at all
if it is at the end of the line. */
- if (isspace (c1))
+ if (ISSPACE (c1))
{
- while (c1 != end_char)
+ while (c1 != '\n')
{
c1 = *t1++;
- if (! isspace (c1))
+ if (! ISSPACE (c1))
{
--t1;
c1 = ' ';
@@ -334,12 +338,12 @@ line_cmp (s1, len1, s2, len2)
}
/* Likewise for line 2. */
- if (isspace (c2))
+ if (ISSPACE (c2))
{
- while (c2 != end_char)
+ while (c2 != '\n')
{
c2 = *t2++;
- if (! isspace (c2))
+ if (! ISSPACE (c2))
{
--t2;
c2 = ' ';
@@ -347,23 +351,44 @@ line_cmp (s1, len1, s2, len2)
}
}
}
+
+ 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;
+ }
+ }
}
- /* Upcase all letters if -i is specified. */
+ /* Lowercase all letters if -i is specified. */
if (ignore_case_flag)
{
- if (islower (c1))
- c1 = toupper (c1);
- if (islower (c2))
- c2 = toupper (c2);
+ if (ISUPPER (c1))
+ c1 = tolower (c1);
+ if (ISUPPER (c2))
+ c2 = tolower (c2);
}
if (c1 != c2)
break;
- if (c1 == end_char)
- return 0;
}
+ if (c1 == '\n')
+ return 0;
}
return (1);
@@ -454,8 +479,7 @@ print_1_line (line_flag, line)
output_1_line (text, limit, flag_format, line_flag);
- if ((!line_flag || line_flag[0]) && limit[-1] != '\n'
- && line_end_char == '\n')
+ if ((!line_flag || line_flag[0]) && limit[-1] != '\n')
fprintf (out, "\n\\ No newline at end of file\n");
}
@@ -505,7 +529,7 @@ output_1_line (text, limit, flag_format, line_flag)
break;
default:
- if (isprint (c))
+ if (ISPRINT (c))
column++;
putc (c, out);
break;
@@ -558,7 +582,7 @@ translate_range (file, a, b, aptr, bptr)
void
print_number_range (sepchar, file, a, b)
- char sepchar;
+ int sepchar;
struct file_data *file;
int a, b;
{
@@ -714,7 +738,8 @@ char *
dir_file_pathname (dir, file)
char const *dir, *file;
{
- return concat (dir, "/" + (*dir && dir[strlen (dir) - 1] == '/'), file);
+ char const *p = filename_lastdirchar (dir);
+ return concat (dir, "/" + (p && !p[1]), file);
}
void
@@ -727,18 +752,3 @@ 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 234ec29..c2b6a8a 100644
--- a/gnu/usr.bin/diff/version.c
+++ b/gnu/usr.bin/diff/version.c
@@ -2,4 +2,4 @@
#include "config.h"
-char const version_string[] = "2.6";
+char const version_string[] = "2.7";
OpenPOWER on IntegriCloud