diff options
author | peter <peter@FreeBSD.org> | 1995-10-28 19:11:01 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-10-28 19:11:01 +0000 |
commit | c37ff62e9be62a7cd6340caca3316bb40062ac2d (patch) | |
tree | 987fcf998a10323a27da08d8512088fb01e8396f /gnu/usr.bin | |
parent | 72fa7ec057bc2d7930e60d59f3936afe1de4bc11 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | gnu/usr.bin/diff/config.h | 56 | ||||
-rw-r--r-- | gnu/usr.bin/diff/context.c | 12 | ||||
-rw-r--r-- | gnu/usr.bin/diff/diff.c | 213 | ||||
-rw-r--r-- | gnu/usr.bin/diff/diff.h | 16 | ||||
-rw-r--r-- | gnu/usr.bin/diff/diff3.c | 204 | ||||
-rw-r--r-- | gnu/usr.bin/diff/dir.c | 16 | ||||
-rw-r--r-- | gnu/usr.bin/diff/fnmatch.c | 209 | ||||
-rw-r--r-- | gnu/usr.bin/diff/getopt.c | 215 | ||||
-rw-r--r-- | gnu/usr.bin/diff/getopt1.c | 7 | ||||
-rw-r--r-- | gnu/usr.bin/diff/ifdef.c | 22 | ||||
-rw-r--r-- | gnu/usr.bin/diff/io.c | 140 | ||||
-rw-r--r-- | gnu/usr.bin/diff/sdiff.c | 463 | ||||
-rw-r--r-- | gnu/usr.bin/diff/side.c | 2 | ||||
-rw-r--r-- | gnu/usr.bin/diff/system.h | 158 | ||||
-rw-r--r-- | gnu/usr.bin/diff/util.c | 174 | ||||
-rw-r--r-- | gnu/usr.bin/diff/version.c | 2 |
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"; |