summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@suse.de>2009-03-12 15:17:03 +0100
committerAndreas Gruenbacher <agruen@suse.de>2009-03-12 15:17:03 +0100
commit957f7b6423cc7a1f87e7e6a4cb4b41c46821d804 (patch)
tree855171939850bf86108373184ded91ca626af337
parent6b2b4620383eb47f4979b936b266708ed7812788 (diff)
downloadpatch-957f7b6423cc7a1f87e7e6a4cb4b41c46821d804.tar.gz
Import of patch-2.5.3.tar.gzv2.5.3
-rw-r--r--AUTHORS9
-rw-r--r--ChangeLog144
-rw-r--r--Makefile.in56
-rw-r--r--NEWS25
-rw-r--r--acconfig.h12
-rw-r--r--aclocal.m4197
-rw-r--r--ansi2knr.c550
-rw-r--r--argmatch.c14
-rw-r--r--common.h43
-rw-r--r--config.hin21
-rwxr-xr-xconfigure616
-rw-r--r--configure.in24
-rw-r--r--error.c246
-rw-r--r--error.h78
-rw-r--r--getopt.c57
-rw-r--r--getopt.h30
-rw-r--r--getopt1.c34
-rw-r--r--inp.c94
-rw-r--r--maketime.c316
-rw-r--r--maketime.h2
-rw-r--r--malloc.c39
-rw-r--r--memchr.c33
-rw-r--r--partime.c370
-rw-r--r--partime.h18
-rw-r--r--patch.c271
-rw-r--r--patch.man189
-rw-r--r--pch.c288
-rw-r--r--quotearg.c412
-rw-r--r--quotearg.h102
-rw-r--r--quotesys.c125
-rw-r--r--quotesys.h9
-rw-r--r--realloc.c44
-rw-r--r--util.c188
-rw-r--r--util.h11
-rw-r--r--version.c6
-rw-r--r--xalloc.h21
-rw-r--r--xmalloc.c133
37 files changed, 4004 insertions, 823 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..1cc569b
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,9 @@
+Larry Wall wrote the original version of `patch'.
+
+Paul Eggert removed arbitrary limits; added support for binary
+files, setting file times, and deleting files; and made it conform
+better to POSIX.
+
+Wayne Davison added unidiff support.
+
+David MacKenzie added configuration and backup support.
diff --git a/ChangeLog b/ChangeLog
index 80cfc8b..a8ee329 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,147 @@
+1998-03-20 Paul Eggert <eggert@twinsun.com>
+
+ * configure.in (VERSION): Bump to 2.5.3.
+ * quotearg.h (quotearg_quoting_options):
+ Remove; it ran afoul of the Borland C compiler.
+ Its address is now represented by the null pointer.
+ * quotearg.c (default_quoting_options):
+ Renamed from quotearg_quoting_options,
+ and now static instead of extern.
+ (clone_quoting_options, get_quoting_style, set_quoting_style,
+ set_char_quoting, quotearg_buffer):
+ Use default_quoting_options when passed a null pointer.
+ * patch.c (main, get_some_switches):
+ Pass a null pointer instead of address of quotearg_quoting_options.
+
+1998-03-17 Paul Eggert <eggert@twinsun.com>
+
+ * patch.c (option_help): Update bug reporting address to gnu.org.
+ * patch.man: Fix copyright and bug reporting address.
+
+1998-03-16 Paul Eggert <eggert@twinsun.com>
+
+ * configure.in (VERSION): Bump to 2.5.2.
+ (AC_CHECK_FUNCS): Add strerror.
+ (jm_FUNC_MALLOC, jm_FUNC_REALLOC): Add.
+ (AM_C_PROTOTYPES): Add.
+
+ * NEWS, patch.c (longopts, get_some_switches), patch.man:
+ Add --quoting-style, --posix options.
+
+ * Makefile.in (LIBSRCS): Add malloc.c, realloc.c.
+ (SRCS): Add error.c, quotesys.c, xmalloc.c.
+ (OBJS): Likewise.
+ (HDRS): Add error.h, quotesys.h, xalloc.h.
+ (MISC): Add AUTHORS, aclocal.m4, ansi2knr.c.
+ (clean): Use mostlyclean rule.
+ (argmatch.o, inp.o, patch.o, pch.o): Now also depends on quotearg.h.
+ (inp.o, patch.o, util.o): Now also depends on xalloc.h.
+ (error.o, quotearg.o, quotesys.o, xmalloc.o,
+ ansi2knr.o, ansi2knr, quotearg_.c, .c_.c): New rules.
+ (U): New macro.
+ (OBJS, quotearg$U.o): Rename quotearg.o to quotearg$U.o.
+ (mostlyclean): Remove ansi2knr, *_.c.
+ (.SUFFIXES): Add _.c.
+
+ * acconfig.h (PROTOTYPES): New undef.
+
+ * acconfig.h, configure.in (HAVE_INTTYPES_H, malloc, realloc):
+ New macros.
+
+ * aclocal.m4, error.c, error.h, malloc.c,
+ quotearg.h, quotearg.c, realloc.c, xalloc.h, xmalloc.c: New files.
+
+ * argmatch.c: Include <sys/types.h> before <argmatch.h>.
+ Include <quotearg.h>.
+
+ * argmatch.c (invalid_arg),
+ inp.c (scan_input, report_revision, too_many_lines, get_input_file,
+ plan_a),
+ patch.c (main, get_some_switches, numeric_string),
+ pch.c (open_patch_file, intuit_diff_type, do_ed_script):
+ util.c (move_file, create_file, copy_file, version_get, removedirs):
+ Quote output operands properly.
+
+ * common.h: Include <inttypes.h> if available.
+ (CHAR_BIT, TYPE_SIGNED, TYPE_MINIMUM, TYPE_MAXIMUM,
+ CHAR_MAX, INT_MAX, LONG_MIN, SIZE_MAX, O_EXCL): New macros.
+ (TMPINNAME_needs_removal, TMPOUTNAME_needs_removal,
+ TMPPATNAME_needs_removal): New variables.
+ (xmalloc): Remove decl; now in xalloc.h.
+
+ * inp.c: Include <quotearg.h>, <xalloc.h>.
+
+ * inp.c (get_input_file),
+ pch.c (intuit_diff_type),
+ util.c (version_controller):
+ Don't do diff operation if diffbuf is null; used by ClearCase support.
+
+ * inp.c (plan_b),
+ patch.c (init_reject),
+ pch.c (open_patch_file, do_ed_script):
+ Create temporary file with O_EXCL to avoid races.
+
+ * patch.c: Include <quotearg.h>, <xalloc.h>.
+ (create_output_file, init_output): New open_flags arg.
+ All callers changed.
+ (init_reject): No longer takes filename arg. All callers changed.
+ (remove_if_needed): New function.
+ (cleanup): Use it to remove temporary files only if needed.
+ (TMPREJNAME_needs_removal): New var.
+ (main): Set xalloc_fail_func to memory_fatal; needed for xalloc.
+ Initialize quoting style from QUOTING_STYLE.
+ (longopts, get_some_switches): Offset longarg options by CHAR_MAX,
+ not 128; this is needed for EBCDIC ports.
+
+ * patch.c (main, locate_hunk, abort_hunk, spew_output),
+ pch.c (there_is_another_patch, intuit_diff_type, malformed,
+ another_hunk):
+ The LINENUM type now might be longer than long,
+ so print and read line numbers more carefully.
+
+ * patch.c (main),
+ pch.c (there_is_another_patch):
+ util.c (fetchname):
+ strippath now defaults to -1, so that we can distinguish unset
+ value from largest possible.
+
+ * patch.man: Clarify how file name is chosen from candidates.
+
+ * pch.c: Include <quotearg.h>.
+ (p_strip_trailing_cr): New variable.
+ (scan_linenum): New function.
+ (pget_line, re_patch, there_is_another_patch, intuit_diff_type,
+ get_line): Strip trailing CRs from context diffs that need this.
+ (best_name): Use SIZE_MAX instead of (size_t) -1 for max size_t.
+
+ * quotesys.c, quotearg.h: Renamed from quotearg.c and quotearg.h.
+ All uses changed.
+ * quotesys.h (__QUOTESYS_P): Renamed from __QUOTEARG_P.
+
+ * util.c: Include <quotearg.h>, <xalloc.h>.
+ (raise): Don't define if already defined.
+ (move_file): New arg from_needs_removal. All callers changed.
+ (copy_file): New arg to_flags. All callers changed.
+ (CLEARTOOL_CO): New constant.
+ (version_controller): Add ClearCase support.
+ (format_linenum): New function.
+ (fetchname): Allow any POSIX.1 time zone spec, which means
+ any local time offset in the range -25:00 < offset < +26:00.
+ Ignore the name if it doesn't have enough slashes to strip off.
+ (xmalloc): Remove; now in xmalloc.c.
+
+ * util.h (LINENUM_LENGTH_BOUND): New macro.
+ (format_linenum): New decl.
+
+ * version.c (copyright_string): Update years of copyrights.
+
+1997-09-03 Paul Eggert <eggert@twinsun.com>
+
+ * configure.in (VERSION): Bump to 2.5.1.
+ * inp.c (re_input): Don't free buffers twice when input is garbled.
+ * patch.c (main): If skipping patch and Plan A fails, don't
+ bother trying Plan B.
+
1997-08-31 Paul Eggert <eggert@twinsun.com>
* configure.in (VERSION): Version 2.5 released.
diff --git a/Makefile.in b/Makefile.in
index c73010a..98a1a06 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,5 +1,5 @@
# Makefile for GNU patch.
-# Copyright 1993, 1997 Free Software Foundation, Inc.
+# Copyright 1993, 1997, 1998 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
@@ -37,6 +37,7 @@ LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
PACKAGE = @PACKAGE@
+U = @U@
VERSION = @VERSION@
prefix = @prefix@
@@ -56,15 +57,18 @@ CONFIG_STATUS = config.status
SHELL = /bin/sh
-LIBSRCS = getopt.c getopt1.c memchr.c rename.c
-SRCS = addext.c argmatch.c backupfile.c basename.c inp.c maketime.c \
- partime.c patch.c pch.c quotearg.c util.c version.c $(LIBSRCS)
-OBJS = addext.o argmatch.o backupfile.o basename.o inp.o maketime.o \
- partime.o patch.o pch.o quotearg.o util.o version.o $(LIBOBJS)
-HDRS = argmatch.h backupfile.h common.h getopt.h \
- inp.h maketime.h partime.h pch.h quotearg.h util.h version.h
-MISC = COPYING ChangeLog INSTALL Makefile.in NEWS README \
- acconfig.h config.hin configure configure.in \
+LIBSRCS = getopt.c getopt1.c malloc.c memchr.c realloc.c rename.c
+SRCS = addext.c argmatch.c backupfile.c basename.c error.c inp.c maketime.c \
+ partime.c patch.c pch.c quotearg.c quotesys.c \
+ util.c version.c xmalloc.c $(LIBSRCS)
+OBJS = addext.o argmatch.o backupfile.o basename.o error.o inp.o maketime.o \
+ partime.o patch.o pch.o quotearg$U.o quotesys.o \
+ util.o version.o xmalloc.o $(LIBOBJS)
+HDRS = argmatch.h backupfile.h common.h error.h getopt.h \
+ inp.h maketime.h partime.h pch.h quotearg.h quotesys.h \
+ util.h version.h xalloc.h
+MISC = AUTHORS COPYING ChangeLog INSTALL Makefile.in NEWS README \
+ acconfig.h aclocal.m4 ansi2knr.c config.hin configure configure.in \
install-sh mkinstalldirs patch.man
DISTFILES = $(MISC) $(SRCS) $(HDRS)
DISTFILES_PC = pc/chdirsaf.c
@@ -116,10 +120,11 @@ patchlevel.h: Makefile
TAGS: $(HDRS) patchlevel.h $(SRCS)
etags $(HDRS) patchlevel.h $(SRCS)
-clean::
- rm -f patch core* *core *.o
+mostlyclean::
+ rm -f ansi2knr core* *core *.o *_.c
-mostlyclean:: clean
+clean:: mostlyclean
+ rm -f patch
distclean:: clean
rm -f Makefile config.cache config.log config.status config.h
@@ -142,17 +147,30 @@ dist:: $(DISTFILES) $(DISTFILES_PC) $(DISTFILES_PC_DJGPP)
tar -chf - $(PV) | gzip -9 >$(PV).tar.gz
rm -rf $(PV)
+ansi2knr.o: config.h
+ansi2knr: ansi2knr.o
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) ansi2knr.o $(LIBS)
+quotearg_.c: ansi2knr
+.SUFFIXES: _.c
+.c_.c:
+ ./ansi2knr $< $@
+
$(OBJS): config.h
addext.o: backupfile.h
-argmatch.o: argmatch.h
+argmatch.o: argmatch.h quotearg.h
backupfile.o: argmatch.h backupfile.h
basename.o: backupfile.h
+error.o: error.h
getopt.o getopt1.o: getopt.h
maketime.o: maketime.h partime.h
-inp.o: backupfile.h common.h inp.h pch.h util.h
+inp.o: backupfile.h common.h inp.h pch.h quotearg.h util.h xalloc.h
partime.o: partime.h
-patch.o: argmatch.h backupfile.h common.h getopt.h inp.h pch.h util.h version.h
-pch.o: common.h inp.h pch.h util.h
-quotearg.o: quotearg.h
-util.o: backupfile.h common.h maketime.h partime.h quotearg.h util.h version.h
+patch.o: argmatch.h backupfile.h common.h getopt.h inp.h \
+ pch.h quotearg.h util.h version.h xalloc.h
+pch.o: common.h inp.h pch.h quotearg.h util.h
+quotearg$U.o: quotearg.h xalloc.h
+quotesys.o: quotesys.h
+xmalloc.o: xalloc.h
+util.o: backupfile.h common.h maketime.h \
+ partime.h quotearg.h quotesys.h util.h version.h xalloc.h
version.o: common.h patchlevel.h util.h version.h
diff --git a/NEWS b/NEWS
index e984ba7..a8169e6 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,31 @@ Known problems:
* The diffutils 2.7 documentation for `patch' is obsolete; this should be
fixed in diffutils 2.8. Until then, see `patch --help' or `man patch'.
+Changes since version 2.5:
+
+* A security hole has been closed.
+ It involved race conditions with temporary files.
+
+* The default quoting style is 'shell', which causes `patch' to quote
+ file names with funny characters like `$'. This prevents their
+ misinterpretation if you cut them from its output and paste them into
+ the shell.
+
+* `patch' now works correctly with large files on Large File Summit
+ hosts like Solaris 2.6.
+
+* `patch' now ignores trailing carriage returns in lines of context diffs
+ if the context diff headers end in carriage return.
+
+* New options:
+ --posix
+ --quoting-style=WORD
+
+* New environment variables:
+ QUOTING_STYLE
+
+* `patch' now supports ClearCase version management.
+
Changes in version 2.5:
* Version control is now independent of whether backups are made.
diff --git a/acconfig.h b/acconfig.h
index 42e3e60..d7f3c84 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -7,8 +7,20 @@
directory headers. */
#undef D_INO_IN_DIRENT
+/* Define if you have a working <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
/* Define if memchr works. */
#undef HAVE_MEMCHR
/* Define if `struct utimbuf' is declared -- usually in <utime.h>. */
#undef HAVE_STRUCT_UTIMBUF
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to 1 if ANSI function prototypes are usable. */
+#undef PROTOTYPES
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644
index 0000000..4ebfbc6
--- /dev/null
+++ b/aclocal.m4
@@ -0,0 +1,197 @@
+#serial 1
+
+dnl From Jim Meyering.
+dnl Determine whether malloc accepts 0 as its argument.
+dnl If it doesn't, arrange to use the replacement function.
+dnl
+dnl If you use this macro in a package, you should
+dnl add the following two lines to acconfig.h:
+dnl /* Define to rpl_malloc if the replacement function should be used. */
+dnl #undef malloc
+dnl
+
+AC_DEFUN(jm_FUNC_MALLOC,
+[
+ if test x = y; then
+ dnl This code is deliberately never run via ./configure.
+ dnl FIXME: this is a gross hack to make autoheader put an entry
+ dnl for this symbol in config.h.in.
+ AC_CHECK_FUNCS(DONE_WORKING_MALLOC_CHECK)
+ fi
+ dnl xmalloc.c requires that this symbol be defined so it doesn't
+ dnl mistakenly use a broken malloc -- as it might if this test were omitted.
+ ac_kludge=HAVE_DONE_WORKING_MALLOC_CHECK
+ AC_DEFINE_UNQUOTED($ac_kludge)
+
+ AC_CACHE_CHECK([for working malloc], jm_cv_func_working_malloc,
+ [AC_TRY_RUN([
+ char *malloc ();
+ int
+ main ()
+ {
+ exit (malloc (0) ? 0 : 1);
+ }
+ ],
+ jm_cv_func_working_malloc=yes,
+ jm_cv_func_working_malloc=no,
+ dnl When crosscompiling, assume malloc is broken.
+ jm_cv_func_working_malloc=no)
+ ])
+ if test $jm_cv_func_working_malloc = no; then
+ LIBOBJS="$LIBOBJS malloc.o"
+ AC_DEFINE_UNQUOTED(malloc, rpl_malloc)
+ fi
+])
+
+#serial 1
+
+dnl From Jim Meyering.
+dnl Determine whether realloc works when both arguments are 0.
+dnl If it doesn't, arrange to use the replacement function.
+dnl
+dnl If you use this macro in a package, you should
+dnl add the following two lines to acconfig.h:
+dnl /* Define to rpl_realloc if the replacement function should be used. */
+dnl #undef realloc
+dnl
+
+AC_DEFUN(jm_FUNC_REALLOC,
+[
+ if test x = y; then
+ dnl This code is deliberately never run via ./configure.
+ dnl FIXME: this is a gross hack to make autoheader put an entry
+ dnl for this symbol in config.h.in.
+ AC_CHECK_FUNCS(DONE_WORKING_REALLOC_CHECK)
+ fi
+ dnl xmalloc.c requires that this symbol be defined so it doesn't
+ dnl mistakenly use a broken realloc -- as it might if this test were omitted.
+ ac_kludge=HAVE_DONE_WORKING_REALLOC_CHECK
+ AC_DEFINE_UNQUOTED($ac_kludge)
+
+ AC_CACHE_CHECK([for working realloc], jm_cv_func_working_realloc,
+ [AC_TRY_RUN([
+ char *realloc ();
+ int
+ main ()
+ {
+ exit (realloc (0, 0) ? 0 : 1);
+ }
+ ],
+ jm_cv_func_working_realloc=yes,
+ jm_cv_func_working_realloc=no,
+ dnl When crosscompiling, assume realloc is broken.
+ jm_cv_func_working_realloc=no)
+ ])
+ if test $jm_cv_func_working_realloc = no; then
+ LIBOBJS="$LIBOBJS realloc.o"
+ AC_DEFINE_UNQUOTED(realloc, rpl_realloc)
+ fi
+])
+
+# serial 1
+
+AC_DEFUN(AM_C_PROTOTYPES,
+[AC_REQUIRE([AM_PROG_CC_STDC])
+AC_MSG_CHECKING([for function prototypes])
+if test "$am_cv_prog_cc_stdc" != no; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(PROTOTYPES)
+ U= ANSI2KNR=
+else
+ AC_MSG_RESULT(no)
+ U=_ ANSI2KNR=./ansi2knr
+ # Ensure some checks needed by ansi2knr itself.
+ AC_HEADER_STDC
+ AC_CHECK_HEADERS(string.h)
+fi
+AC_SUBST(U)dnl
+AC_SUBST(ANSI2KNR)dnl
+])
+
+
+# serial 1
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so. This macro tries various
+# options that select ANSI C on some system or another. It considers the
+# compiler to be in ANSI C mode if it handles function prototypes correctly.
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN(AM_PROG_CC_STDC,
+[AC_REQUIRE([AC_PROG_CC])
+AC_BEFORE([$0], [AC_C_INLINE])
+AC_BEFORE([$0], [AC_C_CONST])
+dnl Force this before AC_PROG_CPP. Some cpp's, eg on HPUX, require
+dnl a magic option to avoid problems with ANSI preprocessor commands
+dnl like #elif.
+dnl FIXME: can't do this because then AC_AIX won't work due to a
+dnl circular dependency.
+dnl AC_BEFORE([$0], [AC_PROG_CPP])
+AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(am_cv_prog_cc_stdc,
+[am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ AC_TRY_COMPILE(
+[#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+], [
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+],
+[am_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CC="$ac_save_CC"
+])
+if test -z "$am_cv_prog_cc_stdc"; then
+ AC_MSG_RESULT([none needed])
+else
+ AC_MSG_RESULT($am_cv_prog_cc_stdc)
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+])
diff --git a/ansi2knr.c b/ansi2knr.c
new file mode 100644
index 0000000..c6ee833
--- /dev/null
+++ b/ansi2knr.c
@@ -0,0 +1,550 @@
+/* ansi2knr.c */
+/* Convert ANSI C function definitions to K&R ("traditional C") syntax */
+
+/*
+ansi2knr is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY. No author or distributor accepts responsibility to anyone for the
+consequences of using it or for whether it serves any particular purpose or
+works at all, unless he says so in writing. Refer to the GNU General Public
+License (the "GPL") for full details.
+
+Everyone is granted permission to copy, modify and redistribute ansi2knr,
+but only under the conditions described in the GPL. A copy of this license
+is supposed to have been given to you along with ansi2knr so you can know
+your rights and responsibilities. It should be in a file named COPYLEFT.
+Among other things, the copyright notice and this notice must be preserved
+on all copies.
+
+We explicitly state here what we believe is already implied by the GPL: if
+the ansi2knr program is distributed as a separate set of sources and a
+separate executable file which are aggregated on a storage medium together
+with another program, this in itself does not bring the other program under
+the GPL, nor does the mere fact that such a program or the procedures for
+constructing it invoke the ansi2knr executable bring any other part of the
+program under the GPL.
+*/
+
+/*
+ * Usage:
+ ansi2knr input_file [output_file]
+ * If no output_file is supplied, output goes to stdout.
+ * There are no error messages.
+ *
+ * ansi2knr recognizes function definitions by seeing a non-keyword
+ * identifier at the left margin, followed by a left parenthesis,
+ * with a right parenthesis as the last character on the line,
+ * and with a left brace as the first token on the following line
+ * (ignoring possible intervening comments).
+ * It will recognize a multi-line header provided that no intervening
+ * line ends with a left or right brace or a semicolon.
+ * These algorithms ignore whitespace and comments, except that
+ * the function name must be the first thing on the line.
+ * The following constructs will confuse it:
+ * - Any other construct that starts at the left margin and
+ * follows the above syntax (such as a macro or function call).
+ * - Some macros that tinker with the syntax of the function header.
+ */
+
+/*
+ * The original and principal author of ansi2knr is L. Peter Deutsch
+ * <ghost@aladdin.com>. Other authors are noted in the change history
+ * that follows (in reverse chronological order):
+ lpd 96-01-21 added code to cope with not HAVE_CONFIG_H and with
+ compilers that don't understand void, as suggested by
+ Tom Lane
+ lpd 96-01-15 changed to require that the first non-comment token
+ on the line following a function header be a left brace,
+ to reduce sensitivity to macros, as suggested by Tom Lane
+ <tgl@sss.pgh.pa.us>
+ lpd 95-06-22 removed #ifndefs whose sole purpose was to define
+ undefined preprocessor symbols as 0; changed all #ifdefs
+ for configuration symbols to #ifs
+ lpd 95-04-05 changed copyright notice to make it clear that
+ including ansi2knr in a program does not bring the entire
+ program under the GPL
+ lpd 94-12-18 added conditionals for systems where ctype macros
+ don't handle 8-bit characters properly, suggested by
+ Francois Pinard <pinard@iro.umontreal.ca>;
+ removed --varargs switch (this is now the default)
+ lpd 94-10-10 removed CONFIG_BROKETS conditional
+ lpd 94-07-16 added some conditionals to help GNU `configure',
+ suggested by Francois Pinard <pinard@iro.umontreal.ca>;
+ properly erase prototype args in function parameters,
+ contributed by Jim Avera <jima@netcom.com>;
+ correct error in writeblanks (it shouldn't erase EOLs)
+ lpd 89-xx-xx original version
+ */
+
+/* Most of the conditionals here are to make ansi2knr work with */
+/* or without the GNU configure machinery. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+
+#if HAVE_CONFIG_H
+
+/*
+ For properly autoconfiguring ansi2knr, use AC_CONFIG_HEADER(config.h).
+ This will define HAVE_CONFIG_H and so, activate the following lines.
+ */
+
+# if STDC_HEADERS || HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+#else /* not HAVE_CONFIG_H */
+
+/* Otherwise do it the hard way */
+
+# ifdef BSD
+# include <strings.h>
+# else
+# ifdef VMS
+ extern int strlen(), strncmp();
+# else
+# include <string.h>
+# endif
+# endif
+
+#endif /* not HAVE_CONFIG_H */
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+/*
+ malloc and free should be declared in stdlib.h,
+ but if you've got a K&R compiler, they probably aren't.
+ */
+# ifdef MSDOS
+# include <malloc.h>
+# else
+# ifdef VMS
+ extern char *malloc();
+ extern void free();
+# else
+ extern char *malloc();
+ extern int free();
+# endif
+# endif
+
+#endif
+
+/*
+ * The ctype macros don't always handle 8-bit characters correctly.
+ * Compensate for this here.
+ */
+#ifdef isascii
+# undef HAVE_ISASCII /* just in case */
+# define HAVE_ISASCII 1
+#else
+#endif
+#if STDC_HEADERS || !HAVE_ISASCII
+# define is_ascii(c) 1
+#else
+# define is_ascii(c) isascii(c)
+#endif
+
+#define is_space(c) (is_ascii(c) && isspace(c))
+#define is_alpha(c) (is_ascii(c) && isalpha(c))
+#define is_alnum(c) (is_ascii(c) && isalnum(c))
+
+/* Scanning macros */
+#define isidchar(ch) (is_alnum(ch) || (ch) == '_')
+#define isidfirstchar(ch) (is_alpha(ch) || (ch) == '_')
+
+/* Forward references */
+char *skipspace();
+int writeblanks();
+int test1();
+int convert1();
+
+/* The main program */
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{ FILE *in, *out;
+#define bufsize 5000 /* arbitrary size */
+ char *buf;
+ char *line;
+ char *more;
+ /*
+ * In previous versions, ansi2knr recognized a --varargs switch.
+ * If this switch was supplied, ansi2knr would attempt to convert
+ * a ... argument to va_alist and va_dcl; if this switch was not
+ * supplied, ansi2knr would simply drop any such arguments.
+ * Now, ansi2knr always does this conversion, and we only
+ * check for this switch for backward compatibility.
+ */
+ int convert_varargs = 1;
+
+ if ( argc > 1 && argv[1][0] == '-' )
+ { if ( !strcmp(argv[1], "--varargs") )
+ { convert_varargs = 1;
+ argc--;
+ argv++;
+ }
+ else
+ { fprintf(stderr, "Unrecognized switch: %s\n", argv[1]);
+ exit(1);
+ }
+ }
+ if (argc < 2 || argc > 3)
+ {
+ printf("Usage: ansi2knr input_file [output_file]\n");
+ exit(1);
+ }
+ in = fopen(argv[1], "r");
+ if ( in == NULL )
+ {
+ fprintf(stderr, "Cannot open input file %s\n", argv[1]);
+ exit(1);
+ }
+ if (argc == 3)
+ {
+ out = fopen(argv[2], "w");
+ if ( out == NULL )
+ {
+ fprintf(stderr, "Cannot open output file %s\n", argv[2]);
+ exit(1);
+ }
+ }
+ else
+ {
+ out = stdout;
+ }
+ fprintf(out, "#line 1 \"%s\"\n", argv[1]);
+ buf = malloc(bufsize);
+ line = buf;
+ while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
+ {
+test: line += strlen(line);
+ switch ( test1(buf) )
+ {
+ case 2: /* a function header */
+ convert1(buf, out, 1, convert_varargs);
+ break;
+ case 1: /* a function */
+ /* Check for a { at the start of the next line. */
+ more = ++line;
+f: if ( line >= buf + (bufsize - 1) ) /* overflow check */
+ goto wl;
+ if ( fgets(line, (unsigned)(buf + bufsize - line), in) == NULL )
+ goto wl;
+ switch ( *skipspace(more, 1) )
+ {
+ case '{':
+ /* Definitely a function header. */
+ convert1(buf, out, 0, convert_varargs);
+ fputs(more, out);
+ break;
+ case 0:
+ /* The next line was blank or a comment: */
+ /* keep scanning for a non-comment. */
+ line += strlen(line);
+ goto f;
+ default:
+ /* buf isn't a function header, but */
+ /* more might be. */
+ fputs(buf, out);
+ strcpy(buf, more);
+ line = buf;
+ goto test;
+ }
+ break;
+ case -1: /* maybe the start of a function */
+ if ( line != buf + (bufsize - 1) ) /* overflow check */
+ continue;
+ /* falls through */
+ default: /* not a function */
+wl: fputs(buf, out);
+ break;
+ }
+ line = buf;
+ }
+ if ( line != buf )
+ fputs(buf, out);
+ free(buf);
+ fclose(out);
+ fclose(in);
+ return 0;
+}
+
+/* Skip over space and comments, in either direction. */
+char *
+skipspace(p, dir)
+ register char *p;
+ register int dir; /* 1 for forward, -1 for backward */
+{ for ( ; ; )
+ { while ( is_space(*p) )
+ p += dir;
+ if ( !(*p == '/' && p[dir] == '*') )
+ break;
+ p += dir; p += dir;
+ while ( !(*p == '*' && p[dir] == '/') )
+ { if ( *p == 0 )
+ return p; /* multi-line comment?? */
+ p += dir;
+ }
+ p += dir; p += dir;
+ }
+ return p;
+}
+
+/*
+ * Write blanks over part of a string.
+ * Don't overwrite end-of-line characters.
+ */
+int
+writeblanks(start, end)
+ char *start;
+ char *end;
+{ char *p;
+ for ( p = start; p < end; p++ )
+ if ( *p != '\r' && *p != '\n' )
+ *p = ' ';
+ return 0;
+}
+
+/*
+ * Test whether the string in buf is a function definition.
+ * The string may contain and/or end with a newline.
+ * Return as follows:
+ * 0 - definitely not a function definition;
+ * 1 - definitely a function definition;
+ * 2 - definitely a function prototype (NOT USED);
+ * -1 - may be the beginning of a function definition,
+ * append another line and look again.
+ * The reason we don't attempt to convert function prototypes is that
+ * Ghostscript's declaration-generating macros look too much like
+ * prototypes, and confuse the algorithms.
+ */
+int
+test1(buf)
+ char *buf;
+{ register char *p = buf;
+ char *bend;
+ char *endfn;
+ int contin;
+
+ if ( !isidfirstchar(*p) )
+ return 0; /* no name at left margin */
+ bend = skipspace(buf + strlen(buf) - 1, -1);
+ switch ( *bend )
+ {
+ case ';': contin = 0 /*2*/; break;
+ case ')': contin = 1; break;
+ case '{': return 0; /* not a function */
+ case '}': return 0; /* not a function */
+ default: contin = -1;
+ }
+ while ( isidchar(*p) )
+ p++;
+ endfn = p;
+ p = skipspace(p, 1);
+ if ( *p++ != '(' )
+ return 0; /* not a function */
+ p = skipspace(p, 1);
+ if ( *p == ')' )
+ return 0; /* no parameters */
+ /* Check that the apparent function name isn't a keyword. */
+ /* We only need to check for keywords that could be followed */
+ /* by a left parenthesis (which, unfortunately, is most of them). */
+ { static char *words[] =
+ { "asm", "auto", "case", "char", "const", "double",
+ "extern", "float", "for", "if", "int", "long",
+ "register", "return", "short", "signed", "sizeof",
+ "static", "switch", "typedef", "unsigned",
+ "void", "volatile", "while", 0
+ };
+ char **key = words;
+ char *kp;
+ int len = endfn - buf;
+
+ while ( (kp = *key) != 0 )
+ { if ( strlen(kp) == len && !strncmp(kp, buf, len) )
+ return 0; /* name is a keyword */
+ key++;
+ }
+ }
+ return contin;
+}
+
+/* Convert a recognized function definition or header to K&R syntax. */
+int
+convert1(buf, out, header, convert_varargs)
+ char *buf;
+ FILE *out;
+ int header; /* Boolean */
+ int convert_varargs; /* Boolean */
+{ char *endfn;
+ register char *p;
+ /*
+ * The breaks table contains pointers to the beginning and end
+ * of each argument.
+ */
+ char **breaks;
+ unsigned num_breaks = 2; /* for testing */
+ char **btop;
+ char **bp;
+ char **ap;
+ char *vararg = 0;
+
+ /* Pre-ANSI implementations don't agree on whether strchr */
+ /* is called strchr or index, so we open-code it here. */
+ for ( endfn = buf; *(endfn++) != '('; )
+ ;
+top: p = endfn;
+ breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
+ if ( breaks == 0 )
+ { /* Couldn't allocate break table, give up */
+ fprintf(stderr, "Unable to allocate break table!\n");
+ fputs(buf, out);
+ return -1;
+ }
+ btop = breaks + num_breaks * 2 - 2;
+ bp = breaks;
+ /* Parse the argument list */
+ do
+ { int level = 0;
+ char *lp = NULL;
+ char *rp;
+ char *end = NULL;
+
+ if ( bp >= btop )
+ { /* Filled up break table. */
+ /* Allocate a bigger one and start over. */
+ free((char *)breaks);
+ num_breaks <<= 1;
+ goto top;
+ }
+ *bp++ = p;
+ /* Find the end of the argument */
+ for ( ; end == NULL; p++ )
+ { switch(*p)
+ {
+ case ',':
+ if ( !level ) end = p;
+ break;
+ case '(':
+ if ( !level ) lp = p;
+ level++;
+ break;
+ case ')':
+ if ( --level < 0 ) end = p;
+ else rp = p;
+ break;
+ case '/':
+ p = skipspace(p, 1) - 1;
+ break;
+ default:
+ ;
+ }
+ }
+ /* Erase any embedded prototype parameters. */
+ if ( lp )
+ writeblanks(lp + 1, rp);
+ p--; /* back up over terminator */
+ /* Find the name being declared. */
+ /* This is complicated because of procedure and */
+ /* array modifiers. */
+ for ( ; ; )
+ { p = skipspace(p - 1, -1);
+ switch ( *p )
+ {
+ case ']': /* skip array dimension(s) */
+ case ')': /* skip procedure args OR name */
+ { int level = 1;
+ while ( level )
+ switch ( *--p )
+ {
+ case ']': case ')': level++; break;
+ case '[': case '(': level--; break;
+ case '/': p = skipspace(p, -1) + 1; break;
+ default: ;
+ }
+ }
+ if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
+ { /* We found the name being declared */
+ while ( !isidfirstchar(*p) )
+ p = skipspace(p, 1) + 1;
+ goto found;
+ }
+ break;
+ default:
+ goto found;
+ }
+ }
+found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
+ { if ( convert_varargs )
+ { *bp++ = "va_alist";
+ vararg = p-2;
+ }
+ else
+ { p++;
+ if ( bp == breaks + 1 ) /* sole argument */
+ writeblanks(breaks[0], p);
+ else
+ writeblanks(bp[-1] - 1, p);
+ bp--;
+ }
+ }
+ else
+ { while ( isidchar(*p) ) p--;
+ *bp++ = p+1;
+ }
+ p = end;
+ }
+ while ( *p++ == ',' );
+ *bp = p;
+ /* Make a special check for 'void' arglist */
+ if ( bp == breaks+2 )
+ { p = skipspace(breaks[0], 1);
+ if ( !strncmp(p, "void", 4) )
+ { p = skipspace(p+4, 1);
+ if ( p == breaks[2] - 1 )
+ { bp = breaks; /* yup, pretend arglist is empty */
+ writeblanks(breaks[0], p + 1);
+ }
+ }
+ }
+ /* Put out the function name and left parenthesis. */
+ p = buf;
+ while ( p != endfn ) putc(*p, out), p++;
+ /* Put out the declaration. */
+ if ( header )
+ { fputs(");", out);
+ for ( p = breaks[0]; *p; p++ )
+ if ( *p == '\r' || *p == '\n' )
+ putc(*p, out);
+ }
+ else
+ { for ( ap = breaks+1; ap < bp; ap += 2 )
+ { p = *ap;
+ while ( isidchar(*p) )
+ putc(*p, out), p++;
+ if ( ap < bp - 1 )
+ fputs(", ", out);
+ }
+ fputs(") ", out);
+ /* Put out the argument declarations */
+ for ( ap = breaks+2; ap <= bp; ap += 2 )
+ (*ap)[-1] = ';';
+ if ( vararg != 0 )
+ { *vararg = 0;
+ fputs(breaks[0], out); /* any prior args */
+ fputs("va_dcl", out); /* the final arg */
+ fputs(bp[0], out);
+ }
+ else
+ fputs(breaks[0], out);
+ }
+ free((char *)breaks);
+ return 0;
+}
diff --git a/argmatch.c b/argmatch.c
index aa55933..5b22d6f 100644
--- a/argmatch.c
+++ b/argmatch.c
@@ -22,10 +22,11 @@
# include <config.h>
#endif
-#include <argmatch.h>
-
#include <sys/types.h>
+#include <argmatch.h>
+#include <quotearg.h>
+
#include <stdio.h>
#if HAVE_STRING_H
# include <string.h>
@@ -83,10 +84,7 @@ invalid_arg (kind, value, problem)
const char *value;
int problem;
{
- fprintf (stderr, "%s: ", program_name);
- if (problem == -1)
- fprintf (stderr, "invalid");
- else /* Assume -2. */
- fprintf (stderr, "ambiguous");
- fprintf (stderr, " %s `%s'\n", kind, value);
+ fprintf (stderr,
+ problem == -1 ? "%s: invalid %s %s\n" : "%s: ambiguous %s %s\n",
+ program_name, kind, quotearg (value));
}
diff --git a/common.h b/common.h
index b2895d4..d10330c 100644
--- a/common.h
+++ b/common.h
@@ -1,10 +1,10 @@
/* common definitions for `patch' */
-/* $Id: common.h,v 1.18 1997/06/13 06:28:37 eggert Exp $ */
+/* $Id: common.h,v 1.19 1998/03/15 14:44:47 eggert Exp $ */
/*
Copyright 1986, 1988 Larry Wall
-Copyright 1990, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
+Copyright 1990, 1991, 1992, 1993, 1997, 1998 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
@@ -84,11 +84,33 @@ If not, write to the Free Software Foundation,
#if HAVE_LIMITS_H
# include <limits.h>
#endif
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+/* The extra casts work around common compiler bugs,
+ e.g. Cray C 5.0.3.0 time_t. */
+#define TYPE_SIGNED(t) ((t) -1 < (t) 0)
+#define TYPE_MINIMUM(t) ((t) (TYPE_SIGNED (t) \
+ ? (t) (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)) \
+ : (t) 0))
+#define TYPE_MAXIMUM(t) ((t) ((t) ~ (t) 0 - TYPE_MINIMUM (t)))
+#ifndef CHAR_MAX
+#define CHAR_MAX TYPE_MAXIMUM (char)
+#endif
#ifndef INT_MAX
-#define INT_MAX 2147483647
+#define INT_MAX TYPE_MAXIMUM (int)
#endif
#ifndef LONG_MIN
-#define LONG_MIN (-1-2147483647L)
+#define LONG_MIN TYPE_MINIMUM (long)
+#endif
+
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifndef SIZE_MAX
+/* On some nonstandard hosts, size_t is signed,
+ so SIZE_MAX != (size_t) -1. */
+#define SIZE_MAX TYPE_MAXIMUM (size_t)
#endif
#include <ctype.h>
@@ -137,7 +159,7 @@ If not, write to the Free Software Foundation,
/* typedefs */
typedef int bool; /* must promote to itself */
-typedef long LINENUM; /* must be signed */
+typedef off_t LINENUM; /* must be signed */
/* globals */
@@ -159,10 +181,14 @@ XTERN bool posixly_correct;
XTERN char const *origprae;
XTERN char const *origbase;
-XTERN char const * volatile TMPOUTNAME;
XTERN char const * volatile TMPINNAME;
+XTERN char const * volatile TMPOUTNAME;
XTERN char const * volatile TMPPATNAME;
+XTERN int volatile TMPINNAME_needs_removal;
+XTERN int volatile TMPOUTNAME_needs_removal;
+XTERN int volatile TMPPATNAME_needs_removal;
+
#ifdef DEBUGGING
XTERN int debug;
#else
@@ -212,7 +238,6 @@ XTERN char *revision; /* prerequisite revision, if any */
# endif
#endif
-GENERIC_OBJECT *xmalloc PARAMS ((size_t));
void fatal_exit PARAMS ((int)) __attribute__ ((noreturn));
#include <errno.h>
@@ -233,7 +258,6 @@ GENERIC_OBJECT *memchr ();
#if STDC_HEADERS
# include <stdlib.h>
#else
-long atol ();
char *getenv ();
GENERIC_OBJECT *malloc ();
GENERIC_OBJECT *realloc ();
@@ -288,6 +312,9 @@ off_t lseek ();
#ifndef O_CREAT
#define O_CREAT 0
#endif
+#ifndef O_EXCL
+#define O_EXCL 0
+#endif
#ifndef O_TRUNC
#define O_TRUNC 0
#endif
diff --git a/config.hin b/config.hin
index ac2aa7e..e18abfa 100644
--- a/config.hin
+++ b/config.hin
@@ -51,12 +51,30 @@
directory headers. */
#undef D_INO_IN_DIRENT
+/* Define if you have a working <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
/* Define if memchr works. */
#undef HAVE_MEMCHR
/* Define if `struct utimbuf' is declared -- usually in <utime.h>. */
#undef HAVE_STRUCT_UTIMBUF
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to 1 if ANSI function prototypes are usable. */
+#undef PROTOTYPES
+
+/* Define to rpl_realloc if the replacement function should be used. */
+#undef realloc
+
+/* Define if you have the DONE_WORKING_MALLOC_CHECK function. */
+#undef HAVE_DONE_WORKING_MALLOC_CHECK
+
+/* Define if you have the DONE_WORKING_REALLOC_CHECK function. */
+#undef HAVE_DONE_WORKING_REALLOC_CHECK
+
/* Define if you have the _doprintf function. */
#undef HAVE__DOPRINTF
@@ -93,6 +111,9 @@
/* Define if you have the sigsetmask function. */
#undef HAVE_SIGSETMASK
+/* Define if you have the strerror function. */
+#undef HAVE_STRERROR
+
/* Define if you have the <dirent.h> header file. */
#undef HAVE_DIRENT_H
diff --git a/configure b/configure
index 125632a..18388cb 100755
--- a/configure
+++ b/configure
@@ -540,7 +540,7 @@ test "$program_transform_name" = "" && program_transform_name="s,x,x,"
PACKAGE=patch
-VERSION=2.5
+VERSION=2.5.3
@@ -1044,13 +1044,253 @@ else
fi
+
+
+
+echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6
+echo "configure:1052: checking for ${CC-cc} option to accept ANSI C" >&5
+if eval "test \"`echo '$''{'am_cv_prog_cc_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ cat > conftest.$ac_ext <<EOF
+#line 1068 "configure"
+#include "confdefs.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+
+int main() {
+
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+
+; return 0; }
+EOF
+if { (eval echo configure:1105: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ am_cv_prog_cc_stdc="$ac_arg"; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+CC="$ac_save_CC"
+
+fi
+
+if test -z "$am_cv_prog_cc_stdc"; then
+ echo "$ac_t""none needed" 1>&6
+else
+ echo "$ac_t""$am_cv_prog_cc_stdc" 1>&6
+fi
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+
+
+echo $ac_n "checking for function prototypes""... $ac_c" 1>&6
+echo "configure:1130: checking for function prototypes" >&5
+if test "$am_cv_prog_cc_stdc" != no; then
+ echo "$ac_t""yes" 1>&6
+ cat >> confdefs.h <<\EOF
+#define PROTOTYPES 1
+EOF
+
+ U= ANSI2KNR=
+else
+ echo "$ac_t""no" 1>&6
+ U=_ ANSI2KNR=./ansi2knr
+ # Ensure some checks needed by ansi2knr itself.
+ echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:1143: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1148 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1156: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1173 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 1191 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1212 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:1223: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+ for ac_hdr in string.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:1250: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1255 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1260: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+fi
+
echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1049: checking for working const" >&5
+echo "configure:1289: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1054 "configure"
+#line 1294 "configure"
#include "confdefs.h"
int main() {
@@ -1099,7 +1339,7 @@ ccp = (char const *const *) p;
; return 0; }
EOF
-if { (eval echo configure:1103: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1343: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
@@ -1125,12 +1365,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1129: checking for $ac_hdr that defines DIR" >&5
+echo "configure:1369: checking for $ac_hdr that defines DIR" >&5
if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1134 "configure"
+#line 1374 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
@@ -1138,7 +1378,7 @@ int main() {
DIR *dirp = 0;
; return 0; }
EOF
-if { (eval echo configure:1142: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1382: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
@@ -1163,7 +1403,7 @@ done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1167: checking for opendir in -ldir" >&5
+echo "configure:1407: checking for opendir in -ldir" >&5
ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1171,7 +1411,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1175 "configure"
+#line 1415 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1182,7 +1422,7 @@ int main() {
opendir()
; return 0; }
EOF
-if { (eval echo configure:1186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1426: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1204,7 +1444,7 @@ fi
else
echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1208: checking for opendir in -lx" >&5
+echo "configure:1448: checking for opendir in -lx" >&5
ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1212,7 +1452,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1216 "configure"
+#line 1456 "configure"
#include "confdefs.h"
/* Override any gcc2 internal prototype to avoid an error. */
/* We use char because int might match the return type of a gcc2
@@ -1223,7 +1463,7 @@ int main() {
opendir()
; return 0; }
EOF
-if { (eval echo configure:1227: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1467: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1246,12 +1486,12 @@ fi
fi
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1250: checking for ANSI C header files" >&5
+echo "configure:1490: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1255 "configure"
+#line 1495 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -1259,7 +1499,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1263: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1503: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1276,7 +1516,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1280 "configure"
+#line 1520 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -1294,7 +1534,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1298 "configure"
+#line 1538 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -1315,7 +1555,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
-#line 1319 "configure"
+#line 1559 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1326,7 +1566,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
-if { (eval echo configure:1330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1570: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
:
else
@@ -1353,17 +1593,17 @@ for ac_hdr in fcntl.h limits.h string.h unistd.h utime.h varargs.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1357: checking for $ac_hdr" >&5
+echo "configure:1597: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1362 "configure"
+#line 1602 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1367: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1607: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1389,14 +1629,50 @@ else
fi
done
+
+# Use <inttypes.h> only if it exists,
+# doesn't clash with <sys/types.h>, and declares intmax_t.
+echo $ac_n "checking for inttypes.h""... $ac_c" 1>&6
+echo "configure:1637: checking for inttypes.h" >&5
+if eval "test \"`echo '$''{'patch_cv_header_inttypes_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1642 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <inttypes.h>
+int main() {
+intmax_t i = -1;
+; return 0; }
+EOF
+if { (eval echo configure:1650: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ patch_cv_header_inttypes_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ patch_cv_header_inttypes_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$patch_cv_header_inttypes_h" 1>&6
+if test $patch_cv_header_inttypes_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_INTTYPES_H 1
+EOF
+
+fi
echo $ac_n "checking for mode_t""... $ac_c" 1>&6
-echo "configure:1395: checking for mode_t" >&5
+echo "configure:1671: checking for mode_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1400 "configure"
+#line 1676 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -1424,12 +1700,12 @@ EOF
fi
echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:1428: checking for off_t" >&5
+echo "configure:1704: checking for off_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1433 "configure"
+#line 1709 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -1457,12 +1733,12 @@ EOF
fi
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:1461: checking return type of signal handlers" >&5
+echo "configure:1737: checking return type of signal handlers" >&5
if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1466 "configure"
+#line 1742 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -1479,7 +1755,7 @@ int main() {
int i;
; return 0; }
EOF
-if { (eval echo configure:1483: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
@@ -1498,12 +1774,12 @@ EOF
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:1502: checking for size_t" >&5
+echo "configure:1778: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1507 "configure"
+#line 1783 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -1532,12 +1808,12 @@ fi
echo $ac_n "checking for struct utimbuf""... $ac_c" 1>&6
-echo "configure:1536: checking for struct utimbuf" >&5
+echo "configure:1812: checking for struct utimbuf" >&5
if eval "test \"`echo '$''{'patch_cv_sys_struct_utimbuf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1541 "configure"
+#line 1817 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if HAVE_UTIME_H
@@ -1547,7 +1823,7 @@ int main() {
static struct utimbuf x; x.actime = x.modtime;
; return 0; }
EOF
-if { (eval echo configure:1551: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1827: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
patch_cv_sys_struct_utimbuf=yes
else
@@ -1569,7 +1845,7 @@ fi
# Check for NetBSD 1.0 bug, where memchr(..., 0) returns nonzero.
echo $ac_n "checking for working memchr""... $ac_c" 1>&6
-echo "configure:1573: checking for working memchr" >&5
+echo "configure:1849: checking for working memchr" >&5
if eval "test \"`echo '$''{'ac_cv_func_memchr'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1578,12 +1854,12 @@ else
ac_cv_func_memchr=no
else
cat > conftest.$ac_ext <<EOF
-#line 1582 "configure"
+#line 1858 "configure"
#include "confdefs.h"
#include <string.h>
main () { exit (memchr ("", 0, 0) != 0 || memchr ("", 1, 0) != 0); }
EOF
-if { (eval echo configure:1587: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1863: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
ac_cv_func_memchr=yes
else
@@ -1605,12 +1881,12 @@ EOF
fi
echo $ac_n "checking for getopt_long""... $ac_c" 1>&6
-echo "configure:1609: checking for getopt_long" >&5
+echo "configure:1885: checking for getopt_long" >&5
if eval "test \"`echo '$''{'ac_cv_func_getopt_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1614 "configure"
+#line 1890 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char getopt_long(); below. */
@@ -1633,7 +1909,7 @@ getopt_long();
; return 0; }
EOF
-if { (eval echo configure:1637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_getopt_long=yes"
else
@@ -1654,15 +1930,15 @@ LIBOBJS="$LIBOBJS getopt1.o getopt.o"
fi
-for ac_func in _doprintf isascii memcmp mkdir mktemp pathconf raise sigaction sigprocmask sigsetmask
+for ac_func in _doprintf isascii memcmp mkdir mktemp pathconf raise sigaction sigprocmask sigsetmask strerror
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1661: checking for $ac_func" >&5
+echo "configure:1937: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1666 "configure"
+#line 1942 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -1685,7 +1961,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1689: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1965: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1712,12 +1988,12 @@ done
for ac_func in memchr rename
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1716: checking for $ac_func" >&5
+echo "configure:1992: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1721 "configure"
+#line 1997 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -1740,7 +2016,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:1744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2020: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -1766,8 +2042,224 @@ fi
done
+
+ if test x = y; then
+ for ac_func in DONE_WORKING_MALLOC_CHECK
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2051: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2056 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2079: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ fi
+ ac_kludge=HAVE_DONE_WORKING_MALLOC_CHECK
+ cat >> confdefs.h <<EOF
+#define $ac_kludge 1
+EOF
+
+
+ echo $ac_n "checking for working malloc""... $ac_c" 1>&6
+echo "configure:2111: checking for working malloc" >&5
+if eval "test \"`echo '$''{'jm_cv_func_working_malloc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ jm_cv_func_working_malloc=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2119 "configure"
+#include "confdefs.h"
+
+ char *malloc ();
+ int
+ main ()
+ {
+ exit (malloc (0) ? 0 : 1);
+ }
+
+EOF
+if { (eval echo configure:2130: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ jm_cv_func_working_malloc=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ jm_cv_func_working_malloc=no
+fi
+rm -fr conftest*
+fi
+
+
+fi
+
+echo "$ac_t""$jm_cv_func_working_malloc" 1>&6
+ if test $jm_cv_func_working_malloc = no; then
+ LIBOBJS="$LIBOBJS malloc.o"
+ cat >> confdefs.h <<EOF
+#define malloc rpl_malloc
+EOF
+
+ fi
+
+
+ if test x = y; then
+ for ac_func in DONE_WORKING_REALLOC_CHECK
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2159: checking for $ac_func" >&5
+if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2164 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func(); below. */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:2187: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+fi
+
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+done
+
+ fi
+ ac_kludge=HAVE_DONE_WORKING_REALLOC_CHECK
+ cat >> confdefs.h <<EOF
+#define $ac_kludge 1
+EOF
+
+
+ echo $ac_n "checking for working realloc""... $ac_c" 1>&6
+echo "configure:2219: checking for working realloc" >&5
+if eval "test \"`echo '$''{'jm_cv_func_working_realloc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ jm_cv_func_working_realloc=no
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2227 "configure"
+#include "confdefs.h"
+
+ char *realloc ();
+ int
+ main ()
+ {
+ exit (realloc (0, 0) ? 0 : 1);
+ }
+
+EOF
+if { (eval echo configure:2238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+then
+ jm_cv_func_working_realloc=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ jm_cv_func_working_realloc=no
+fi
+rm -fr conftest*
+fi
+
+
+fi
+
+echo "$ac_t""$jm_cv_func_working_realloc" 1>&6
+ if test $jm_cv_func_working_realloc = no; then
+ LIBOBJS="$LIBOBJS realloc.o"
+ cat >> confdefs.h <<EOF
+#define realloc rpl_realloc
+EOF
+
+ fi
+
echo $ac_n "checking whether closedir returns void""... $ac_c" 1>&6
-echo "configure:1771: checking whether closedir returns void" >&5
+echo "configure:2263: checking whether closedir returns void" >&5
if eval "test \"`echo '$''{'ac_cv_func_closedir_void'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1775,13 +2267,13 @@ else
ac_cv_func_closedir_void=yes
else
cat > conftest.$ac_ext <<EOF
-#line 1779 "configure"
+#line 2271 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_header_dirent>
int closedir(); main() { exit(closedir(opendir(".")) != 0); }
EOF
-if { (eval echo configure:1785: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2277: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
ac_cv_func_closedir_void=no
else
@@ -1804,12 +2296,12 @@ EOF
fi
echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:1808: checking for vprintf" >&5
+echo "configure:2300: checking for vprintf" >&5
if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1813 "configure"
+#line 2305 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vprintf(); below. */
@@ -1832,7 +2324,7 @@ vprintf();
; return 0; }
EOF
-if { (eval echo configure:1836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_vprintf=yes"
else
@@ -1856,12 +2348,12 @@ fi
if test "$ac_cv_func_vprintf" != yes; then
echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:1860: checking for _doprnt" >&5
+echo "configure:2352: checking for _doprnt" >&5
if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1865 "configure"
+#line 2357 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char _doprnt(); below. */
@@ -1884,7 +2376,7 @@ _doprnt();
; return 0; }
EOF
-if { (eval echo configure:1888: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2380: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func__doprnt=yes"
else
@@ -1910,7 +2402,7 @@ fi
echo $ac_n "checking for long file names""... $ac_c" 1>&6
-echo "configure:1914: checking for long file names" >&5
+echo "configure:2406: checking for long file names" >&5
if eval "test \"`echo '$''{'ac_cv_sys_long_file_names'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@@ -1955,12 +2447,12 @@ fi
echo $ac_n "checking for d_ino member in directory struct""... $ac_c" 1>&6
-echo "configure:1959: checking for d_ino member in directory struct" >&5
+echo "configure:2451: checking for d_ino member in directory struct" >&5
if eval "test \"`echo '$''{'patch_cv_sys_d_ino_in_dirent'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1964 "configure"
+#line 2456 "configure"
#include "confdefs.h"
#include <sys/types.h>
@@ -1983,7 +2475,7 @@ int main() {
struct dirent dp; dp.d_ino = 0;
; return 0; }
EOF
-if { (eval echo configure:1987: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
patch_cv_sys_d_ino_in_dirent=yes
else
@@ -2142,6 +2634,8 @@ s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
s%@INSTALL_DATA@%$INSTALL_DATA%g
s%@SET_MAKE@%$SET_MAKE%g
s%@ed_PROGRAM@%$ed_PROGRAM%g
+s%@U@%$U%g
+s%@ANSI2KNR@%$ANSI2KNR%g
s%@LIBOBJS@%$LIBOBJS%g
CEOF
diff --git a/configure.in b/configure.in
index eb1c32b..ef5b09b 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
# Configure `patch'.
-# Copyright 1993, 1997 Free Software Foundation, Inc.
+# Copyright 1993, 1997, 1998 Free Software Foundation, Inc.
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.12)
@@ -8,7 +8,7 @@ AC_CONFIG_HEADER(config.h:config.hin)
AC_ARG_PROGRAM
PACKAGE=patch
-VERSION=2.5
+VERSION=2.5.3
AC_SUBST(PACKAGE)
AC_SUBST(VERSION)
@@ -56,11 +56,27 @@ AC_AIX
AC_MINIX
AC_ISC_POSIX
+AM_C_PROTOTYPES
AC_C_CONST
AC_HEADER_DIRENT
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h limits.h string.h unistd.h utime.h varargs.h)
+
+# Use <inttypes.h> only if it exists,
+# doesn't clash with <sys/types.h>, and declares intmax_t.
+AC_MSG_CHECKING(for inttypes.h)
+AC_CACHE_VAL(patch_cv_header_inttypes_h,
+[AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <inttypes.h>],
+ [intmax_t i = -1;],
+ patch_cv_header_inttypes_h=yes,
+ patch_cv_header_inttypes_h=no)])
+AC_MSG_RESULT($patch_cv_header_inttypes_h)
+if test $patch_cv_header_inttypes_h = yes; then
+ AC_DEFINE(HAVE_INTTYPES_H)
+fi
AC_TYPE_MODE_T
AC_TYPE_OFF_T
@@ -97,8 +113,10 @@ fi
AC_CHECK_FUNC(getopt_long, , [LIBOBJS="$LIBOBJS getopt1.o getopt.o"])
AC_SUBST(LIBOBJS)
-AC_CHECK_FUNCS(_doprintf isascii memcmp mkdir mktemp pathconf raise sigaction sigprocmask sigsetmask)
+AC_CHECK_FUNCS(_doprintf isascii memcmp mkdir mktemp pathconf raise sigaction sigprocmask sigsetmask strerror)
AC_REPLACE_FUNCS(memchr rename)
+jm_FUNC_MALLOC
+jm_FUNC_REALLOC
AC_FUNC_CLOSEDIR_VOID
AC_FUNC_VPRINTF
diff --git a/error.c b/error.c
new file mode 100644
index 0000000..66a4844
--- /dev/null
+++ b/error.c
@@ -0,0 +1,246 @@
+/* Error handler for noninteractive utilities
+ Copyright (C) 1990,91,92,93,94,95,96,97 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+
+#if HAVE_VPRINTF || HAVE_DOPRNT || _LIBC
+# if __STDC__
+# include <stdarg.h>
+# define VA_START(args, lastarg) va_start(args, lastarg)
+# else
+# include <varargs.h>
+# define VA_START(args, lastarg) va_start(args)
+# endif
+#else
+# define va_alist a1, a2, a3, a4, a5, a6, a7, a8
+# define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
+#endif
+
+#if STDC_HEADERS || _LIBC
+# include <stdlib.h>
+# include <string.h>
+#else
+void exit ();
+#endif
+
+#include "error.h"
+
+#ifndef _
+#define _(String) String
+#endif
+
+/* If NULL, error will flush stdout, then print on stderr the program
+ name, a colon and a space. Otherwise, error will call this
+ function without parameters instead. */
+void (*error_print_progname) (
+#if __STDC__ - 0
+ void
+#endif
+ );
+
+/* This variable is incremented each time `error' is called. */
+unsigned int error_message_count;
+
+#ifdef _LIBC
+/* In the GNU C library, there is a predefined variable for this. */
+
+#define program_name program_invocation_name
+#include <errno.h>
+
+/* In GNU libc we want do not want to use the common name `error' directly.
+ Instead make it a weak alias. */
+#define error __error
+#define error_at_line __error_at_line
+
+#else
+
+/* The calling program should define program_name and set it to the
+ name of the executing program. */
+extern char *program_name;
+
+#ifndef HAVE_STRERROR_R
+# if HAVE_STRERROR
+# ifndef strerror /* On some systems, strerror is a macro */
+char *strerror ();
+# endif
+# else
+static char *
+private_strerror (errnum)
+ int errnum;
+{
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+
+ if (errnum > 0 && errnum <= sys_nerr)
+ return _(sys_errlist[errnum]);
+ return _("Unknown system error");
+}
+# define strerror private_strerror
+# endif /* HAVE_STRERROR */
+#endif /* HAVE_STRERROR_R */
+#endif /* _LIBC */
+
+/* Print the program name and error message MESSAGE, which is a printf-style
+ format string with optional args.
+ If ERRNUM is nonzero, print its corresponding system error message.
+ Exit with status STATUS if it is nonzero. */
+/* VARARGS */
+
+void
+#if defined(VA_START) && __STDC__
+error (int status, int errnum, const char *message, ...)
+#else
+error (status, errnum, message, va_alist)
+ int status;
+ int errnum;
+ char *message;
+ va_dcl
+#endif
+{
+#ifdef VA_START
+ va_list args;
+#endif
+
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+ fflush (stdout);
+ fprintf (stderr, "%s: ", program_name);
+ }
+
+#ifdef VA_START
+ VA_START (args, message);
+# if HAVE_VPRINTF || _LIBC
+ vfprintf (stderr, message, args);
+# else
+ _doprnt (message, args, stderr);
+# endif
+ va_end (args);
+#else
+ fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
+#endif
+
+ ++error_message_count;
+ if (errnum)
+ {
+#if defined HAVE_STRERROR_R || defined _LIBC
+ char errbuf[1024];
+ fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf));
+#else
+ fprintf (stderr, ": %s", strerror (errnum));
+#endif
+ }
+ putc ('\n', stderr);
+ fflush (stderr);
+ if (status)
+ exit (status);
+}
+
+/* Sometimes we want to have at most one error per line. This
+ variable controls whether this mode is selected or not. */
+int error_one_per_line;
+
+void
+#if defined(VA_START) && __STDC__
+error_at_line (int status, int errnum, const char *file_name,
+ unsigned int line_number, const char *message, ...)
+#else
+error_at_line (status, errnum, file_name, line_number, message, va_alist)
+ int status;
+ int errnum;
+ const char *file_name;
+ unsigned int line_number;
+ char *message;
+ va_dcl
+#endif
+{
+#ifdef VA_START
+ va_list args;
+#endif
+
+ if (error_one_per_line)
+ {
+ static const char *old_file_name;
+ static unsigned int old_line_number;
+
+ if (old_line_number == line_number &&
+ (file_name == old_file_name || !strcmp (old_file_name, file_name)))
+ /* Simply return and print nothing. */
+ return;
+
+ old_file_name = file_name;
+ old_line_number = line_number;
+ }
+
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+ fflush (stdout);
+ fprintf (stderr, "%s:", program_name);
+ }
+
+ if (file_name != NULL)
+ fprintf (stderr, "%s:%d: ", file_name, line_number);
+
+#ifdef VA_START
+ VA_START (args, message);
+# if HAVE_VPRINTF || _LIBC
+ vfprintf (stderr, message, args);
+# else
+ _doprnt (message, args, stderr);
+# endif
+ va_end (args);
+#else
+ fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
+#endif
+
+ ++error_message_count;
+ if (errnum)
+ {
+#if defined HAVE_STRERROR_R || defined _LIBC
+ char errbuf[1024];
+ fprintf (stderr, ": %s", __strerror_r (errnum, errbuf, sizeof errbuf));
+#else
+ fprintf (stderr, ": %s", strerror (errnum));
+#endif
+ }
+ putc ('\n', stderr);
+ fflush (stderr);
+ if (status)
+ exit (status);
+}
+
+#ifdef _LIBC
+/* Make the weak alias. */
+#undef error
+#undef error_at_line
+weak_alias (__error, error)
+weak_alias (__error_at_line, error_at_line)
+#endif
diff --git a/error.h b/error.h
new file mode 100644
index 0000000..20f7582
--- /dev/null
+++ b/error.h
@@ -0,0 +1,78 @@
+/* Declaration for error-reporting function
+ Copyright (C) 1995, 1996, 1997 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined (__STDC__) && __STDC__
+
+/* Print a message with `fprintf (stderr, FORMAT, ...)';
+ if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
+ If STATUS is nonzero, terminate the program with `exit (STATUS)'. */
+
+extern void error (int status, int errnum, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+
+extern void error_at_line (int status, int errnum, const char *fname,
+ unsigned int lineno, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 5, 6)));
+
+/* If NULL, error will flush stdout, then print on stderr the program
+ name, a colon and a space. Otherwise, error will call this
+ function without parameters instead. */
+extern void (*error_print_progname) (void);
+
+#else
+void error ();
+void error_at_line ();
+extern void (*error_print_progname) ();
+#endif
+
+/* This variable is incremented each time `error' is called. */
+extern unsigned int error_message_count;
+
+/* Sometimes we want to have at most one error per line. This
+ variable controls whether this mode is selected or not. */
+extern int error_one_per_line;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/getopt.c b/getopt.c
index 300f86d..fc87ce6 100644
--- a/getopt.c
+++ b/getopt.c
@@ -6,23 +6,23 @@
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-USA. */
+ 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
@@ -79,12 +79,6 @@ USA. */
#endif
#endif
-#if defined (WIN32) && !defined (__CYGWIN32__)
-/* It's not Unix, really. See? Capital letters. */
-#include <windows.h>
-#define getpid() GetCurrentProcessId()
-#endif
-
#ifndef _
/* This is for other GNU distributions with internationalized messages.
When compiling libc, the _ macro is predefined. */
@@ -262,8 +256,6 @@ static int nonoption_flags_len;
static int original_argc;
static char *const *original_argv;
-extern pid_t __libc_pid;
-
/* Make sure the environment variable bash 2.0 puts in the environment
is valid for the getopt call we must make sure that the ARGV passed
to getopt is that one passed to the process. */
@@ -276,7 +268,9 @@ store_args_and_env (int argc, char *const *argv)
original_argc = argc;
original_argv = argv;
}
+# ifdef text_set_element
text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
# define SWAP_FLAGS(ch1, ch2) \
if (nonoption_flags_len > 0) \
@@ -329,9 +323,9 @@ exchange (argv)
nonoption_flags_len = nonoption_flags_max_len = 0;
else
{
- memcpy (new_str, __getopt_nonoption_flags, nonoption_flags_max_len);
- memset (&new_str[nonoption_flags_max_len], '\0',
- top + 1 - nonoption_flags_max_len);
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
nonoption_flags_max_len = top + 1;
__getopt_nonoption_flags = new_str;
}
@@ -440,11 +434,8 @@ _getopt_initialize (argc, argv, optstring)
if (__getopt_nonoption_flags == NULL)
nonoption_flags_max_len = -1;
else
- {
- memcpy (__getopt_nonoption_flags, orig_str, len);
- memset (&__getopt_nonoption_flags[len], '\0',
- nonoption_flags_max_len - len);
- }
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', nonoption_flags_max_len - len);
}
}
nonoption_flags_len = nonoption_flags_max_len;
diff --git a/getopt.h b/getopt.h
index 69256fd..c4adc30 100644
--- a/getopt.h
+++ b/getopt.h
@@ -1,23 +1,23 @@
/* Declarations for getopt.
Copyright (C) 1989,90,91,92,93,94,96,97 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.
+ 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 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.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
@@ -130,4 +130,4 @@ extern int _getopt_internal ();
}
#endif
-#endif /* _GETOPT_H */
+#endif /* getopt.h */
diff --git a/getopt1.c b/getopt1.c
index 6507ba1..af8e681 100644
--- a/getopt1.c
+++ b/getopt1.c
@@ -1,23 +1,23 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
Copyright (C) 1987,88,89,90,91,92,93,94,96,97 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-USA. */
+ 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/inp.c b/inp.c
index 880b90e..dc6f63e 100644
--- a/inp.c
+++ b/inp.c
@@ -1,10 +1,10 @@
/* inputting files to be patched */
-/* $Id: inp.c,v 1.18 1997/07/21 17:59:46 eggert Exp $ */
+/* $Id: inp.c,v 1.20 1998/03/15 14:44:47 eggert Exp $ */
/*
Copyright 1986, 1988 Larry Wall
-Copyright 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
+Copyright 1991, 1992, 1993, 1997, 1998 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
@@ -26,7 +26,9 @@ If not, write to the Free Software Foundation,
#include <common.h>
#include <backupfile.h>
#include <pch.h>
+#include <quotearg.h>
#include <util.h>
+#include <xalloc.h>
#undef XTERN
#define XTERN
#include <inp.h>
@@ -58,14 +60,21 @@ void
re_input()
{
if (using_plan_a) {
- free (i_buffer);
- free (i_ptr);
+ if (i_buffer)
+ {
+ free (i_buffer);
+ i_buffer = 0;
+ free (i_ptr);
+ }
}
else {
close (tifd);
tifd = -1;
- free(tibuf[0]);
- tibuf[0] = 0;
+ if (tibuf[0])
+ {
+ free (tibuf[0]);
+ tibuf[0] = 0;
+ }
tiline[0] = tiline[1] = -1;
tireclen = 0;
}
@@ -80,19 +89,16 @@ char *filename;
using_plan_a = ! (debug & 16) && plan_a (filename);
if (!using_plan_a)
plan_b(filename);
- switch (verbosity)
- {
- case SILENT:
- break;
- case VERBOSE:
- say ("Patching file `%s' using Plan %s...\n",
- filename, using_plan_a ? "A" : "B");
- break;
+ if (verbosity != SILENT)
+ {
+ filename = quotearg (filename);
- case DEFAULT_VERBOSITY:
- say ("patching file `%s'\n", filename);
- break;
+ if (verbosity == VERBOSE)
+ say ("Patching file %s using Plan %s...\n",
+ filename, using_plan_a ? "A" : "B");
+ else
+ say ("patching file %s\n", filename);
}
}
@@ -102,6 +108,8 @@ static void
report_revision (found_revision)
int found_revision;
{
+ revision = quotearg (revision);
+
if (found_revision)
{
if (verbosity == VERBOSE)
@@ -114,10 +122,8 @@ report_revision (found_revision)
revision);
}
else if (batch)
- {
- fatal ("This file doesn't appear to be the %s version -- aborting.",
- revision);
- }
+ fatal ("This file doesn't appear to be the %s version -- aborting.",
+ revision);
else
{
ask ("This file doesn't appear to be the %s version -- patch anyway? [n] ",
@@ -132,7 +138,7 @@ static void
too_many_lines (filename)
char const *filename;
{
- fatal ("File `%s' has too many lines.", filename);
+ fatal ("File %s has too many lines", quotearg (filename));
}
@@ -168,18 +174,23 @@ get_input_file (filename, outname)
if (!elsewhere
&& (instat.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) != 0)
/* Somebody can write to it. */
- fatal ("file `%s' seems to be locked by somebody else under %s",
- filename, cs);
- /* It might be checked out unlocked. See if it's safe to
- check out the default version locked. */
- if (verbosity == VERBOSE)
- say ("Comparing file `%s' to default %s version...\n",
- filename, cs);
- if (systemic (diffbuf) != 0)
+ fatal ("File %s seems to be locked by somebody else under %s",
+ quotearg (filename), cs);
+ if (diffbuf)
{
- say ("warning: patching file `%s', which does not match default %s version\n",
- filename, cs);
- cs = 0;
+ /* It might be checked out unlocked. See if it's safe to
+ check out the default version locked. */
+
+ if (verbosity == VERBOSE)
+ say ("Comparing file %s to default %s version...\n",
+ quotearg (filename), cs);
+
+ if (systemic (diffbuf) != 0)
+ {
+ say ("warning: Patching file %s, which does not match default %s version\n",
+ quotearg (filename), cs);
+ cs = 0;
+ }
}
}
@@ -188,12 +199,13 @@ get_input_file (filename, outname)
inerrno = 0;
free (getbuf);
- free (diffbuf);
+ if (diffbuf)
+ free (diffbuf);
} else if (inerrno && !pch_says_nonexistent (reverse))
{
errno = inerrno;
- pfatal ("can't find file `%s'", filename);
+ pfatal ("Can't find file %s", quotearg (filename));
}
if (inerrno)
@@ -202,7 +214,8 @@ get_input_file (filename, outname)
instat.st_size = 0;
}
else if (! S_ISREG (instat.st_mode))
- fatal ("`%s' is not a regular file -- can't patch", filename);
+ fatal ("File %s is not a regular file -- can't patch",
+ quotearg (filename));
}
@@ -232,7 +245,7 @@ plan_a(filename)
int ifd = open (filename, O_RDONLY|binary_transput);
size_t buffered = 0, n;
if (ifd < 0)
- pfatal ("can't open file `%s'", filename);
+ pfatal ("can't open file %s", quotearg (filename));
while (size - buffered != 0)
{
@@ -327,12 +340,15 @@ plan_b(filename)
register char const *rev;
register size_t revlen;
register LINENUM line = 1;
+ int exclusive;
if (instat.st_size == 0)
filename = NULL_DEVICE;
if (! (ifp = fopen (filename, binary_transput ? "rb" : "r")))
- pfatal ("can't open file `%s'", filename);
- tifd = create_file (TMPINNAME, O_RDWR | O_BINARY, (mode_t) 0);
+ pfatal ("Can't open file %s", quotearg (filename));
+ exclusive = TMPINNAME_needs_removal ? 0 : O_EXCL;
+ TMPINNAME_needs_removal = 1;
+ tifd = create_file (TMPINNAME, O_RDWR | O_BINARY | exclusive, (mode_t) 0);
i = 0;
len = 0;
maxlen = 1;
diff --git a/maketime.c b/maketime.c
index e66f9df..e13e70a 100644
--- a/maketime.c
+++ b/maketime.c
@@ -26,6 +26,11 @@
*/
+/* For maximum portability, use only localtime and gmtime.
+ Make no assumptions about the time_t epoch or the range of time_t values.
+ Avoid mktime because it's not universal and because there's no easy,
+ portable way for mktime to yield the inverse of gmtime. */
+
#if has_conf_h
# include <conf.h>
#else
@@ -58,18 +63,29 @@
#include <partime.h>
#include <maketime.h>
-char const maketId[] =
- "$Id: maketime.c,v 5.15 1997/06/17 16:54:36 eggert Exp $";
+char const maket_id[] =
+ "$Id: maketime.c,v 5.16 1997/12/04 07:49:27 eggert Exp $";
static int isleap P ((int));
static int month_days P ((struct tm const *));
static time_t maketime P ((struct partime const *, time_t));
-/* For maximum portability, use only localtime and gmtime.
- Make no assumptions about the time_t epoch or the range of time_t values.
- Avoid mktime because it's not universal and because there's no easy,
- portable way for mktime to yield the inverse of gmtime. */
+/* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
+ Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
+ Then this yields nonzero if overflow occurred during the addition.
+ Overflow occurs if A and B have the same sign, but A and SUM differ in sign.
+ Use `^' to test whether signs differ, and `< 0' to isolate the sign. */
+#define overflow_sum_sign(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
+
+/* Quotient and remainder when dividing A by B,
+ truncating towards minus infinity, where B is positive. */
+#define div(a, b) ((a) / (b) - ((a) % (b) < 0))
+#define mod(a, b) ((a) % (b) + (b) * ((a) % (b) < 0))
+/* Number of days in 400 consecutive Gregorian years. */
+#define Y400_DAYS (365 * 400L + 100 - 4 + 1)
+
+/* Number of years to add to tm_year to get Gregorian year. */
#define TM_YEAR_ORIGIN 1900
static int
@@ -121,8 +137,8 @@ difftm (a, b)
{
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
- int ac = ay / 100 - (ay % 100 < 0);
- int bc = by / 100 - (by % 100 < 0);
+ int ac = div (ay, 100);
+ int bc = div (by, 100);
int difference_in_day_of_year = a->tm_yday - b->tm_yday;
int intervening_leap_days = (((ay >> 2) - (by >> 2))
- (ac - bc)
@@ -139,76 +155,73 @@ difftm (a, b)
+ (a->tm_sec - b->tm_sec));
}
-/*
- * Adjust time T by adding SECONDS. SECONDS must be at most 24 hours' worth.
- * Adjust only T's year, mon, mday, hour, min and sec members;
- * plus adjust wday if it is defined.
- */
+/* Adjust time T by adding SECONDS.
+ The absolute value of SECONDS cannot exceed 59 * INT_MAX,
+ and also cannot exceed one month's worth of seconds;
+ this is enough to handle any POSIX or real-life daylight-saving offset.
+ Adjust only T's year, mon, mday, hour, min and sec members;
+ plus adjust wday if it is defined. */
void
adjzone (t, seconds)
register struct tm *t;
long seconds;
{
- /*
- * This code can be off by a second if SECONDS is not a multiple of 60,
- * if T is local time, and if a leap second happens during this minute.
- * But this bug has never occurred, and most likely will not ever occur.
- * Liberia, the last country for which SECONDS % 60 was nonzero,
- * switched to UTC in May 1972; the first leap second was in June 1972.
- */
+ int days = 0;
+
+ /* This code can be off by a second if SECONDS is not a multiple of 60,
+ if T is local time, and if a leap second happens during this minute.
+ But this bug has never occurred, and most likely will not ever occur.
+ Liberia, the last country for which SECONDS % 60 was nonzero,
+ switched to UTC in May 1972; the first leap second was in June 1972. */
int leap_second = t->tm_sec == 60;
long sec = seconds + (t->tm_sec - leap_second);
if (sec < 0)
{
- if ((t->tm_min -= (59 - sec) / 60) < 0)
+ if ((t->tm_min -= (59 - sec) / 60) < 0
+ && (t->tm_hour -= (59 - t->tm_min) / 60) < 0)
{
- if ((t->tm_hour -= (59 - t->tm_min) / 60) < 0)
+ days = - ((23 - t->tm_hour) / 24);
+ if ((t->tm_mday += days) <= 0)
{
- t->tm_hour += 24;
- if (TM_DEFINED (t->tm_wday) && --t->tm_wday < 0)
- t->tm_wday = 6;
- if (--t->tm_mday <= 0)
+ if (--t->tm_mon < 0)
{
- if (--t->tm_mon < 0)
- {
- --t->tm_year;
- t->tm_mon = 11;
- }
- t->tm_mday = month_days (t);
+ --t->tm_year;
+ t->tm_mon = 11;
}
+ t->tm_mday += month_days (t);
}
- t->tm_min += 24 * 60;
}
- sec += 24L * 60 * 60;
}
- else if (60 <= (t->tm_min += sec / 60))
- if (24 <= (t->tm_hour += t->tm_min / 60))
- {
- t->tm_hour -= 24;
- if (TM_DEFINED (t->tm_wday) && ++t->tm_wday == 7)
- t->tm_wday = 0;
- if (month_days (t) < ++t->tm_mday)
- {
- if (11 < ++t->tm_mon)
- {
- ++t->tm_year;
- t->tm_mon = 0;
- }
- t->tm_mday = 1;
- }
- }
- t->tm_min %= 60;
- t->tm_sec = (int) (sec % 60) + leap_second;
+ else
+ {
+ if (60 <= (t->tm_min += sec / 60)
+ && (24 <= (t->tm_hour += t->tm_min / 60)))
+ {
+ days = t->tm_hour / 24;
+ if (month_days (t) < (t->tm_mday += days))
+ {
+ if (11 < ++t->tm_mon)
+ {
+ ++t->tm_year;
+ t->tm_mon = 0;
+ }
+ t->tm_mday = 1;
+ }
+ }
+ }
+ if (TM_DEFINED (t->tm_wday))
+ t->tm_wday = mod (t->tm_wday + days, 7);
+ t->tm_hour = mod (t->tm_hour, 24);
+ t->tm_min = mod (t->tm_min, 60);
+ t->tm_sec = (int) mod (sec, 60) + leap_second;
}
-/*
- * Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise.
- * Use only TM's year, mon, mday, hour, min, and sec members.
- * Ignore TM's old tm_yday and tm_wday, but fill in their correct values.
- * Yield -1 on failure (e.g. a member out of range).
- * Posix 1003.1-1990 doesn't allow leap seconds, but some implementations
- * have them anyway, so allow them if localtime/gmtime does.
- */
+/* Convert TM to time_t, using localtime if LOCALZONE and gmtime otherwise.
+ Use only TM's year, mon, mday, hour, min, and sec members.
+ Ignore TM's old tm_yday and tm_wday, but fill in their correct values.
+ Yield -1 on failure (e.g. a member out of range).
+ POSIX 1003.1 doesn't allow leap seconds, but some implementations
+ have them anyway, so allow them if localtime/gmtime does. */
time_t
tm2time (tm, localzone)
struct tm *tm;
@@ -220,11 +233,9 @@ tm2time (tm, localzone)
time_t d, gt;
struct tm const *gtm;
- /*
- * The maximum number of iterations should be enough to handle any
- * combinations of leap seconds, time zone rule changes, and solar time.
- * 4 is probably enough; we use a bigger number just to be safe.
- */
+ /* The maximum number of iterations should be enough to handle any
+ combinations of leap seconds, time zone rule changes, and solar time.
+ 4 is probably enough; we use a bigger number just to be safe. */
int remaining_tries = 8;
/* Avoid subscript errors. */
@@ -247,11 +258,9 @@ tm2time (tm, localzone)
gtm = time2tm (gt, localzone);
}
- /*
- * Check that the guess actually matches;
- * overflow can cause difftm to yield 0 even on differing times,
- * or tm may have members out of range (e.g. bad leap seconds).
- */
+ /* Check that the guess actually matches;
+ overflow can cause difftm to yield 0 even on differing times,
+ or tm may have members out of range (e.g. bad leap seconds). */
#define TM_DIFFER(a,b) \
( \
((a)->tm_year ^ (b)->tm_year) | \
@@ -263,11 +272,9 @@ tm2time (tm, localzone)
)
if (TM_DIFFER (tm, gtm))
{
- /*
- * If gt is a leap second, try gt+1; if it is one greater than
- * a leap second, try gt-1; otherwise, it doesn't matter.
- * Leap seconds always fall at month end.
- */
+ /* If gt is a leap second, try gt+1; if it is one greater than
+ a leap second, try gt-1; otherwise, it doesn't matter.
+ Leap seconds always fall at month end. */
int yd = tm->tm_year - gtm->tm_year;
gt += yd + (yd ? 0 : tm->tm_mon - gtm->tm_mon);
gtm = time2tm (gt, localzone);
@@ -281,29 +288,32 @@ tm2time (tm, localzone)
return gt;
}
-/*
- * Check *PT and convert it to time_t.
- * If it is incompletely specified, use DEFAULT_TIME to fill it out.
- * Use localtime if PT->zone is the special value TM_LOCAL_ZONE.
- * Yield -1 on failure.
- * ISO 8601 day-of-year and week numbers are not yet supported.
- */
+/* Check *PT and convert it to time_t.
+ If it is incompletely specified, use DEFAULT_TIME to fill it out.
+ Use localtime if PT->zone is the special value TM_LOCAL_ZONE.
+ Yield -1 on failure.
+ ISO 8601 day-of-year and week numbers are not yet supported. */
static time_t
maketime (pt, default_time)
struct partime const *pt;
time_t default_time;
{
- int localzone, wday;
+ int localzone, wday, year;
struct tm tm;
struct tm *tm0 = 0;
time_t r;
+ int use_ordinal_day;
tm0 = 0; /* Keep gcc -Wall happy. */
localzone = pt->zone == TM_LOCAL_ZONE;
tm = pt->tm;
+ year = tm.tm_year;
+ wday = tm.tm_wday;
+ use_ordinal_day = (!TM_DEFINED (tm.tm_mday)
+ && TM_DEFINED (wday) && TM_DEFINED (pt->wday_ordinal));
- if (TM_DEFINED (pt->ymodulus) || !TM_DEFINED (tm.tm_year))
+ if (use_ordinal_day || TM_DEFINED (pt->ymodulus) || !TM_DEFINED (year))
{
/* Get tm corresponding to default time. */
tm0 = time2tm (default_time, localzone);
@@ -311,13 +321,25 @@ maketime (pt, default_time)
adjzone (tm0, pt->zone);
}
+ if (use_ordinal_day)
+ tm.tm_mday = (tm0->tm_mday
+ + ((wday - tm0->tm_wday + 7) % 7
+ + 7 * (pt->wday_ordinal - (pt->wday_ordinal != 0))));
+
if (TM_DEFINED (pt->ymodulus))
- tm.tm_year +=
- (tm0->tm_year + TM_YEAR_ORIGIN) / pt->ymodulus * pt->ymodulus;
- else if (!TM_DEFINED (tm.tm_year))
+ {
+ /* Yield a year closest to the default that has the given modulus. */
+ int year0 = tm0->tm_year + TM_YEAR_ORIGIN;
+ int y0 = mod (year0, pt->ymodulus);
+ int d = 2 * (year - y0);
+ year += (((year0 - y0) / pt->ymodulus
+ + (pt->ymodulus < d ? -1 : d < -pt->ymodulus))
+ * pt->ymodulus);
+ }
+ else if (!TM_DEFINED (year))
{
/* Set default year, month, day from current time. */
- tm.tm_year = tm0->tm_year + TM_YEAR_ORIGIN;
+ year = tm0->tm_year + TM_YEAR_ORIGIN;
if (!TM_DEFINED (tm.tm_mon))
{
tm.tm_mon = tm0->tm_mon;
@@ -326,9 +348,6 @@ maketime (pt, default_time)
}
}
- /* Convert from partime year (Gregorian) to Posix year. */
- tm.tm_year -= TM_YEAR_ORIGIN;
-
/* Set remaining default fields to be their minimum values. */
if (!TM_DEFINED (tm.tm_mon))
tm.tm_mon = 0;
@@ -341,37 +360,125 @@ maketime (pt, default_time)
if (!TM_DEFINED (tm.tm_sec))
tm.tm_sec = 0;
+ tm.tm_year = year - TM_YEAR_ORIGIN;
+ if ((year < tm.tm_year) != (TM_YEAR_ORIGIN < 0))
+ return -1;
+
if (!localzone)
- adjzone (&tm, -pt->zone);
- wday = tm.tm_wday;
+ {
+ adjzone (&tm, -pt->zone);
+ wday = tm.tm_wday;
+ }
/* Convert and fill in the rest of the tm. */
r = tm2time (&tm, localzone);
+ if (r == -1)
+ return r;
/* Check weekday. */
- if (r != -1 && TM_DEFINED (wday) && wday != tm.tm_wday)
+ if (TM_DEFINED (wday) && wday != tm.tm_wday)
return -1;
- return r;
+ /* Add relative time, except for seconds.
+ We handle seconds separately, at the end,
+ so that leap seconds are handled properly. */
+ if (pt->tmr.tm_year | pt->tmr.tm_mon | pt->tmr.tm_mday
+ | pt->tmr.tm_hour | pt->tmr.tm_min)
+ {
+ int years = tm.tm_year + pt->tmr.tm_year;
+ int mons = tm.tm_mon + pt->tmr.tm_mon;
+ int mdays = tm.tm_mday + pt->tmr.tm_mday;
+ int hours = tm.tm_hour + pt->tmr.tm_hour;
+ int mins = tm.tm_min + pt->tmr.tm_min;
+
+ int carried_hours = div (mins, 60);
+ int hours1 = hours + carried_hours;
+ int carried_days = div (hours1, 24);
+ int mdays1 = mdays + carried_days;
+
+ int mon0 = mod (mons, 12);
+ int carried_years0 = div (mons, 12);
+ int year0 = years + carried_years0;
+ int yday0 = (month_yday[mon0]
+ - (mon0 < 2 || !isleap (year0 + TM_YEAR_ORIGIN)));
+
+ int yday1 = yday0 + mdays1;
+ int carried_years1 = div (yday1, Y400_DAYS) * 400;
+ int year1 = year0 + carried_years1;
+ int yday2 = mod (yday1, Y400_DAYS);
+ int leap;
+
+ if (overflow_sum_sign (tm.tm_year, pt->tmr.tm_year, years)
+ | overflow_sum_sign (tm.tm_mon, pt->tmr.tm_mon, mons)
+ | overflow_sum_sign (tm.tm_mday, pt->tmr.tm_mday, mdays)
+ | overflow_sum_sign (tm.tm_hour, pt->tmr.tm_hour, hours)
+ | overflow_sum_sign (tm.tm_min, pt->tmr.tm_min, mins)
+ | overflow_sum_sign (hours, carried_hours, hours1)
+ | overflow_sum_sign (mdays, carried_days, mdays1)
+ | overflow_sum_sign (years, carried_years0, year0)
+ | overflow_sum_sign (yday0, mdays1, yday1)
+ | overflow_sum_sign (year0, carried_years1, year1))
+ return -1;
+
+ for (;;)
+ {
+ int days_per_year = 365 + (leap = isleap (year1 + TM_YEAR_ORIGIN));
+ if (yday2 < days_per_year)
+ break;
+ yday2 -= days_per_year;
+ year1++;
+ }
+
+ tm.tm_year = year1;
+
+ {
+ int mon;
+ for (mon = 11;
+ (tm.tm_mday = (yday2 - month_yday[mon] + (mon < 2 || !leap))) <= 0;
+ mon--)
+ continue;
+ tm.tm_mon = mon;
+ }
+
+ tm.tm_hour = mod (hours1, 24);
+ tm.tm_min = mod (mins, 60);
+
+ r = tm2time (&tm, localzone);
+ if (r == -1)
+ return r;
+ }
+
+ /* Add the seconds' part of relative time. */
+ {
+ time_t rs = r + pt->tmr.tm_sec;
+ if ((pt->tmr.tm_sec < 0) != (rs < r))
+ return -1;
+ return rs;
+ }
}
-/* Parse a free-format date in SOURCE, yielding a Unix format time. */
+/* Parse a free-format date in *SOURCE, yielding a Unix format time.
+ Update *SOURCE to point to the first character after the date.
+ If *SOURCE is missing some information, take defaults from
+ DEFAULT_TIME and DEFAULT_ZONE. *SOURCE may even be the empty
+ string or an immediately invalid string, in which case the default
+ time and zone is used.
+ Return (time_t) -1 if the time is invalid or cannot be represented. */
time_t
str2time (source, default_time, default_zone)
- char const *source;
+ char const **source;
time_t default_time;
long default_zone;
{
struct partime pt;
- if (*partime (source, &pt))
- return -1;
+ *source = partime (*source, &pt);
if (pt.zone == TM_UNDEFINED_ZONE)
pt.zone = default_zone;
return maketime (&pt, default_time);
}
-#if TEST
+#ifdef TEST
#include <stdio.h>
int
main (argc, argv)
@@ -379,12 +486,15 @@ main (argc, argv)
char **argv;
{
time_t default_time = time ((time_t *) 0);
- long default_zone = argv[1] ? atol (argv[1]) : 0;
+ long default_zone = argv[1] ? atol (argv[1]) : TM_LOCAL_ZONE;
char buf[1000];
while (fgets (buf, sizeof (buf), stdin))
{
- time_t t = str2time (buf, default_time, default_zone);
- printf ("%s", asctime (gmtime (&t)));
+ char const *p = buf;
+ time_t t = str2time (&p, default_time, default_zone);
+ printf ("`%.*s' -> %s",
+ (int) (p - buf - (p[0] == '\0' && p[-1] == '\n')), buf,
+ asctime ((argv[1] ? gmtime : localtime) (&t)));
}
return 0;
}
diff --git a/maketime.h b/maketime.h
index 3948eda..2f977c4 100644
--- a/maketime.h
+++ b/maketime.h
@@ -34,6 +34,6 @@
struct tm *time2tm __MAKETIME_P ((time_t, int));
time_t difftm __MAKETIME_P ((struct tm const *, struct tm const *));
-time_t str2time __MAKETIME_P ((char const *, time_t, long));
+time_t str2time __MAKETIME_P ((char const **, time_t, long));
time_t tm2time __MAKETIME_P ((struct tm *, int));
void adjzone __MAKETIME_P ((struct tm *, long));
diff --git a/malloc.c b/malloc.c
new file mode 100644
index 0000000..b859e58
--- /dev/null
+++ b/malloc.c
@@ -0,0 +1,39 @@
+/* Work around bug on some systems where malloc (0) fails.
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#undef malloc
+
+#include <sys/types.h>
+
+char *malloc ();
+
+/* Allocate an N-byte block of memory from the heap.
+ If N is zero, allocate a 1-byte block. */
+
+char *
+rpl_malloc (n)
+ size_t n;
+{
+ if (n == 0)
+ n = 1;
+ return malloc (n);
+}
diff --git a/memchr.c b/memchr.c
index c75217f..2012fa1 100644
--- a/memchr.c
+++ b/memchr.c
@@ -1,27 +1,27 @@
-/* Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc.
Based on strlen implementation by Torbjorn Granlund (tege@sics.se),
with help from Dan Sahlin (dan@sics.se) and
commentary by Jim Blandy (jimb@ai.mit.edu);
adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu),
and implemented by Roland McGrath (roland@ai.mit.edu).
-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.
+ 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 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.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-USA. */
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -50,9 +50,10 @@ USA. */
#include <sys/types.h>
+#undef memchr
-/* Search no more than N bytes of S for C. */
+/* Search no more than N bytes of S for C. */
__ptr_t
memchr (s, c, n)
const __ptr_t s;
diff --git a/partime.c b/partime.c
index ce87109..bcc181f 100644
--- a/partime.c
+++ b/partime.c
@@ -42,6 +42,9 @@
# ifndef LONG_MIN
# define LONG_MIN (-1-2147483647L)
# endif
+# if HAVE_STDDEF_H
+# include <stddef.h>
+# endif
# if STDC_HEADERS
# include <stdlib.h>
# endif
@@ -53,6 +56,10 @@
# endif
#endif
+#ifndef offsetof
+#define offsetof(aggregate, member) ((size_t) &((aggregate *) 0)->member)
+#endif
+
#include <ctype.h>
#if STDC_HEADERS
# define CTYPE_DOMAIN(c) 1
@@ -67,8 +74,8 @@
#include <partime.h>
-char const partimeId[] =
- "$Id: partime.c,v 5.16 1997/05/19 06:33:53 eggert Exp $";
+char const partime_id[] =
+ "$Id: partime.c,v 5.18 1998/03/15 15:48:53 eggert Exp $";
/* Lookup tables for names of months, weekdays, time zones. */
@@ -85,8 +92,9 @@ struct name_val
static char const *parse_decimal P ((char const *, int, int, int, int, int *, int *));
static char const *parse_fixed P ((char const *, int, int *));
static char const *parse_pattern_letter P ((char const *, int, struct partime *));
-static char const *parse_prefix P ((char const *, struct partime *, int *));
+static char const *parse_prefix P ((char const *, char const **, struct partime *));
static char const *parse_ranged P ((char const *, int, int, int, int *));
+static char const *parse_varying P ((char const *, int *));
static int lookup P ((char const *, struct name_val const[]));
static int merge_partime P ((struct partime *, struct partime const *));
static void undefine P ((struct partime *));
@@ -121,10 +129,39 @@ static struct name_val const weekday_names[] =
{"", TM_UNDEFINED}
};
-#define hr60nonnegative(t) ((t)/100 * 60 + (t)%100)
-#define hr60(t) ((t)<0 ? -hr60nonnegative(-(t)) : hr60nonnegative(t))
-#define zs(t,s) {s, hr60(t)}
-#define zd(t,s,d) zs(t, s), zs((t)+100, d)
+#define RELATIVE_CONS(member, multiplier) \
+ (offsetof (struct tm, member) + (multiplier) * sizeof (struct tm))
+#define RELATIVE_OFFSET(c) ((c) % sizeof (struct tm))
+#define RELATIVE_MULTIPLIER(c) ((c) / sizeof (struct tm))
+static struct name_val const relative_units[] =
+{
+ {"year", RELATIVE_CONS (tm_year, 1) },
+ {"mont", RELATIVE_CONS (tm_mon , 1) },
+ {"fort", RELATIVE_CONS (tm_mday, 14) },
+ {"week", RELATIVE_CONS (tm_mday, 7) },
+ {"day" , RELATIVE_CONS (tm_mday, 1) },
+ {"hour", RELATIVE_CONS (tm_hour, 1) },
+ {"min" , RELATIVE_CONS (tm_min , 1) },
+ {"sec" , RELATIVE_CONS (tm_sec , 1) },
+ {"", TM_UNDEFINED}
+};
+
+static struct name_val const ago[] =
+{
+ {"ago", 0},
+ {"", TM_UNDEFINED}
+};
+
+static struct name_val const dst_names[] =
+{
+ {"dst", 1},
+ {"", 0}
+};
+
+#define hr60nonnegative(t) ((t)/100 * 60 + (t)%100)
+#define hr60(t) ((t) < 0 ? - hr60nonnegative (-(t)) : hr60nonnegative (t))
+#define zs(t, s) {s, hr60 (t)}
+#define zd(t, s, d) zs (t, s), zs ((t) + 100, d)
static struct name_val const zone_names[] =
{
@@ -155,7 +192,8 @@ static struct name_val const zone_names[] =
{"lt", 1},
#if 0
/* The following names are duplicates or are not well attested.
- There are lots more where these came from. */
+ It's not worth keeping a complete list, since alphabetic time zone names
+ are deprecated and there are lots more where these came from. */
zs (-1100, "sst" ), /* Samoan */
zd (- 900, "yst" , "ydt" ), /* Yukon - name is no longer used */
zd (- 500, "ast" , "adt" ), /* Acre */
@@ -191,13 +229,15 @@ lookup (s, table)
for (j = 0; j < NAME_LENGTH_MAXIMUM; j++)
{
- unsigned char c = *s++;
+ unsigned char c = *s;
if (! ISALPHA (c))
{
buf[j] = '\0';
break;
}
buf[j] = ISUPPER (c) ? tolower (c) : c;
+ s++;
+ s += *s == '.';
}
for (;; table++)
@@ -216,54 +256,109 @@ undefine (t)
{
t->tm.tm_sec = t->tm.tm_min = t->tm.tm_hour = t->tm.tm_mday = t->tm.tm_mon
= t->tm.tm_year = t->tm.tm_wday = t->tm.tm_yday
- = t->ymodulus = t->yweek
+ = t->wday_ordinal = t->ymodulus = t->yweek
= TM_UNDEFINED;
+ t->tmr.tm_sec = t->tmr.tm_min = t->tmr.tm_hour =
+ t->tmr.tm_mday = t->tmr.tm_mon = t->tmr.tm_year = 0;
t->zone = TM_UNDEFINED_ZONE;
}
-/* Array of patterns to look for in a date string.
+/* Patterns to look for in a time string.
Order is important: we look for the first matching pattern
whose values do not contradict values that we already know about.
See `parse_pattern_letter' below for the meaning of the pattern codes. */
-static char const *const patterns[] =
+static char const time_patterns[] =
{
- /* These traditional patterns must come first,
+ /* Traditional patterns come first,
to prevent an ISO 8601 format from misinterpreting their prefixes. */
- "E_n_y", "x", /* RFC 822 */
- "E_n", "n_E", "n", "t:m:s_A", "t:m_A", "t_A", /* traditional */
- "y/N/D$", /* traditional RCS */
+
+ /* RFC 822, extended */
+ 'E', '_', 'N', '_', 'y', '$', 0,
+ 'x', 0,
+
+ /* traditional */
+ '4', '_', 'M', '_', 'D', '_', 'h', '_', 'm', '_', 's', '$', 0,
+ 'R', '_', 'M', '_', 'D', '_', 'h', '_', 'm', '_', 's', '$', 0,
+ 'E', '_', 'N', 0,
+ 'N', '_', 'E', '_', 'y', ';', 0,
+ 'N', '_', 'E', ';', 0,
+ 'N', 0,
+ 't', ':', 'm', ':', 's', '_', 'A', 0,
+ 't', ':', 'm', '_', 'A', 0,
+ 't', '_', 'A', 0,
+
+ /* traditional get_date */
+ 'i', '_', 'x', 0,
+ 'Y', '/', 'n', '/', 'E', ';', 0,
+ 'n', '/', 'E', '/', 'y', ';', 0,
+ 'n', '/', 'E', ';', 0,
+ 'u', 0,
/* ISO 8601:1988 formats, generalized a bit. */
- "y-N-D$", "4ND$", "Y-N$",
- "RND$", "-R=N$", "-R$", "--N=D$", "N=DT",
- "--N$", "---D$", "DT",
- "Y-d$", "4d$", "R=d$", "-d$", "dT",
- "y-W-X", "yWX", "y=W",
- "-r-W-X", "r-W-XT", "-rWX", "rWXT", "-W=X", "W=XT", "-W",
- "-w-X", "w-XT", "---X$", "XT", "4$",
- "T",
- "h:m:s$", "hms$", "h:m$", "hm$", "h$", "-m:s$", "-ms$", "-m$", "--s$",
- "Y", "Z",
+ 'y', '-', 'M', '-', 'D', '$', 0,
+ '4', 'M', 'D', '$', 0,
+ 'Y', '-', 'M', '$', 0,
+ 'R', 'M', 'D', '$', 0,
+ '-', 'R', '=', 'M', '$', 0,
+ '-', 'R', '$', 0,
+ '-', '-', 'M', '=', 'D', '$', 0,
+ 'M', '=', 'D', 'T', 0,
+ '-', '-', 'M', '$', 0,
+ '-', '-', '-', 'D', '$', 0,
+ 'D', 'T', 0,
+ 'Y', '-', 'd', '$', 0,
+ '4', 'd', '$', 0,
+ 'R', '=', 'd', '$', 0,
+ '-', 'd', '$', 0,
+ 'd', 'T', 0,
+ 'y', '-', 'W', '-', 'X', 0,
+ 'y', 'W', 'X', 0,
+ 'y', '=', 'W', 0,
+ '-', 'r', '-', 'W', '-', 'X', 0,
+ 'r', '-', 'W', '-', 'X', 'T', 0,
+ '-', 'r', 'W', 'X', 0,
+ 'r', 'W', 'X', 'T', 0,
+ '-', 'W', '=', 'X', 0,
+ 'W', '=', 'X', 'T', 0,
+ '-', 'W', 0,
+ '-', 'w', '-', 'X', 0,
+ 'w', '-', 'X', 'T', 0,
+ '-', '-', '-', 'X', '$', 0,
+ 'X', 'T', 0,
+ '4', '$', 0,
+ 'T', 0,
+ 'h', ':', 'm', ':', 's', '$', 0,
+ 'h', 'm', 's', '$', 0,
+ 'h', ':', 'L', '$', 0,
+ 'h', 'L', '$', 0,
+ 'H', '$', 0,
+ '-', 'm', ':', 's', '$', 0,
+ '-', 'm', 's', '$', 0,
+ '-', 'L', '$', 0,
+ '-', '-', 's', '$', 0,
+ 'Y', 0,
+ 'Z', 0,
0
};
-/* Parse an initial prefix of STR, setting *T accordingly.
+/* Parse an initial prefix of STR according to *PATTERNS, setting *T.
Return the first character after the prefix, or 0 if it couldn't be parsed.
- Start with pattern *PI; if success, set *PI to the next pattern to try.
- Set *PI to -1 if we know there are no more patterns to try;
- if *PI is initially negative, give up immediately. */
+ *PATTERNS is a character array containing one pattern string after another;
+ it is terminated by an empty string.
+ If success, set *PATTERNS to the next pattern to try.
+ Set *PATTERNS to 0 if we know there are no more patterns to try;
+ if *PATTERNS is initially 0, give up immediately. */
static char const *
-parse_prefix (str, t, pi)
+parse_prefix (str, patterns, t)
char const *str;
+ char const **patterns;
struct partime *t;
- int *pi;
{
- int i = *pi;
- char const *pat;
+ char const *pat = *patterns;
unsigned char c;
- if (i < 0)
+ if (! pat)
return 0;
/* Remove initial noise. */
@@ -272,26 +367,31 @@ parse_prefix (str, t, pi)
if (! c)
{
undefine (t);
- *pi = -1;
+ *patterns = 0;
return str;
}
+
str++;
}
/* Try a pattern until one succeeds. */
- while ((pat = patterns[i++]) != 0)
+ while (*pat)
{
char const *s = str;
undefine (t);
+
do
{
if (! (c = *pat++))
{
- *pi = i;
+ *patterns = pat;
return s;
}
}
while ((s = parse_pattern_letter (s, c, t)) != 0);
+
+ while (*pat++)
+ continue;
}
return 0;
@@ -318,6 +418,27 @@ parse_fixed (s, digits, res)
return s;
}
+/* Parse a possibly empty initial prefix of S.
+ Store the parsed number into *RES.
+ Return the first character after the prefix. */
+static char const *
+parse_varying (s, res)
+ char const *s;
+ int *res;
+{
+ int n = 0;
+ for (;;)
+ {
+ unsigned d = *s - '0';
+ if (9 < d)
+ break;
+ s++;
+ n = 10 * n + d;
+ }
+ *res = n;
+ return s;
+}
+
/* Parse an initial prefix of S of length DIGITS;
it must be a number in the range LO through HI.
Store the parsed number into *RES.
@@ -379,9 +500,11 @@ parzone (s, zone)
char const *s;
long *zone;
{
+ char const *s1;
char sign;
int hh, mm, ss;
- int minutesEastOfUTC;
+ int minutes_east_of_UTC;
+ int trailing_DST;
long offset, z;
/* The formats are LT, n, n DST, nDST, no, o
@@ -395,40 +518,52 @@ parzone (s, zone)
break;
default:
- minutesEastOfUTC = lookup (s, zone_names);
- if (minutesEastOfUTC == -1)
+ minutes_east_of_UTC = lookup (s, zone_names);
+ if (minutes_east_of_UTC == -1)
return 0;
- /* Don't bother to check rest of spelling. */
+ /* Don't bother to check rest of spelling,
+ but look for an embedded "DST". */
+ trailing_DST = 0;
while (ISALPHA ((unsigned char) *s))
- s++;
+ {
+ if ((*s == 'D' || *s == 'd') && lookup (s, dst_names))
+ trailing_DST = 1;
+ s++;
+ s += *s == '.';
+ }
/* Don't modify LT. */
- if (minutesEastOfUTC == 1)
+ if (minutes_east_of_UTC == 1)
{
*zone = TM_LOCAL_ZONE;
return (char *) s;
}
- z = minutesEastOfUTC * 60L;
+ z = minutes_east_of_UTC * 60L;
+ s1 = s;
- /* Look for trailing " DST". */
- if ((s[-1] == 'T' || s[-1] == 't')
- && (s[-2] == 'S' || s[-2] == 's')
- && (s[-3] == 'D' || s[-3] == 'd'))
- goto trailing_dst;
+ /* Look for trailing "DST" or " DST". */
while (ISSPACE ((unsigned char) *s))
s++;
- if ((s[0] == 'D' || s[0] == 'd')
- && (s[1] == 'S' || s[1] == 's')
- && (s[2] == 'T' || s[2] == 't'))
+ if (lookup (s, dst_names))
+ {
+ while (ISALPHA ((unsigned char) *s))
+ {
+ s++;
+ s += *s == '.';
+ }
+ trailing_DST = 1;
+ }
+
+ if (trailing_DST)
{
- s += 3;
- trailing_dst:
*zone = z + 60*60;
return (char *) s;
}
+ s = s1;
+
switch (*s)
{
case '-':
@@ -475,6 +610,8 @@ parse_pattern_letter (s, c, t)
int c;
struct partime *t;
{
+ char const *s0 = s;
+
switch (c)
{
case '$': /* The next character must be a non-digit. */
@@ -494,15 +631,20 @@ parse_pattern_letter (s, c, t)
s = parse_fixed (s, 4, &t->tm.tm_year);
break;
+ case ';': /* The next character must be a non-digit, and cannot be ':'. */
+ if (ISDIGIT (*s) || *s == ':')
+ return 0;
+ break;
+
case '=': /* optional '-' */
s += *s == '-';
break;
case 'A': /* AM or PM */
- /* This matches the regular expression [AaPp][Mm]?.
+ /* This matches the regular expression [AaPp]\.?([Mm]\.?)?.
It must not be followed by a letter or digit;
otherwise it would match prefixes of strings like "PST". */
- switch (*s++)
+ switch (*s)
{
case 'A':
case 'a':
@@ -519,11 +661,14 @@ parse_pattern_letter (s, c, t)
default:
return 0;
}
+ s++;
+ s += *s == '.';
switch (*s)
{
case 'M':
case 'm':
s++;
+ s += *s == '.';
break;
}
if (ISALNUM ((unsigned char) *s))
@@ -539,12 +684,16 @@ parse_pattern_letter (s, c, t)
t->tm.tm_yday--;
break;
- case 'E': /* extended day of month [1-9, 01-31] */
+ case 'E': /* traditional day of month [1-9, 01-31] */
s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 31,
&t->tm.tm_mday);
break;
- case 'h': /* hour [00-23 followed by optional fraction] */
+ case 'h': /* hour [00-23] */
+ s = parse_ranged (s, 2, 0, 23, &t->tm.tm_hour);
+ break;
+
+ case 'H': /* hour [00-23 followed by optional fraction] */
{
int frac;
s = parse_decimal (s, 2, 0, 23, 60 * 60, &t->tm.tm_hour, &frac);
@@ -553,11 +702,34 @@ parse_pattern_letter (s, c, t)
}
break;
- case 'm': /* minute [00-59 followed by optional fraction] */
+ case 'i': /* ordinal day number, e.g. "3rd" */
+ s = parse_varying (s, &t->wday_ordinal);
+ if (s == s0)
+ return 0;
+ while (ISALPHA ((unsigned char) *s))
+ s++;
+ break;
+
+ case 'L': /* minute [00-59 followed by optional fraction] */
s = parse_decimal (s, 2, 0, 59, 60, &t->tm.tm_min, &t->tm.tm_sec);
break;
- case 'n': /* month name [e.g. "Jan"] */
+ case 'm': /* minute [00-59] */
+ s = parse_ranged (s, 2, 0, 59, &t->tm.tm_min);
+ break;
+
+ case 'M': /* month [01-12] */
+ s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon);
+ t->tm.tm_mon--;
+ break;
+
+ case 'n': /* traditional month [1-9, 01-12] */
+ s = parse_ranged (s, (ISDIGIT (s[0]) && ISDIGIT (s[1])) + 1, 1, 12,
+ &t->tm.tm_mon);
+ t->tm.tm_mon--;
+ break;
+
+ case 'N': /* month name [e.g. "Jan"] */
if (! TM_DEFINED (t->tm.tm_mon = lookup (s, month_names)))
return 0;
/* Don't bother to check rest of spelling. */
@@ -565,11 +737,6 @@ parse_pattern_letter (s, c, t)
s++;
break;
- case 'N': /* month [01-12] */
- s = parse_ranged (s, 2, 1, 12, &t->tm.tm_mon);
- t->tm.tm_mon--;
- break;
-
case 'r': /* year % 10 (remainder in origin-0 decade) [0-9] */
s = parse_fixed (s, 1, &t->tm.tm_year);
t->ymodulus = 10;
@@ -605,6 +772,50 @@ parse_pattern_letter (s, c, t)
&t->tm.tm_hour);
break;
+ case 'u': /* relative unit */
+ {
+ int i;
+ int n;
+ int negative = 0;
+ switch (*s)
+ {
+ case '-': negative = 1;
+ /* Fall through. */
+ case '+': s++;
+ }
+ if (ISDIGIT (*s))
+ s = parse_varying (s, &n);
+ else if (s == s0)
+ n = 1;
+ else
+ return 0;
+ if (negative)
+ n = -n;
+ while (!ISALNUM ((unsigned char) *s))
+ s++;
+ i = lookup (s, relative_units);
+ if (!TM_DEFINED (i))
+ return 0;
+ * (int *) ((char *) &t->tmr + RELATIVE_OFFSET (i))
+ += n * RELATIVE_MULTIPLIER (i);
+ while (ISALPHA ((unsigned char) *s))
+ s++;
+ while (! ISALNUM ((unsigned char) *s) && *s)
+ s++;
+ if (TM_DEFINED (lookup (s, ago)))
+ {
+ t->tmr.tm_sec = - t->tmr.tm_sec;
+ t->tmr.tm_min = - t->tmr.tm_min;
+ t->tmr.tm_hour = - t->tmr.tm_hour;
+ t->tmr.tm_mday = - t->tmr.tm_mday;
+ t->tmr.tm_mon = - t->tmr.tm_mon;
+ t->tmr.tm_year = - t->tmr.tm_year;
+ while (ISALPHA ((unsigned char) *s))
+ s++;
+ }
+ break;
+ }
+
case 'w': /* 'W' or 'w' only (stands for current week) */
switch (*s++)
{
@@ -646,14 +857,9 @@ parse_pattern_letter (s, c, t)
goto case_R;
/* fall into */
case 'Y': /* year in full [4 or more digits] */
- {
- int len = 0;
- while (ISDIGIT (s[len]))
- len++;
- if (len < 4)
- return 0;
- s = parse_fixed (s, len, &t->tm.tm_year);
- }
+ s = parse_varying (s, &t->tm.tm_year);
+ if (s - s0 < 4)
+ return 0;
break;
case 'Z': /* time zone */
@@ -686,7 +892,8 @@ merge_partime (t, u)
|| conflict (t->tm.tm_mday, u->tm.tm_mday)
|| conflict (t->tm.tm_mon, u->tm.tm_mon)
|| conflict (t->tm.tm_year, u->tm.tm_year)
- || conflict (t->tm.tm_wday, u->tm.tm_yday)
+ || conflict (t->tm.tm_wday, u->tm.tm_wday)
+ || conflict (t->tm.tm_yday, u->tm.tm_yday)
|| conflict (t->ymodulus, u->ymodulus)
|| conflict (t->yweek, u->yweek)
|| (t->zone != u->zone
@@ -701,10 +908,17 @@ merge_partime (t, u)
merge_ (t->tm.tm_mday, u->tm.tm_mday)
merge_ (t->tm.tm_mon, u->tm.tm_mon)
merge_ (t->tm.tm_year, u->tm.tm_year)
- merge_ (t->tm.tm_wday, u->tm.tm_yday)
+ merge_ (t->tm.tm_wday, u->tm.tm_wday)
+ merge_ (t->tm.tm_yday, u->tm.tm_yday)
merge_ (t->ymodulus, u->ymodulus)
merge_ (t->yweek, u->yweek)
# undef merge_
+ t->tmr.tm_sec += u->tmr.tm_sec;
+ t->tmr.tm_min += u->tmr.tm_min;
+ t->tmr.tm_hour += u->tmr.tm_hour;
+ t->tmr.tm_mday += u->tmr.tm_mday;
+ t->tmr.tm_mon += u->tmr.tm_mon;
+ t->tmr.tm_year += u->tmr.tm_year;
if (u->zone != TM_UNDEFINED_ZONE)
t->zone = u->zone;
return 0;
@@ -725,12 +939,12 @@ partime (s, t)
while (*s)
{
- int i = 0;
+ char const *patterns = time_patterns;
char const *s1;
do
{
- if (! (s1 = parse_prefix (s, &p, &i)))
+ if (! (s1 = parse_prefix (s, &patterns, &p)))
return (char *) s;
}
while (merge_partime (t, &p) != 0);
diff --git a/partime.h b/partime.h
index bcc8165..1f4d31a 100644
--- a/partime.h
+++ b/partime.h
@@ -36,19 +36,29 @@
struct partime
{
/* This structure describes the parsed time.
- Only the following tm_* values in it are used:
+ Only the following tm_* members are used:
sec, min, hour, mday, mon, year, wday, yday.
- If TM_UNDEFINED (value), the parser never found the value.
+ If ! TM_DEFINED (value), the parser never found the value.
The tm_year field is the actual year, not the year - 1900;
but see ymodulus below. */
struct tm tm;
- /* If !TM_UNDEFINED (ymodulus),
+ /* Like tm, but values are relative to the value in tm,
+ and values are initialized to 0 rather than to TM_UNDEFINED.
+ Only the following tm_* members are used:
+ sec, min, hour, mday, mon, year. */
+ struct tm tmr;
+
+ /* If TM_DEFINED (wday_ordinal),
+ then day number (e.g. 3 in "3rd Sunday"). */
+ int wday_ordinal;
+
+ /* If TM_DEFINED (ymodulus),
then tm.tm_year is actually modulo ymodulus. */
int ymodulus;
/* Week of year, ISO 8601 style.
- If TM_UNDEFINED (yweek), the parser never found yweek.
+ If ! TM_DEFINED (yweek), the parser never found yweek.
Weeks start on Mondays.
Week 1 includes Jan 4. */
int yweek;
diff --git a/patch.c b/patch.c
index 7eb83f5..1045df1 100644
--- a/patch.c
+++ b/patch.c
@@ -1,10 +1,10 @@
/* patch - a program to apply diffs to original files */
-/* $Id: patch.c,v 1.23 1997/07/05 10:32:23 eggert Exp $ */
+/* $Id: patch.c,v 1.27 1998/03/20 22:42:54 eggert Exp $ */
/*
Copyright 1984, 1985, 1986, 1987, 1988 Larry Wall
-Copyright 1989, 1990, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
+Copyright 1989, 1990-1993, 1997, 1998 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
@@ -31,8 +31,10 @@ If not, write to the Free Software Foundation,
#include <getopt.h>
#include <inp.h>
#include <pch.h>
+#include <quotearg.h>
#include <util.h>
#include <version.h>
+#include <xalloc.h>
#if HAVE_UTIME_H
# include <utime.h>
@@ -56,7 +58,7 @@ struct outstate
/* procedures */
-static FILE *create_output_file PARAMS ((char const *));
+static FILE *create_output_file PARAMS ((char const *, int));
static LINENUM locate_hunk PARAMS ((LINENUM));
static bool apply_hunk PARAMS ((struct outstate *, LINENUM));
static bool copy_till PARAMS ((struct outstate *, LINENUM));
@@ -68,9 +70,10 @@ static int numeric_string PARAMS ((char const *, int, char const *));
static void abort_hunk PARAMS ((void));
static void cleanup PARAMS ((void));
static void get_some_switches PARAMS ((void));
-static void init_output PARAMS ((char const *, struct outstate *));
-static void init_reject PARAMS ((char const *));
+static void init_output PARAMS ((char const *, int, struct outstate *));
+static void init_reject PARAMS ((void));
static void reinitialize_almost_everything PARAMS ((void));
+static void remove_if_needed PARAMS ((char const *, int volatile *));
static void usage PARAMS ((FILE *, int)) __attribute__((noreturn));
static int make_backups;
@@ -98,6 +101,7 @@ static FILE *rejfp; /* reject file pointer */
static char const *patchname;
static char *rejname;
static char const * volatile TMPREJNAME;
+static int volatile TMPREJNAME_needs_removal;
static LINENUM last_offset;
static LINENUM maxfuzz = 2;
@@ -118,15 +122,24 @@ char **argv;
char const *val;
bool somefailed = FALSE;
struct outstate outstate;
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
init_time ();
setbuf(stderr, serrbuf);
+ xalloc_fail_func = memory_fatal;
bufsize = 8 * 1024;
buf = xmalloc (bufsize);
- strippath = INT_MAX;
+ strippath = -1;
+
+ val = getenv ("QUOTING_STYLE");
+ {
+ int i = val ? argmatch (val, quoting_style_args) : -1;
+ set_quoting_style ((struct quoting_options *) 0,
+ i < 0 ? shell_quoting_style : (enum quoting_style) i);
+ }
posixly_correct = getenv ("POSIXLY_CORRECT") != 0;
backup_if_mismatch = ! posixly_correct;
@@ -134,11 +147,9 @@ char **argv;
? numeric_string (val, 1, "PATCH_GET value")
: posixly_correct - 1);
- {
- char const *v = getenv ("SIMPLE_BACKUP_SUFFIX");
- if (v && *v)
- simple_backup_suffix = v;
- }
+ val = getenv ("SIMPLE_BACKUP_SUFFIX");
+ if (val && *val)
+ simple_backup_suffix = val;
version_control = getenv ("PATCH_VERSION_CONTROL");
if (! version_control)
@@ -159,7 +170,7 @@ char **argv;
if (make_backups | backup_if_mismatch)
backup_type = get_version (version_control);
- init_output (outfile, &outstate);
+ init_output (outfile, 0, &outstate);
/* Make sure we clean up in case of disaster. */
set_signals(0);
@@ -196,10 +207,14 @@ char **argv;
/* initialize the patched file */
if (! skip_rest_of_patch && ! outfile)
- init_output (TMPOUTNAME, &outstate);
+ {
+ int exclusive = TMPOUTNAME_needs_removal ? 0 : O_EXCL;
+ TMPOUTNAME_needs_removal = 1;
+ init_output (TMPOUTNAME, exclusive, &outstate);
+ }
/* initialize reject file */
- init_reject(TMPREJNAME);
+ init_reject ();
/* find out where all the lines are */
if (!skip_rest_of_patch)
@@ -271,53 +286,62 @@ char **argv;
abort_hunk();
failed++;
if (verbosity == VERBOSE)
- say ("Hunk #%d ignored at %ld.\n", hunk, newwhere);
+ say ("Hunk #%d ignored at %s.\n", hunk,
+ format_linenum (numbuf, newwhere));
}
else if (!where
|| (where == 1 && pch_says_nonexistent (reverse)
&& instat.st_size)) {
+
if (where)
- say ("Patch attempted to create file `%s', which already exists.\n", inname);
+ say ("Patch attempted to create file %s, which already exists.\n",
+ quotearg (inname));
+
abort_hunk();
failed++;
if (verbosity != SILENT)
- say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
+ say ("Hunk #%d FAILED at %s.\n", hunk,
+ format_linenum (numbuf, newwhere));
}
else if (! apply_hunk (&outstate, where)) {
abort_hunk ();
failed++;
if (verbosity != SILENT)
- say ("Hunk #%d FAILED at %ld.\n", hunk, newwhere);
+ say ("Hunk #%d FAILED at %s.\n", hunk,
+ format_linenum (numbuf, newwhere));
} else {
if (verbosity == VERBOSE
|| (verbosity != SILENT && (fuzz || last_offset))) {
- say ("Hunk #%d succeeded at %ld", hunk, newwhere);
+ say ("Hunk #%d succeeded at %s", hunk,
+ format_linenum (numbuf, newwhere));
if (fuzz)
- say (" with fuzz %ld", fuzz);
+ say (" with fuzz %s", format_linenum (numbuf, fuzz));
if (last_offset)
- say (" (offset %ld line%s)",
- last_offset, last_offset==1?"":"s");
+ say (" (offset %s line%s)",
+ format_linenum (numbuf, last_offset),
+ "s" + (last_offset == 1));
say (".\n");
}
}
}
- if (got_hunk < 0 && using_plan_a) {
- if (outfile)
- fatal ("out of memory using Plan A");
- say ("\n\nRan out of memory using Plan A -- trying again...\n\n");
- if (outstate.ofp)
+ if (!skip_rest_of_patch)
+ {
+ if (got_hunk < 0 && using_plan_a)
{
- fclose (outstate.ofp);
- outstate.ofp = 0;
+ if (outfile)
+ fatal ("out of memory using Plan A");
+ say ("\n\nRan out of memory using Plan A -- trying again...\n\n");
+ if (outstate.ofp)
+ {
+ fclose (outstate.ofp);
+ outstate.ofp = 0;
+ }
+ fclose (rejfp);
+ continue;
}
- fclose (rejfp);
- continue;
- }
- /* finish spewing out the new file */
- if (!skip_rest_of_patch)
- {
+ /* Finish spewing out the new file. */
assert (hunk);
if (! spew_output (&outstate))
{
@@ -336,11 +360,11 @@ char **argv;
&& ! posixly_correct)))
{
if (verbosity == VERBOSE)
- say ("Removing file `%s'%s.\n", outname,
+ say ("Removing file %s%s\n", quotearg (outname),
dry_run ? " and any empty ancestor directories" : "");
if (! dry_run)
{
- move_file ((char *) 0, outname, (mode_t) 0,
+ move_file ((char *) 0, (int *) 0, outname, (mode_t) 0,
(make_backups
|| (backup_if_mismatch && (mismatch | failed))));
removedirs (outname);
@@ -353,15 +377,16 @@ char **argv;
{
mismatch = 1;
if (verbosity != SILENT)
- say ("File `%s' is not empty after patch, as expected.\n",
- outname);
+ say ("File %s is not empty after patch, as expected\n",
+ quotearg (outname));
}
if (! dry_run)
{
time_t t;
- move_file (TMPOUTNAME, outname, instat.st_mode,
+ move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal,
+ outname, instat.st_mode,
(make_backups
|| (backup_if_mismatch && (mismatch | failed))));
@@ -375,17 +400,19 @@ char **argv;
&& ! pch_says_nonexistent (reverse)
&& (t = pch_timestamp (reverse)) != (time_t) -1
&& t != instat.st_mtime)
- say ("not setting time of file `%s' (time mismatch)\n",
- outname);
+ say ("Not setting time of file %s (time mismatch)\n",
+ quotearg (outname));
else if (! force && (mismatch | failed))
- say ("not setting time of file `%s' (contents mismatch)\n",
- outname);
+ say ("Not setting time of file %s (contents mismatch)\n",
+ quotearg (outname));
else if (utime (outname, &utimbuf) != 0)
- pfatal ("can't set timestamp on file `%s'", outname);
+ pfatal ("Can't set timestamp on file %s",
+ quotearg (outname));
}
if (! inerrno && chmod (outname, instat.st_mode) != 0)
- pfatal ("can't set permissions on file `%s'", outname);
+ pfatal ("Can't set permissions on file %s",
+ quotearg (outname));
}
}
}
@@ -403,15 +430,17 @@ char **argv;
strcpy (rej, outname);
addext (rej, ".rej", '#');
}
- say (" -- saving rejects to %s", rej);
+ say (" -- saving rejects to file %s", quotearg (rej));
if (! dry_run)
{
- move_file (TMPREJNAME, rej, instat.st_mode, FALSE);
+ move_file (TMPREJNAME, &TMPREJNAME_needs_removal,
+ rej, instat.st_mode, FALSE);
if (! inerrno
&& (chmod (rej, (instat.st_mode
& ~(S_IXUSR|S_IXGRP|S_IXOTH)))
!= 0))
- pfatal ("can't set permissions on file `%s'", rej);
+ pfatal ("can't set permissions on file %s",
+ quotearg (rej));
}
if (!rejname)
free (rej);
@@ -490,12 +519,14 @@ static struct option const longopts[] =
{"basename-prefix", required_argument, NULL, 'Y'},
{"suffix", required_argument, NULL, 'z'},
{"set-utc", no_argument, NULL, 'Z'},
- {"dry-run", no_argument, NULL, 129},
- {"verbose", no_argument, NULL, 130},
- {"binary", no_argument, NULL, 131},
- {"help", no_argument, NULL, 132},
- {"backup-if-mismatch", no_argument, NULL, 133},
- {"no-backup-if-mismatch", no_argument, NULL, 134},
+ {"dry-run", no_argument, NULL, CHAR_MAX + 1},
+ {"verbose", no_argument, NULL, CHAR_MAX + 2},
+ {"binary", no_argument, NULL, CHAR_MAX + 3},
+ {"help", no_argument, NULL, CHAR_MAX + 4},
+ {"backup-if-mismatch", no_argument, NULL, CHAR_MAX + 5},
+ {"no-backup-if-mismatch", no_argument, NULL, CHAR_MAX + 6},
+ {"posix", no_argument, NULL, CHAR_MAX + 7},
+ {"quoting-style", required_argument, NULL, CHAR_MAX + 8},
{NULL, no_argument, NULL, 0}
};
@@ -528,6 +559,10 @@ static char const *const option_help[] =
" -Z --set-utc Set times of patched files, assuming diff uses UTC (GMT).",
" -T --set-time Likewise, assuming local time.",
"",
+" --quoting-style=WORD output file names using quoting style WORD.",
+" Valid WORDs are: literal, shell, shell-always, c, escape.",
+" Default is taken from QUOTING_STYLE env variable, or 'shell' if unset.",
+"",
"Backup and version control options:",
"",
" -b --backup Back up the original contents of each file.",
@@ -540,7 +575,7 @@ static char const *const option_help[] =
" -Y PREFIX --basename-prefix=PREFIX Prepend PREFIX to backup file basenames.",
" -z SUFFIX --suffix=SUFFIX Append SUFFIX to backup file names.",
"",
-" -g NUM --get=NUM Get files from RCS or SCCS if positive; ask if negative.",
+" -g NUM --get=NUM Get files from RCS etc. if positive; ask if negative.",
"",
"Miscellaneous options:",
"",
@@ -549,6 +584,7 @@ static char const *const option_help[] =
" -s --quiet --silent Work silently unless an error occurs.",
" --verbose Output extra information about the work being done.",
" --dry-run Do not actually change any files; just print what would happen.",
+" --posix Conform to the POSIX standard.",
"",
" -d DIR --directory=DIR Change the working directory to DIR first.",
#if HAVE_SETMODE
@@ -560,7 +596,7 @@ static char const *const option_help[] =
" -v --version Output version info.",
" --help Output this help.",
"",
-"Report bugs to <bug-gnu-utils@prep.ai.mit.edu>.",
+"Report bugs to <bug-gnu-utils@gnu.org>.",
0
};
@@ -630,7 +666,7 @@ get_some_switches()
break;
case 'd':
if (chdir(optarg) < 0)
- pfatal ("can't change directory to `%s'", optarg);
+ pfatal ("Can't change to directory %s", quotearg (optarg));
break;
case 'D':
do_defines = savestr (optarg);
@@ -715,25 +751,40 @@ get_some_switches()
case 'Z':
set_utc = 1;
break;
- case 129:
+ case CHAR_MAX + 1:
dry_run = TRUE;
break;
- case 130:
+ case CHAR_MAX + 2:
verbosity = VERBOSE;
break;
- case 131:
+ case CHAR_MAX + 3:
#if HAVE_SETMODE
binary_transput = O_BINARY;
#endif
break;
- case 132:
+ case CHAR_MAX + 4:
usage (stdout, 0);
- case 133:
+ case CHAR_MAX + 5:
backup_if_mismatch = 1;
break;
- case 134:
+ case CHAR_MAX + 6:
backup_if_mismatch = 0;
break;
+ case CHAR_MAX + 7:
+ posixly_correct = 1;
+ break;
+ case CHAR_MAX + 8:
+ {
+ int i = argmatch (optarg, quoting_style_args);
+ if (i < 0)
+ {
+ invalid_arg ("quoting style", optarg, i);
+ usage (stderr, 2);
+ }
+ set_quoting_style ((struct quoting_options *) 0,
+ (enum quoting_style) i);
+ }
+ break;
default:
usage (stderr, 2);
}
@@ -749,8 +800,8 @@ get_some_switches()
patchname = savestr (Argv[optind++]);
if (optind < Argc)
{
- fprintf (stderr, "%s: extra operand `%s'\n",
- program_name, Argv[optind]);
+ fprintf (stderr, "%s: %s: extra operand\n",
+ program_name, quotearg (Argv[optind]));
usage (stderr, 2);
}
}
@@ -780,17 +831,17 @@ numeric_string (string, negative_allowed, argtype_msgid)
int next_value = v10 + signed_digit;
if (9 < (unsigned) digit)
- fatal ("%s `%s' is not a number", argtype_msgid, string);
+ fatal ("%s %s is not a number", argtype_msgid, quotearg (string));
if (v10 / 10 != value || (next_value < v10) != (signed_digit < 0))
- fatal ("%s `%s' is too large", argtype_msgid, string);
+ fatal ("%s %s is too large", argtype_msgid, quotearg (string));
value = next_value;
}
while (*++p);
if (value < 0 && ! negative_allowed)
- fatal ("%s `%s' is negative", argtype_msgid, string);
+ fatal ("%s %s is negative", argtype_msgid, quotearg (string));
return value;
}
@@ -860,17 +911,23 @@ LINENUM fuzz;
}
for (offset = 0; offset <= max_offset; offset++) {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
if (offset <= max_pos_offset
&& patch_match (first_guess, offset, prefix_fuzz, suffix_fuzz)) {
if (debug & 1)
- say ("Offset changing from %ld to %ld\n", last_offset, offset);
+ say ("Offset changing from %s to %s\n",
+ format_linenum (numbuf0, last_offset),
+ format_linenum (numbuf1, offset));
last_offset = offset;
return first_guess+offset;
}
if (0 < offset && offset <= max_neg_offset
&& patch_match (first_guess, -offset, prefix_fuzz, suffix_fuzz)) {
if (debug & 1)
- say ("Offset changing from %ld to %ld\n", last_offset, -offset);
+ say ("Offset changing from %s to %s\n",
+ format_linenum (numbuf0, last_offset),
+ format_linenum (numbuf1, -offset));
last_offset = -offset;
return first_guess-offset;
}
@@ -897,22 +954,30 @@ abort_hunk()
fprintf(rejfp, "***************\n");
for (i=0; i<=pat_end; i++) {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
switch (pch_char(i)) {
case '*':
if (oldlast < oldfirst)
fprintf(rejfp, "*** 0%s\n", stars);
else if (oldlast == oldfirst)
- fprintf(rejfp, "*** %ld%s\n", oldfirst, stars);
+ fprintf (rejfp, "*** %s%s\n",
+ format_linenum (numbuf0, oldfirst), stars);
else
- fprintf(rejfp, "*** %ld,%ld%s\n", oldfirst, oldlast, stars);
+ fprintf (rejfp, "*** %s,%s%s\n",
+ format_linenum (numbuf0, oldfirst),
+ format_linenum (numbuf1, oldlast), stars);
break;
case '=':
if (newlast < newfirst)
fprintf(rejfp, "--- 0%s\n", minuses);
else if (newlast == newfirst)
- fprintf(rejfp, "--- %ld%s\n", newfirst, minuses);
+ fprintf (rejfp, "--- %s%s\n",
+ format_linenum (numbuf0, newfirst), minuses);
else
- fprintf(rejfp, "--- %ld,%ld%s\n", newfirst, newlast, minuses);
+ fprintf (rejfp, "--- %s,%s%s\n",
+ format_linenum (numbuf0, newfirst),
+ format_linenum (numbuf1, newlast), minuses);
break;
case ' ': case '-': case '+': case '!':
fprintf (rejfp, "%c ", pch_char (i));
@@ -994,12 +1059,14 @@ apply_hunk (outstate, where)
new++;
}
else if (pch_char(new) != pch_char(old)) {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
if (debug & 1)
say ("oldchar = '%c', newchar = '%c'\n",
pch_char (old), pch_char (new));
- fatal ("Out-of-sync patch, lines %ld,%ld -- mangled text or line numbers, maybe?",
- pch_hunk_beg() + old,
- pch_hunk_beg() + new);
+ fatal ("Out-of-sync patch, lines %s,%s -- mangled text or line numbers, maybe?",
+ format_linenum (numbuf0, pch_hunk_beg() + old),
+ format_linenum (numbuf1, pch_hunk_beg() + new));
}
else if (pch_char(new) == '!') {
assert (outstate->after_newline);
@@ -1092,24 +1159,27 @@ apply_hunk (outstate, where)
/* Create an output file. */
static FILE *
-create_output_file (name)
+create_output_file (name, open_flags)
char const *name;
+ int open_flags;
{
- int fd = create_file (name, O_WRONLY | binary_transput, instat.st_mode);
+ int fd = create_file (name, O_WRONLY | binary_transput | open_flags,
+ instat.st_mode);
FILE *f = fdopen (fd, binary_transput ? "wb" : "w");
if (! f)
- pfatal ("can't create `%s'", name);
+ pfatal ("Can't create file %s", quotearg (name));
return f;
}
/* Open the new file. */
static void
-init_output (name, outstate)
+init_output (name, open_flags, outstate)
char const *name;
+ int open_flags;
struct outstate *outstate;
{
- outstate->ofp = name ? create_output_file (name) : (FILE *) 0;
+ outstate->ofp = name ? create_output_file (name, open_flags) : (FILE *) 0;
outstate->after_newline = 1;
outstate->zero_output = 1;
}
@@ -1117,10 +1187,11 @@ init_output (name, outstate)
/* Open a file to put hunks we can't locate. */
static void
-init_reject(name)
- char const *name;
+init_reject ()
{
- rejfp = create_output_file (name);
+ int exclusive = TMPREJNAME_needs_removal ? 0 : O_EXCL;
+ TMPREJNAME_needs_removal = 1;
+ rejfp = create_output_file (TMPREJNAME, exclusive);
}
/* Copy input file to output, up to wherever hunk is to be applied. */
@@ -1163,7 +1234,13 @@ spew_output (outstate)
struct outstate *outstate;
{
if (debug & 256)
- say ("il=%ld lfl=%ld\n", input_lines, last_frozen_line);
+ {
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
+ say ("il=%s lfl=%s\n",
+ format_linenum (numbuf0, input_lines),
+ format_linenum (numbuf1, last_frozen_line));
+ }
if (last_frozen_line < input_lines)
if (! copy_till (outstate, input_lines))
@@ -1293,10 +1370,22 @@ fatal_exit (sig)
}
static void
+remove_if_needed (name, needs_removal)
+ char const *name;
+ int volatile *needs_removal;
+{
+ if (*needs_removal)
+ {
+ unlink (name);
+ *needs_removal = 0;
+ }
+}
+
+static void
cleanup ()
{
- unlink (TMPINNAME);
- unlink (TMPOUTNAME);
- unlink (TMPPATNAME);
- unlink (TMPREJNAME);
+ remove_if_needed (TMPINNAME, &TMPINNAME_needs_removal);
+ remove_if_needed (TMPOUTNAME, &TMPOUTNAME_needs_removal);
+ remove_if_needed (TMPPATNAME, &TMPPATNAME_needs_removal);
+ remove_if_needed (TMPREJNAME, &TMPREJNAME_needs_removal);
}
diff --git a/patch.man b/patch.man
index e3589ba..d7190cb 100644
--- a/patch.man
+++ b/patch.man
@@ -2,7 +2,7 @@
.de Id
.ds Dt \\$4
..
-.Id $Id: patch.man,v 1.23 1997/07/16 12:26:36 eggert Exp $
+.Id $Id: patch.man,v 1.25 1998/03/17 18:35:38 eggert Exp $
.ds = \-\^\-
.de Sp
.if t .sp .3
@@ -66,7 +66,8 @@ diff listing to
.BR patch ,
and it should work.
If the entire diff is indented by a consistent amount,
-or if a context diff is encapsulated one or more times by prepending
+or if a context diff contains lines ending in \s-1CRLF\s0
+or is encapsulated one or more times by prepending
"\fB\- \fP" to lines starting with "\fB\-\fP" as specified by Internet RFC 934,
this is taken into account.
.PP
@@ -136,22 +137,31 @@ is specified on the command line,
.B patch
tries to figure out from the leading garbage what the name of the file
to edit is, using the following rules.
+.LP
+First,
+.B patch
+takes an ordered list of candidate file names as follows:
.TP 3
.B " \(bu"
If the header is that of a context diff,
.B patch
takes the old and new file names in the header.
-Any
+A name is ignored if it does not have enough slashes to satisfy the
+.BI \-p num
+or
+.BI \*=strip= num
+option.
+The name
.B /dev/null
-names are ignored.
+is also ignored.
.TP
.B " \(bu"
If there is an
.B Index:\&
line in the leading garbage
-and if either the old and new names are both absent or the
-.B POSIXLY_CORRECT
-environment variable is set,
+and if either the old and new names are both absent or if
+.B patch
+is conforming to \s-1POSIX\s0,
.B patch
takes the name in the
.B Index:\&
@@ -159,39 +169,47 @@ line.
.TP
.B " \(bu"
For the purpose of the following rules,
-the names are considered to be in the order (old, new, index),
+the candidate file names are considered to be in the order (old, new, index),
regardless of the order that they appear in the header.
-.TP
+.LP
+Then
+.B patch
+selects a file name from the candidate list as follows:
+.TP 3
.B " \(bu"
If some of the named files exist,
.B patch
-uses the first name if the
-.B POSIXLY_CORRECT
-environment variable is set, and the best name otherwise.
+selects the first name if conforming to \s-1POSIX\s0,
+and the best name otherwise.
.TP
.B " \(bu"
If
.B patch
-is not ignoring \s-1RCS\s0 and \s-1SCCS\s0 (see the
+is not ignoring \s-1RCS\s0, ClearCase, and \s-1SCCS\s0 (see the
.BI "\-g\ " num
or
.BI \*=get= num
option), and no named files exist
-but an \s-1RCS\s0 or \s-1SCCS\s0 master is found,
+but an \s-1RCS\s0, ClearCase, or \s-1SCCS\s0 master is found,
.B patch
-uses the first named file with an \s-1RCS\s0 or \s-1SCCS\s0 master.
+selects the first named file
+with an \s-1RCS\s0, ClearCase, or \s-1SCCS\s0 master.
.TP
.B " \(bu"
-If no named files exist, no \s-1RCS\s0 or \s-1SCCS\s0 master was found,
+If no named files exist,
+no \s-1RCS\s0, ClearCase, or \s-1SCCS\s0 master was found,
some names are given,
-.B POSIXLY_CORRECT
-is not set, and the patch appears to create a file,
.B patch
-uses the best name requiring the creation of the fewest directories.
+is not conforming to \s-1POSIX\s0,
+and the patch appears to create a file,
+.B patch
+selects the best name requiring the creation of the fewest directories.
.TP
.B " \(bu"
If no file name results from the above heuristics, you are asked
-for the name of the file to patch.
+for the name of the file to patch, and
+.B patch
+selects that name.
.LP
To determine the
.I best
@@ -248,16 +266,16 @@ option for details about how backup file names are determined.
.B \*=backup\-if\-mismatch
Back up a file if the patch does not match the file exactly
and if backups are not otherwise requested.
-This is the default unless the
-.B POSIXLY_CORRECT
-environment variable is set.
+This is the default unless
+.B patch
+is conforming to \s-1POSIX\s0.
.TP
.B \*=no\-backup\-if\-mismatch
Do not back up a file if the patch does not match the file exactly
and if backups are not otherwise requested.
-This is the default if the
-.B POSIXLY_CORRECT
-environment variable is set.
+This is the default if
+.B patch
+is conforming to \s-1POSIX\s0.
.TP
\fB\-B\fP \fIpref\fP or \fB\*=prefix=\fP\fIpref\fP
Prefix
@@ -274,7 +292,7 @@ is
Read and write all files in binary mode,
except for standard output and
.BR /dev/tty .
-This option has no effect on \s-1POSIX\s0-compliant systems.
+This option has no effect on \s-1POSIX\s0-conforming systems.
On systems like \s-1DOS\s0 where this option makes a difference,
the patch should be generated by
.BR "diff\ \-a\ \*=binary" .
@@ -309,9 +327,9 @@ Normally this option is unnecessary, since
.B patch
can examine the time stamps on the header to determine whether a file
should exist after patching.
-However, if the input is not a context diff or if the
-.B POSIXLY_CORRECT
-environment variable is set,
+However, if the input is not a context diff or if
+.B patch
+is conforming to \s-1POSIX\s0,
.B patch
does not remove empty patched files unless this option is given.
When
@@ -343,21 +361,23 @@ the number of lines of context in the context diff, ordinarily 3.
This option controls
.BR patch 's
actions when a file is under \s-1RCS\s0 or \s-1SCCS\s0 control,
-and does not exist or is read-only and matches the default version.
+and does not exist or is read-only and matches the default version,
+or when a file is under ClearCase control and does not exist.
If
.I num
is positive,
.B patch
gets (or checks out) the file from the revision control system; if zero,
.B patch
-ignores \s-1RCS\s0 and \s-1SCCS\s0 and does not get the file; and if negative,
+ignores \s-1RCS\s0, ClearCase, and \s-1SCCS\s0
+and does not get the file; and if negative,
.B patch
asks the user whether to get the file.
The default value of this option is given by the value of the
.B PATCH_GET
environment variable if it is set; if not, the default value is zero if
-.B POSIXLY_CORRECT
-is set, negative otherwise.
+.B patch
+is conforming to \s-1POSIX\s0, negative otherwise.
.TP
.B "\*=help"
Print a summary of options and exit.
@@ -426,6 +446,62 @@ or the directory specified by the
.B \-d
option.
.TP
+.B \*=posix
+Conform more strictly to the \s-1POSIX\s0 standard, as follows.
+.RS
+.TP 3
+.B " \(bu"
+Take the first existing file from the list (old, new, index)
+when intuiting file names from diff headers.
+.TP
+.B " \(bu"
+Do not remove files that are empty after patching.
+.TP
+.B " \(bu"
+Do not ask whether to get files from \s-1RCS\s0, ClearCase, or \s-1SCCS\s0.
+.TP
+.B " \(bu"
+Require that all options precede the files in the command line.
+.TP
+.B " \(bu"
+Do not backup files when there is a mismatch.
+.RE
+.TP
+.BI \*=quoting\-style= word
+Use style
+.I word
+to quote output names.
+The
+.I word
+should be one of the following:
+.RS
+.TP
+.B literal
+Output names as-is.
+.TP
+.B shell
+Quote names for the shell if they contain shell metacharacters or would
+cause ambiguous output.
+.TP
+.B shell-always
+Quote names for the shell, even if they would normally not require quoting.
+.TP
+.B c
+Quote names as for a C language string.
+.TP
+.B escape
+Quote as with
+.B c
+except omit the surrounding double-quote characters.
+.LP
+You can specify the default value of the
+.B \*=quoting\-style
+option with the environment variable
+.BR QUOTING_STYLE .
+If that environment variable is not set, the default value is
+.BR shell .
+.RE
+.TP
\fB\-r\fP \fIrejectfile\fP or \fB\*=reject\-file=\fP\fIrejectfile\fP
Put rejects into
.I rejectfile
@@ -636,10 +712,10 @@ all files that depend on the patched files, so that later invocations of
do not get confused by the patched files' times.
.SH ENVIRONMENT
.TP 3
-\fBPATCH_GET\fP
+.B PATCH_GET
This specifies whether
.B patch
-gets missing or read-only files from \s-1RCS\s0 or \s-1SCCS\s0
+gets missing or read-only files from \s-1RCS\s0, ClearCase, or \s-1SCCS\s0
by default; see the
.B \-g
or
@@ -649,13 +725,15 @@ option.
.B POSIXLY_CORRECT
If set,
.B patch
-conforms more strictly to the \s-1POSIX\s0 standard:
-it takes the first existing file from the list (old, new, index)
-when intuiting file names from diff headers,
-it does not remove files that are empty after patching,
-it does not ask whether to get files from \s-1RCS\s0 or \s-1SCCS\s0,
-it requires that all options precede the files in the command line,
-and it does not backup files when there is a mismatch.
+conforms more strictly to the \s-1POSIX\s0 standard by default:
+see the
+.B \*=posix
+option.
+.TP
+.B QUOTING_STYLE
+Default value of the
+.B \*=quoting\-style
+option.
.TP
.B SIMPLE_BACKUP_SUFFIX
Extension to use for simple backup file names instead of
@@ -748,9 +826,9 @@ This only works if the file you want to create doesn't exist already in
the target directory.
Conversely, you can remove a file by sending out a context diff that compares
the file to be deleted with an empty file dated the Epoch.
-The file will be removed unless the
-.B POSIXLY_CORRECT
-environment variable is set and the
+The file will be removed unless
+.B patch
+is conforming to \s-1POSIX\s0 and the
.B \-E
or
.B \*=remove\-empty\-files
@@ -879,7 +957,7 @@ The \s-1POSIX\s0 standard specifies behavior that differs from
traditional behavior.
You should be aware of these differences if you must interoperate with
.B patch
-versions 2.1 and earlier, which are not \s-1POSIX\s0-compliant.
+versions 2.1 and earlier, which do not conform to \s-1POSIX\s0.
.TP 3
.B " \(bu"
In traditional
@@ -930,6 +1008,8 @@ In \s-1GNU\s0
.BR patch ,
this behavior is enabled with the
.B \*=no\-backup\-if\-mismatch
+option, or by conforming to \s-1POSIX\s0 with the
+.B \*=posix
option or by setting the
.B POSIXLY_CORRECT
environment variable.
@@ -949,11 +1029,11 @@ Traditional
.B patch
used a complicated (and incompletely documented) method
to intuit the name of the file to be patched from the patch header.
-This method was not \s-1POSIX\s0-compliant, and had a few gotchas.
+This method did not conform to \s-1POSIX\s0, and had a few gotchas.
Now
.B patch
uses a different, equally complicated (but better documented) method
-that is optionally \s-1POSIX\s0-compliant; we hope it has
+that is optionally \s-1POSIX\s0-conforming; we hope it has
fewer gotchas. The two methods are compatible if the
file names in the context diff header and the
.B Index:\&
@@ -994,8 +1074,9 @@ meant to be executed by anyone running \s-1GNU\s0
.BR patch ,
traditional
.BR patch ,
-or a \s-1POSIX\s0-compliant
-.BR patch .
+or a
+.B patch
+that conforms to \s-1POSIX\s0.
Spaces are significant in the following list, and operands are required.
.Sp
.nf
@@ -1015,6 +1096,9 @@ Spaces are significant in the following list, and operands are required.
.in
.fi
.SH BUGS
+Please report bugs via email to
+.BR <bug-gnu-utils@gnu.org> .
+.PP
.B patch
could be smarter about partial matches, excessively deviant offsets and
swapped code, but that would take an extra pass.
@@ -1036,7 +1120,8 @@ Copyright
.br
Copyright
.if t \(co
-1997 Free Software Foundation, Inc.
+1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+Free Software Foundation, Inc.
.PP
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
diff --git a/pch.c b/pch.c
index f5c0ce0..c87644e 100644
--- a/pch.c
+++ b/pch.c
@@ -1,10 +1,10 @@
/* reading patches */
-/* $Id: pch.c,v 1.26 1997/07/21 17:59:46 eggert Exp $ */
+/* $Id: pch.c,v 1.27 1998/03/15 14:44:47 eggert Exp $ */
/*
Copyright 1986, 1987, 1988 Larry Wall
-Copyright 1990, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
+Copyright 1990, 1991, 1992, 1993, 1997, 1998 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
@@ -26,6 +26,7 @@ If not, write to the Free Software Foundation,
#include <common.h>
#include <backupfile.h>
#include <inp.h>
+#include <quotearg.h>
#include <util.h>
#undef XTERN
#define XTERN
@@ -55,6 +56,7 @@ static size_t *p_len; /* line length including \n if any */
static char *p_Char; /* +, -, and ! */
static LINENUM hunkmax = INITHUNKMAX; /* size of above arrays */
static int p_indent; /* indent to patch */
+static int p_strip_trailing_cr; /* nonzero if stripping trailing \r */
static file_offset p_base; /* where to intuit this time */
static LINENUM p_bline; /* line # of p_base */
static file_offset p_start; /* where intuit found a patch */
@@ -65,10 +67,11 @@ static LINENUM p_bfake = -1; /* beg of faked up lines */
enum nametype { OLD, NEW, INDEX, NONE };
+static char *scan_linenum PARAMS ((char *, LINENUM *));
static enum diff intuit_diff_type PARAMS ((void));
static enum nametype best_name PARAMS ((char * const *, int const *));
static int prefix_components PARAMS ((char *, int));
-static size_t pget_line PARAMS ((int, int));
+static size_t pget_line PARAMS ((int, int, int));
static size_t get_line PARAMS ((void));
static bool incomplete_line PARAMS ((void));
static bool grow_hunkmax PARAMS ((void));
@@ -88,6 +91,7 @@ re_patch()
p_end = -1;
p_max = 0;
p_indent = 0;
+ p_strip_trailing_cr = 0;
}
/* Open the patch file at the beginning of time. */
@@ -119,9 +123,14 @@ open_patch_file(filename)
else
{
size_t charsread;
- pfp = fopen (TMPPATNAME, "w+b");
+ int exclusive = TMPPATNAME_needs_removal ? 0 : O_EXCL;
+ TMPPATNAME_needs_removal = 1;
+ pfp = fdopen (create_file (TMPPATNAME,
+ O_RDWR | O_BINARY | exclusive,
+ (mode_t) 0),
+ "w+b");
if (!pfp)
- pfatal ("can't create `%s'", TMPPATNAME);
+ pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME));
for (st.st_size = 0;
(charsread = fread (buf, 1, bufsize, stdin)) != 0;
st.st_size += charsread)
@@ -138,7 +147,7 @@ open_patch_file(filename)
{
pfp = fopen (filename, binary_transput ? "rb" : "r");
if (!pfp)
- pfatal ("can't open patch file `%s'", filename);
+ pfatal ("Can't open patch file %s", quotearg (filename));
if (fstat (fileno (pfp), &st) != 0)
pfatal ("fstat");
}
@@ -223,11 +232,14 @@ there_is_another_patch()
{
if (p_indent)
say ("(Patch is indented %d space%s.)\n", p_indent, p_indent==1?"":"s");
+ if (p_strip_trailing_cr)
+ say ("(Stripping trailing CRs from patch.)\n");
if (! inname)
{
- say ("can't find file to patch at input line %ld\n",
- p_sline);
- say (strippath == INT_MAX
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
+ say ("can't find file to patch at input line %s\n",
+ format_linenum (numbuf, p_sline));
+ say (strippath == -1
? "Perhaps you should have used the -p or --strip option?\n"
: "Perhaps you used the wrong -p or --strip option?\n");
}
@@ -274,16 +286,10 @@ there_is_another_patch()
static enum diff
intuit_diff_type()
{
- register char *s;
- register char *t;
- register int indent;
register file_offset this_line = 0;
- register file_offset previous_line;
register file_offset first_command_line = -1;
LINENUM fcl_line = 0; /* Pacify `gcc -W'. */
- register bool last_line_was_command = FALSE;
register bool this_is_a_command = FALSE;
- register bool stars_last_line = FALSE;
register bool stars_this_line = FALSE;
enum nametype i;
char *name[3];
@@ -302,12 +308,20 @@ intuit_diff_type()
Fseek (pfp, p_base, SEEK_SET);
p_input_line = p_bline - 1;
for (;;) {
- previous_line = this_line;
- last_line_was_command = this_is_a_command;
- stars_last_line = stars_this_line;
+ register char *s;
+ register char *t;
+ register file_offset previous_line = this_line;
+ register bool last_line_was_command = this_is_a_command;
+ register bool stars_last_line = stars_this_line;
+ register int indent = 0;
+ int strip_trailing_cr;
+ size_t chars_read;
+
this_line = file_tell (pfp);
- indent = 0;
- if (! pget_line (0, 0)) {
+ chars_read = pget_line (0, 0, 0);
+ if (chars_read == (size_t) -1)
+ memory_fatal ();
+ if (! chars_read) {
if (first_command_line >= 0) {
/* nothing but deletes!? */
p_start = first_command_line;
@@ -321,6 +335,7 @@ intuit_diff_type()
return NO_DIFF;
}
}
+ strip_trailing_cr = 2 <= chars_read && buf[chars_read - 2] == '\r';
for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) {
if (*s == '\t')
indent = (indent + 8) & ~7;
@@ -335,6 +350,7 @@ intuit_diff_type()
first_command_line = this_line;
fcl_line = p_input_line;
p_indent = indent; /* assume this for now */
+ p_strip_trailing_cr = strip_trailing_cr;
}
if (!stars_last_line && strnEQ(s, "*** ", 4))
name[OLD] = fetchname (s+4, strippath, &p_timestamp[OLD]);
@@ -376,6 +392,7 @@ intuit_diff_type()
first_command_line >= 0 &&
strEQ(s, ".\n") ) {
p_indent = indent;
+ p_strip_trailing_cr = strip_trailing_cr;
p_start = first_command_line;
p_sline = fcl_line;
retval = ED_DIFF;
@@ -393,22 +410,26 @@ intuit_diff_type()
name[NEW] = t;
s += 4;
- if (! atol (s))
+ if (s[0] == '0' && !ISDIGIT (s[1]))
p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];
while (*s != ' ' && *s != '\n')
s++;
while (*s == ' ')
s++;
- if (! atol (s))
+ if (s[0] == '+' && s[1] == '0' && !ISDIGIT (s[2]))
p_says_nonexistent[NEW] = 1 + ! p_timestamp[NEW];
p_indent = indent;
+ p_strip_trailing_cr = strip_trailing_cr;
p_start = this_line;
p_sline = p_input_line;
retval = UNI_DIFF;
if (! ((name[OLD] || ! p_timestamp[OLD])
&& (name[NEW] || ! p_timestamp[NEW])))
- say ("missing header for unified diff at line %ld of patch\n",
- p_sline);
+ {
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
+ say ("missing header for unified diff at line %s of patch\n",
+ format_linenum (numbuf, p_sline));
+ }
goto scan_exit;
}
stars_this_line = strnEQ(s, "********", 8);
@@ -417,13 +438,14 @@ intuit_diff_type()
|| diff_type == NEW_CONTEXT_DIFF)
&& stars_last_line && strnEQ (s, "*** ", 4)) {
s += 4;
- if (! atol (s))
+ if (s[0] == '0' && !ISDIGIT (s[1]))
p_says_nonexistent[OLD] = 1 + ! p_timestamp[OLD];
/* if this is a new context diff the character just before */
/* the newline is a '*'. */
while (*s != '\n')
s++;
p_indent = indent;
+ p_strip_trailing_cr = strip_trailing_cr;
p_start = previous_line;
p_sline = p_input_line - 1;
retval = (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
@@ -443,8 +465,11 @@ intuit_diff_type()
if (! ((name[OLD] || ! p_timestamp[OLD])
&& (name[NEW] || ! p_timestamp[NEW])))
- say ("missing header for context diff at line %ld of patch\n",
- p_sline);
+ {
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
+ say ("missing header for context diff at line %s of patch\n",
+ format_linenum (numbuf, p_sline));
+ }
goto scan_exit;
}
if ((diff_type == NO_DIFF || diff_type == NORMAL_DIFF) &&
@@ -453,6 +478,7 @@ intuit_diff_type()
p_start = previous_line;
p_sline = p_input_line - 1;
p_indent = indent;
+ p_strip_trailing_cr = strip_trailing_cr;
retval = NORMAL_DIFF;
goto scan_exit;
}
@@ -545,7 +571,8 @@ intuit_diff_type()
version_controlled[i] = 0;
free (getbuf);
- free (diffbuf);
+ if (diffbuf)
+ free (diffbuf);
if (! stat_errno[i])
break;
@@ -560,12 +587,12 @@ intuit_diff_type()
{
assert (i0 != NONE);
if (ok_to_reverse
- ("The next patch%s would %s the file `%s',\nwhich %s!",
+ ("The next patch%s would %s the file %s,\nwhich %s!",
reverse ? ", when reversed," : "",
(i == NONE ? "delete"
: st[i].st_size == 0 ? "empty out"
: "create"),
- name[i == NONE || st[i].st_size == 0 ? i0 : i],
+ quotearg (name[i == NONE || st[i].st_size == 0 ? i0 : i]),
(i == NONE ? "does not exist"
: st[i].st_size == 0 ? "is already empty"
: "already exists")))
@@ -657,9 +684,9 @@ best_name (name, ignore)
int components[3];
int components_min = INT_MAX;
size_t basename_len[3];
- size_t basename_len_min = (size_t) -1;
+ size_t basename_len_min = SIZE_MAX;
size_t len[3];
- size_t len_min = (size_t) -1;
+ size_t len_min = SIZE_MAX;
for (i = OLD; i <= INDEX; i++)
if (name[i] && !ignore[i])
@@ -744,10 +771,43 @@ LINENUM file_line;
static void
malformed ()
{
- fatal ("malformed patch at line %ld: %s", p_input_line, buf);
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
+ fatal ("malformed patch at line %s: %s",
+ format_linenum (numbuf, p_input_line), buf);
/* about as informative as "Syntax error" in C */
}
+/* Parse a line number from a string.
+ Return the address of the first char after the number. */
+static char *
+scan_linenum (s0, linenum)
+ char *s0;
+ LINENUM *linenum;
+{
+ char *s;
+ LINENUM n = 0;
+ int overflow = 0;
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
+
+ for (s = s0; ISDIGIT (*s); s++)
+ {
+ LINENUM new_n = 10 * n + (*s - '0');
+ overflow |= new_n / 10 != n;
+ n = new_n;
+ }
+
+ if (s == s0)
+ fatal ("missing line number at line %s: %s",
+ format_linenum (numbuf, p_input_line), buf);
+
+ if (overflow)
+ fatal ("line number %.*s is too large at line %s: %s",
+ (int) (s - s0), s0, format_linenum (numbuf, p_input_line), buf);
+
+ *linenum = n;
+ return s;
+}
+
/* 1 if there is more of the current diff listing to process;
0 if not; -1 if ran out of memory. */
@@ -759,6 +819,10 @@ another_hunk (difftype, rev)
register char *s;
register LINENUM context = 0;
register size_t chars_read;
+ char numbuf0[LINENUM_LENGTH_BOUND + 1];
+ char numbuf1[LINENUM_LENGTH_BOUND + 1];
+ char numbuf2[LINENUM_LENGTH_BOUND + 1];
+ char numbuf3[LINENUM_LENGTH_BOUND + 1];
while (p_end >= 0) {
if (p_end == p_efake)
@@ -821,8 +885,9 @@ another_hunk (difftype, rev)
}
p_end++;
if (p_end == hunkmax)
- fatal ("unterminated hunk starting at line %ld; giving up at line %ld: %s",
- pch_hunk_beg (), p_input_line, buf);
+ fatal ("unterminated hunk starting at line %s; giving up at line %s: %s",
+ format_linenum (numbuf0, pch_hunk_beg ()),
+ format_linenum (numbuf1, p_input_line), buf);
assert(p_end < hunkmax);
p_Char[p_end] = *buf;
p_len[p_end] = 0;
@@ -835,16 +900,16 @@ another_hunk (difftype, rev)
goto hunk_done;
}
else
- fatal ("unexpected end of hunk at line %ld",
- p_input_line);
+ fatal ("unexpected end of hunk at line %s",
+ format_linenum (numbuf0, p_input_line));
}
if (p_end != 0) {
if (repl_beginning && repl_could_be_missing) {
repl_missing = TRUE;
goto hunk_done;
}
- fatal ("unexpected `***' at line %ld: %s",
- p_input_line, buf);
+ fatal ("unexpected `***' at line %s: %s",
+ format_linenum (numbuf0, p_input_line), buf);
}
context = 0;
p_len[p_end] = strlen (buf);
@@ -854,19 +919,14 @@ another_hunk (difftype, rev)
}
for (s = buf; *s && !ISDIGIT (*s); s++)
continue;
- if (!*s)
- malformed ();
if (strnEQ(s,"0,0",3))
remove_prefix (s, 2);
- p_first = (LINENUM) atol(s);
- while (ISDIGIT (*s))
- s++;
+ s = scan_linenum (s, &p_first);
if (*s == ',') {
while (*s && !ISDIGIT (*s))
s++;
- if (!*s)
- malformed ();
- p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
+ scan_linenum (s, &p_ptrn_lines);
+ p_ptrn_lines += 1 - p_first;
}
else if (p_first)
p_ptrn_lines = 1;
@@ -901,14 +961,17 @@ another_hunk (difftype, rev)
fillcnt = p_ptrn_lines;
}
else if (! repl_beginning)
- fatal ("%s `---' at line %ld; check line numbers at line %ld",
+ fatal ("%s `---' at line %s; check line numbers at line %s",
(p_end <= p_ptrn_lines
? "Premature"
: "Overdue"),
- p_input_line, p_hunk_beg);
+ format_linenum (numbuf0, p_input_line),
+ format_linenum (numbuf1, p_hunk_beg));
else if (! repl_could_be_missing)
- fatal ("duplicate `---' at line %ld; check line numbers at line %ld",
- p_input_line, p_hunk_beg + repl_beginning);
+ fatal ("duplicate `---' at line %s; check line numbers at line %s",
+ format_linenum (numbuf0, p_input_line),
+ format_linenum (numbuf1,
+ p_hunk_beg + repl_beginning));
else
{
repl_missing = TRUE;
@@ -928,11 +991,7 @@ another_hunk (difftype, rev)
p_Char[p_end] = '=';
for (s = buf; *s && ! ISDIGIT (*s); s++)
continue;
- if (!*s)
- malformed ();
- p_newfirst = (LINENUM) atol (s);
- while (ISDIGIT (*s))
- s++;
+ s = scan_linenum (s, &p_newfirst);
if (*s == ',')
{
do
@@ -941,7 +1000,8 @@ another_hunk (difftype, rev)
malformed ();
}
while (! ISDIGIT (*s));
- p_repl_lines = (LINENUM) atol (s) - p_newfirst + 1;
+ scan_linenum (s, &p_repl_lines);
+ p_repl_lines += 1 - p_newfirst;
}
else if (p_newfirst)
p_repl_lines = 1;
@@ -1066,7 +1126,8 @@ another_hunk (difftype, rev)
hunk_done:
if (p_end >=0 && !repl_beginning)
- fatal ("no `---' found in patch at line %ld", pch_hunk_beg ());
+ fatal ("no `---' found in patch at line %s",
+ format_linenum (numbuf0, pch_hunk_beg ()));
if (repl_missing) {
@@ -1132,8 +1193,10 @@ another_hunk (difftype, rev)
&& p_Char[fillsrc] != ' ')
fillsrc++;
if (p_end < fillsrc || fillsrc == repl_beginning)
+ {
fatal ("replacement text or line numbers mangled in hunk at line %ld",
p_hunk_beg);
+ }
p_line[filldst] = p_line[fillsrc];
p_Char[filldst] = p_Char[fillsrc];
p_len[filldst] = p_len[fillsrc];
@@ -1142,13 +1205,16 @@ another_hunk (difftype, rev)
while (fillsrc <= p_end && fillsrc != repl_beginning)
{
if (p_Char[fillsrc] == ' ')
- fatal ("replacement text or line numbers mangled in hunk at line %ld",
- p_hunk_beg);
+ fatal ("replacement text or line numbers mangled in hunk at line %s",
+ format_linenum (numbuf0, p_hunk_beg));
fillsrc++;
}
if (debug & 64)
- printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n",
- fillsrc,filldst,repl_beginning,p_end+1);
+ printf ("fillsrc %s, filldst %s, rb %s, e+1 %s\n",
+ format_linenum (numbuf0, fillsrc),
+ format_linenum (numbuf1, filldst),
+ format_linenum (numbuf2, repl_beginning),
+ format_linenum (numbuf3, p_end + 1));
assert(fillsrc==p_end+1 || fillsrc==repl_beginning);
assert(filldst==p_end+1 || filldst==repl_beginning);
}
@@ -1167,29 +1233,18 @@ another_hunk (difftype, rev)
next_intuit_at(line_beginning,p_input_line);
return chars_read == (size_t) -1 ? -1 : 0;
}
- s = buf+4;
- if (!*s)
- malformed ();
- p_first = (LINENUM) atol(s);
- while (ISDIGIT (*s))
- s++;
- if (*s == ',') {
- p_ptrn_lines = (LINENUM) atol(++s);
- while (ISDIGIT (*s))
- s++;
- } else
+ s = scan_linenum (buf + 4, &p_first);
+ if (*s == ',')
+ s = scan_linenum (s + 1, &p_ptrn_lines);
+ else
p_ptrn_lines = 1;
if (*s == ' ') s++;
- if (*s != '+' || !*++s)
+ if (*s != '+')
malformed ();
- p_newfirst = (LINENUM) atol(s);
- while (ISDIGIT (*s))
- s++;
- if (*s == ',') {
- p_repl_lines = (LINENUM) atol(++s);
- while (ISDIGIT (*s))
- s++;
- } else
+ s = scan_linenum (s + 1, &p_newfirst);
+ if (*s == ',')
+ s = scan_linenum (s + 1, &p_repl_lines);
+ else
p_repl_lines = 1;
if (*s == ' ') s++;
if (*s != '@')
@@ -1205,14 +1260,18 @@ another_hunk (difftype, rev)
fillsrc = 1;
filldst = fillsrc + p_ptrn_lines;
p_end = filldst + p_repl_lines;
- sprintf (buf,"*** %ld,%ld ****\n",p_first,p_first + p_ptrn_lines - 1);
+ sprintf (buf, "*** %s,%s ****\n",
+ format_linenum (numbuf0, p_first),
+ format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
p_len[0] = strlen (buf);
if (! (p_line[0] = savestr (buf))) {
p_end = -1;
return -1;
}
p_Char[0] = '*';
- sprintf (buf,"--- %ld,%ld ----\n",p_newfirst,p_newfirst+p_repl_lines-1);
+ sprintf (buf, "--- %s,%s ----\n",
+ format_linenum (numbuf0, p_newfirst),
+ format_linenum (numbuf1, p_newfirst + p_repl_lines - 1));
p_len[filldst] = strlen (buf);
if (! (p_line[filldst] = savestr (buf))) {
p_end = 0;
@@ -1322,24 +1381,19 @@ another_hunk (difftype, rev)
next_intuit_at(line_beginning,p_input_line);
return chars_read == (size_t) -1 ? -1 : 0;
}
- p_first = (LINENUM)atol(buf);
- for (s = buf; ISDIGIT (*s); s++)
- continue;
+ s = scan_linenum (buf, &p_first);
if (*s == ',') {
- p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
- while (ISDIGIT (*s))
- s++;
+ s = scan_linenum (s + 1, &p_ptrn_lines);
+ p_ptrn_lines += 1 - p_first;
}
else
p_ptrn_lines = (*s != 'a');
hunk_type = *s;
if (hunk_type == 'a')
p_first++; /* do append rather than insert */
- min = (LINENUM)atol(++s);
- while (ISDIGIT (*s))
- s++;
+ s = scan_linenum (s + 1, &min);
if (*s == ',')
- max = (LINENUM)atol(++s);
+ scan_linenum (s + 1, &max);
else
max = min;
if (hunk_type == 'd')
@@ -1353,7 +1407,9 @@ another_hunk (difftype, rev)
}
p_newfirst = min;
p_repl_lines = max - min + 1;
- sprintf (buf, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1);
+ sprintf (buf, "*** %s,%s\n",
+ format_linenum (numbuf0, p_first),
+ format_linenum (numbuf1, p_first + p_ptrn_lines - 1));
p_len[0] = strlen (buf);
if (! (p_line[0] = savestr (buf))) {
p_end = -1;
@@ -1368,10 +1424,11 @@ another_hunk (difftype, rev)
return -1;
}
if (!chars_read)
- fatal ("unexpected end of file in patch at line %ld",
- p_input_line);
+ fatal ("unexpected end of file in patch at line %s",
+ format_linenum (numbuf0, p_input_line));
if (buf[0] != '<' || (buf[1] != ' ' && buf[1] != '\t'))
- fatal ("`<' expected at line %ld of patch", p_input_line);
+ fatal ("`<' expected at line %s of patch",
+ format_linenum (numbuf0, p_input_line));
chars_read -= 2 + (i == p_ptrn_lines && incomplete_line ());
p_len[i] = chars_read;
if (! (p_line[i] = savebuf (buf + 2, chars_read))) {
@@ -1388,12 +1445,15 @@ another_hunk (difftype, rev)
return -1;
}
if (! chars_read)
- fatal ("unexpected end of file in patch at line %ld",
- p_input_line);
+ fatal ("unexpected end of file in patch at line %s",
+ format_linenum (numbuf0, p_input_line));
if (*buf != '-')
- fatal ("`---' expected at line %ld of patch", p_input_line);
+ fatal ("`---' expected at line %s of patch",
+ format_linenum (numbuf0, p_input_line));
}
- sprintf (buf, "--- %ld,%ld\n", min, max);
+ sprintf (buf, "--- %s,%s\n",
+ format_linenum (numbuf0, min),
+ format_linenum (numbuf1, max));
p_len[i] = strlen (buf);
if (! (p_line[i] = savestr (buf))) {
p_end = i-1;
@@ -1408,10 +1468,11 @@ another_hunk (difftype, rev)
return -1;
}
if (!chars_read)
- fatal ("unexpected end of file in patch at line %ld",
- p_input_line);
+ fatal ("unexpected end of file in patch at line %s",
+ format_linenum (numbuf0, p_input_line));
if (buf[0] != '>' || (buf[1] != ' ' && buf[1] != '\t'))
- fatal ("`>' expected at line %ld of patch", p_input_line);
+ fatal ("`>' expected at line %s of patch",
+ format_linenum (numbuf0, p_input_line));
chars_read -= 2 + (i == p_end && incomplete_line ());
p_len[i] = chars_read;
if (! (p_line[i] = savebuf (buf + 2, chars_read))) {
@@ -1433,7 +1494,8 @@ another_hunk (difftype, rev)
special = '^';
else
special = ' ';
- fprintf (stderr, "%3ld %c %c ", i, p_Char[i], special);
+ fprintf (stderr, "%s %c %c ", format_linenum (numbuf0, i),
+ p_Char[i], special);
pch_write_line (i, stderr);
fflush (stderr);
}
@@ -1446,21 +1508,23 @@ another_hunk (difftype, rev)
static size_t
get_line ()
{
- return pget_line (p_indent, p_rfc934_nesting);
+ return pget_line (p_indent, p_rfc934_nesting, p_strip_trailing_cr);
}
/* Input a line from the patch file, worrying about indentation.
Strip up to INDENT characters' worth of leading indentation.
Then remove up to RFC934_NESTING instances of leading "- ".
+ If STRIP_TRAILING_CR is nonzero, remove any trailing carriage-return.
Ignore any partial lines at end of input, but warn about them.
Succeed if a line was read; it is terminated by "\n\0" for convenience.
Return the number of characters read, including '\n' but not '\0'.
Return -1 if we ran out of memory. */
static size_t
-pget_line (indent, rfc934_nesting)
+pget_line (indent, rfc934_nesting, strip_trailing_cr)
int indent;
int rfc934_nesting;
+ int strip_trailing_cr;
{
register FILE *fp = pfp;
register int c;
@@ -1531,6 +1595,8 @@ pget_line (indent, rfc934_nesting)
goto patch_ends_in_middle_of_line;
}
+ if (strip_trailing_cr && 2 <= i && b[i - 2] == '\r')
+ b[i-- - 2] = '\n';
b[i] = '\0';
p_input_line++;
return i;
@@ -1803,14 +1869,16 @@ do_ed_script (ofp)
register size_t chars_read;
if (!skip_rest_of_patch) {
+ int exclusive = TMPOUTNAME_needs_removal ? 0 : O_EXCL;
assert (! inerrno);
- copy_file (inname, TMPOUTNAME, instat.st_mode);
+ TMPOUTNAME_needs_removal = 1;
+ copy_file (inname, TMPOUTNAME, exclusive, instat.st_mode);
sprintf (buf, "%s %s%s", ed_program, verbosity == VERBOSE ? "" : "- ",
TMPOUTNAME);
fflush (stdout);
pipefp = popen(buf, binary_transput ? "wb" : "w");
if (!pipefp)
- pfatal ("can't open pipe to `%s'", buf);
+ pfatal ("Can't open pipe to %s", quotearg (buf));
}
for (;;) {
beginning_of_this_line = file_tell (pfp);
diff --git a/quotearg.c b/quotearg.c
index e4926e4..7cdad92 100644
--- a/quotearg.c
+++ b/quotearg.c
@@ -1,5 +1,5 @@
-/* Shell command argument quoting.
- Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
+/* quotearg.c - quote arguments for output
+ Copyright (C) 1998 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
@@ -12,9 +12,8 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING.
- If not, write to the Free Software Foundation,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Written by Paul Eggert <eggert@twinsun.com> */
@@ -24,102 +23,333 @@
#include <sys/types.h>
#include <quotearg.h>
+#include <xalloc.h>
-/* Place into QUOTED a quoted version of ARG suitable for `system'.
- Return the length of the resulting string (which is not null-terminated).
- If QUOTED is null, return the length without any side effects. */
+#include <ctype.h>
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii (c)
+#endif
+#ifdef isgraph
+# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
+#else
+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+#endif
-size_t
-quote_system_arg (quoted, arg)
- char *quoted;
- char const *arg;
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+#ifndef UCHAR_MAX
+#define UCHAR_MAX ((unsigned char) -1)
+#endif
+
+#if HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#if HAVE_STRING_H
+# include <string.h>
+#endif
+
+#define INT_BITS (sizeof (int) * CHAR_BIT)
+
+struct quoting_options
+{
+ /* Basic quoting style. */
+ enum quoting_style style;
+
+ /* Quote the chararacters indicated by this bit vector even if the
+ quoting style would not normally require them to be quoted. */
+ int quote_these_too[((UCHAR_MAX + 1) / INT_BITS
+ + ((UCHAR_MAX + 1) % INT_BITS != 0))];
+};
+
+/* Names of quoting styles. */
+char const *const quoting_style_args[] =
{
- char const *a;
- size_t len = 0;
+ "literal", "shell", "shell-always", "c", "escape", 0
+};
- /* Scan ARG, copying it to QUOTED if QUOTED is not null,
- looking for shell metacharacters. */
+/* The default quoting options. */
+static struct quoting_options default_quoting_options;
- for (a = arg; ; a++)
+/* Allocate a new set of quoting options, with contents initially identical
+ to O if O is not null, or to the default if O is null.
+ It is the caller's responsibility to free the result. */
+struct quoting_options *
+clone_quoting_options (struct quoting_options *o)
+{
+ struct quoting_options *p
+ = (struct quoting_options *) xmalloc (sizeof (struct quoting_options));
+ *p = *(o ? o : &default_quoting_options);
+ return p;
+}
+
+/* Get the value of O's quoting style. If O is null, use the default. */
+enum quoting_style
+get_quoting_style (struct quoting_options *o)
+{
+ return (o ? o : &default_quoting_options)->style;
+}
+
+/* In O (or in the default if O is null),
+ set the value of the quoting style to S. */
+void
+set_quoting_style (struct quoting_options *o, enum quoting_style s)
+{
+ (o ? o : &default_quoting_options)->style = s;
+}
+
+/* In O (or in the default if O is null),
+ set the value of the quoting options for character C to I.
+ Return the old value. Currently, the only values defined for I are
+ 0 (the default) and 1 (which means to quote the character even if
+ it would not otherwise be quoted). */
+int
+set_char_quoting (struct quoting_options *o, char c, int i)
+{
+ unsigned char uc = c;
+ int *p = (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS;
+ int shift = uc % INT_BITS;
+ int r = (*p >> shift) & 1;
+ *p ^= ((i & 1) ^ r) << shift;
+ return r;
+}
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using O to control quoting.
+ If O is null, use the default.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
+size_t
+quotearg_buffer (char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ struct quoting_options const *o)
+{
+ unsigned char c;
+ size_t i;
+ size_t len;
+ int quote_mark;
+ struct quoting_options const *p = o ? o : &default_quoting_options;
+ enum quoting_style quoting_style = p->style;
+# define STORE(c) \
+ do \
+ { \
+ if (len < buffersize) \
+ buffer[len] = (c); \
+ len++; \
+ } \
+ while (0)
+
+ switch (quoting_style)
{
- char c = *a;
- switch (c)
+ case shell_quoting_style:
+ if (! (argsize == -1 ? arg[0] == '\0' : argsize == 0))
{
- case 0:
- /* ARG has no shell metacharacters. */
- return len;
-
- case '=':
- if (*arg == '-')
- break;
- /* Fall through. */
- case '\t': case '\n': case ' ':
- case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
- case '(': case ')': case '*': case ';':
- case '<': case '>': case '?': case '[': case '\\':
- case '^': case '`': case '|': case '~':
- {
- /* ARG has a shell metacharacter.
- Start over, quoting it this time. */
-
- len = 0;
- c = *arg++;
-
- /* If ARG is an option, quote just its argument.
- This is not necessary, but it looks nicer. */
- if (c == '-' && arg < a)
- {
- c = *arg++;
-
- if (quoted)
- {
- quoted[len] = '-';
- quoted[len + 1] = c;
- }
- len += 2;
-
- if (c == '-')
- while (arg < a)
+ switch (arg[0])
+ {
+ case '#': case '~':
+ break;
+
+ default:
+ len = 0;
+ for (i = 0; ; i++)
+ {
+ if (argsize == -1 ? arg[i] == '\0' : i == argsize)
+ goto done;
+
+ c = arg[i];
+
+ switch (c)
{
- c = *arg++;
- if (quoted)
- quoted[len] = c;
- len++;
- if (c == '=')
- break;
+ case '\t': case '\n': case ' ':
+ case '!': /* special in csh */
+ case '"': case '$': case '&': case '\'':
+ case '(': case ')': case '*': case ';':
+ case '<': case '>': case '?': case '[': case '\\':
+ case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */
+ case '`': case '|':
+ goto needs_quoting;
}
- c = *arg++;
- }
-
- if (quoted)
- quoted[len] = '\'';
- len++;
-
- for (; c; c = *arg++)
- {
- if (c == '\'')
- {
- if (quoted)
- {
- quoted[len] = '\'';
- quoted[len + 1] = '\\';
- quoted[len + 2] = '\'';
- }
- len += 3;
- }
- if (quoted)
- quoted[len] = c;
- len++;
- }
-
- if (quoted)
- quoted[len] = '\'';
- return len + 1;
- }
+
+ if (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))
+ goto needs_quoting;
+
+ STORE (c);
+ }
+
+ needs_quoting:;
+ break;
+ }
}
+ /* Fall through. */
+
+ case shell_always_quoting_style:
+ quote_mark = '\'';
+ break;
+
+ case c_quoting_style:
+ quote_mark = '"';
+ break;
- if (quoted)
- quoted[len] = c;
- len++;
+ default:
+ quote_mark = 0;
+ break;
}
+
+ len = 0;
+
+ if (quote_mark)
+ STORE (quote_mark);
+
+ for (i = 0; ! (argsize == -1 ? arg[i] == '\0' : i == argsize); i++)
+ {
+ c = arg[i];
+
+ switch (quoting_style)
+ {
+ case literal_quoting_style:
+ break;
+
+ case shell_quoting_style:
+ case shell_always_quoting_style:
+ if (c == '\'')
+ {
+ STORE ('\'');
+ STORE ('\\');
+ STORE ('\'');
+ }
+ break;
+
+ case c_quoting_style:
+ case escape_quoting_style:
+ switch (c)
+ {
+ case '?': /* Do not generate trigraphs. */
+ case '\\': goto store_escape;
+ /* Not all C compilers know what \a means. */
+ case 7 : c = 'a'; goto store_escape;
+ case '\b': c = 'b'; goto store_escape;
+ case '\f': c = 'f'; goto store_escape;
+ case '\n': c = 'n'; goto store_escape;
+ case '\r': c = 'r'; goto store_escape;
+ case '\t': c = 't'; goto store_escape;
+ case '\v': c = 'v'; goto store_escape;
+
+ case ' ':
+ if (quoting_style == escape_quoting_style)
+ goto store_escape;
+ break;
+
+ case '"':
+ if (quoting_style == c_quoting_style)
+ goto store_escape;
+ break;
+
+ default:
+ if (!ISGRAPH (c))
+ {
+ STORE ('\\');
+ STORE ('0' + (c >> 6));
+ STORE ('0' + ((c >> 3) & 3));
+ c = '0' + (c & 3);
+ goto store_c;
+ }
+ break;
+ }
+
+ if (! (p->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS))))
+ goto store_c;
+
+ store_escape:
+ STORE ('\\');
+ }
+
+ store_c:
+ STORE (c);
+ }
+
+ if (quote_mark)
+ STORE (quote_mark);
+
+ done:
+ if (len < buffersize)
+ buffer[len] = '\0';
+ return len;
+}
+
+/* Use storage slot N to return a quoted version of the string ARG.
+ OPTIONS specifies the quoting options.
+ The returned value points to static storage that can be
+ reused by the next call to this function with the same value of N.
+ N must be nonnegative. */
+static char *
+quotearg_n_options (int n, char const *arg, struct quoting_options *options)
+{
+ static unsigned nslots;
+ static struct slotvec
+ {
+ size_t size;
+ char *val;
+ } *slotvec;
+
+ if (nslots <= n)
+ {
+ int n1 = n + 1;
+ size_t s = n1 * sizeof (struct slotvec);
+ if (! (0 < n1 && n1 == s / sizeof (struct slotvec)))
+ abort ();
+ slotvec = (struct slotvec *) xrealloc (slotvec, s);
+ memset (slotvec + nslots, 0, (n1 - nslots) * sizeof (struct slotvec));
+ nslots = n;
+ }
+
+ {
+ size_t size = slotvec[n].size;
+ char *val = slotvec[n].val;
+ size_t qsize = quotearg_buffer (val, size, arg, (size_t) -1, options);
+
+ if (size <= qsize)
+ {
+ slotvec[n].size = size = qsize + 1;
+ slotvec[n].val = val = xrealloc (val, size);
+ quotearg_buffer (val, size, arg, (size_t) -1, options);
+ }
+
+ return val;
+ }
+}
+
+char *
+quotearg_n (int n, char const *arg)
+{
+ return quotearg_n_options (n, arg, &default_quoting_options);
+}
+
+char *
+quotearg (char const *arg)
+{
+ return quotearg_n (0, arg);
+}
+
+char *
+quotearg_char (char const *arg, char ch)
+{
+ struct quoting_options options;
+ options = default_quoting_options;
+ set_char_quoting (&options, ch, 1);
+ return quotearg_n_options (0, arg, &options);
+}
+
+char *
+quotearg_colon (char const *arg)
+{
+ return quotearg_char (arg, ':');
}
diff --git a/quotearg.h b/quotearg.h
index f32f919..0ace3df 100644
--- a/quotearg.h
+++ b/quotearg.h
@@ -1,9 +1,99 @@
-/* quote.h -- declarations for quoting system arguments */
+/* quotearg.h - quote arguments for output
+ Copyright (C) 1998 Free Software Foundation, Inc.
-#if defined __STDC__ || __GNUC__
-# define __QUOTEARG_P(args) args
-#else
-# define __QUOTEARG_P(args) ()
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+/* Basic quoting styles. */
+enum quoting_style
+ {
+ literal_quoting_style, /* --quoting-style=literal */
+ shell_quoting_style, /* --quoting-style=shell */
+ shell_always_quoting_style, /* --quoting-style=shell-always */
+ c_quoting_style, /* --quoting-style=c */
+ escape_quoting_style /* --quoting-style=escape */
+ };
+
+/* For now, --quoting-style=literal is the default, but
+ this is planned to change to --quoting-style=shell in the future. */
+#ifndef DEFAULT_QUOTING_STYLE
+#define DEFAULT_QUOTING_STYLE literal_quoting_style
+#endif
+
+/* Names of quoting styles. */
+extern char const *const quoting_style_args[];
+
+struct quoting_options;
+
+#ifndef PARAMS
+# if defined PROTOTYPES || defined __STDC__
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
#endif
-size_t quote_system_arg __QUOTEARG_P ((char *, char const *));
+/* The functions listed below set and use a hidden variable
+ that contains the default quoting style options. */
+
+/* Allocate a new set of quoting options, with contents initially identical
+ to O if O is not null, or to the default if O is null.
+ It is the caller's responsibility to free the result. */
+struct quoting_options *clone_quoting_options
+ PARAMS ((struct quoting_options *o));
+
+/* Get the value of O's quoting style. If O is null, use the default. */
+enum quoting_style get_quoting_style PARAMS ((struct quoting_options *o));
+
+/* In O (or in the default if O is null),
+ set the value of the quoting style to S. */
+void set_quoting_style PARAMS ((struct quoting_options *o,
+ enum quoting_style s));
+
+/* In O (or in the default if O is null),
+ set the value of the quoting options for character C to I.
+ Return the old value. Currently, the only values defined for I are
+ 0 (the default) and 1 (which means to quote the character even if
+ it would not otherwise be quoted). */
+int set_char_quoting PARAMS ((struct quoting_options *o, char c, int i));
+
+/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of
+ argument ARG (of size ARGSIZE), using O to control quoting.
+ If O is null, use the default.
+ Terminate the output with a null character, and return the written
+ size of the output, not counting the terminating null.
+ If BUFFERSIZE is too small to store the output string, return the
+ value that would have been returned had BUFFERSIZE been large enough.
+ If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */
+size_t quotearg_buffer PARAMS ((char *buffer, size_t buffersize,
+ char const *arg, size_t argsize,
+ struct quoting_options const *o));
+
+/* Use storage slot N to return a quoted version of the string ARG.
+ Use the default quoting options.
+ The returned value points to static storage that can be
+ reused by the next call to this function with the same value of N.
+ N must be nonnegative. */
+char *quotearg_n PARAMS ((int n, char const *arg));
+
+/* Equivalent to quotearg_n (ARG, 0). */
+char *quotearg PARAMS ((char const *arg));
+
+/* Like quotearg (ARG), except also quote any instances of CH. */
+char *quotearg_char PARAMS ((char const *arg, char ch));
+
+/* Equivalent to quotearg_char (ARG, ':'). */
+char *quotearg_colon PARAMS ((char const *arg));
diff --git a/quotesys.c b/quotesys.c
new file mode 100644
index 0000000..528f382
--- /dev/null
+++ b/quotesys.c
@@ -0,0 +1,125 @@
+/* Shell command argument quoting.
+ Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING.
+ If not, write to the Free Software Foundation,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by Paul Eggert <eggert@twinsun.com> */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <quotesys.h>
+
+/* Place into QUOTED a quoted version of ARG suitable for `system'.
+ Return the length of the resulting string (which is not null-terminated).
+ If QUOTED is null, return the length without any side effects. */
+
+size_t
+quote_system_arg (quoted, arg)
+ char *quoted;
+ char const *arg;
+{
+ char const *a;
+ size_t len = 0;
+
+ /* Scan ARG, copying it to QUOTED if QUOTED is not null,
+ looking for shell metacharacters. */
+
+ for (a = arg; ; a++)
+ {
+ char c = *a;
+ switch (c)
+ {
+ case 0:
+ /* ARG has no shell metacharacters. */
+ return len;
+
+ case '=':
+ if (*arg == '-')
+ break;
+ /* Fall through. */
+ case '\t': case '\n': case ' ':
+ case '!': case '"': case '#': case '$': case '%': case '&': case '\'':
+ case '(': case ')': case '*': case ';':
+ case '<': case '>': case '?': case '[': case '\\':
+ case '^': case '`': case '|': case '~':
+ {
+ /* ARG has a shell metacharacter.
+ Start over, quoting it this time. */
+
+ len = 0;
+ c = *arg++;
+
+ /* If ARG is an option, quote just its argument.
+ This is not necessary, but it looks nicer. */
+ if (c == '-' && arg < a)
+ {
+ c = *arg++;
+
+ if (quoted)
+ {
+ quoted[len] = '-';
+ quoted[len + 1] = c;
+ }
+ len += 2;
+
+ if (c == '-')
+ while (arg < a)
+ {
+ c = *arg++;
+ if (quoted)
+ quoted[len] = c;
+ len++;
+ if (c == '=')
+ break;
+ }
+ c = *arg++;
+ }
+
+ if (quoted)
+ quoted[len] = '\'';
+ len++;
+
+ for (; c; c = *arg++)
+ {
+ if (c == '\'')
+ {
+ if (quoted)
+ {
+ quoted[len] = '\'';
+ quoted[len + 1] = '\\';
+ quoted[len + 2] = '\'';
+ }
+ len += 3;
+ }
+ if (quoted)
+ quoted[len] = c;
+ len++;
+ }
+
+ if (quoted)
+ quoted[len] = '\'';
+ return len + 1;
+ }
+ }
+
+ if (quoted)
+ quoted[len] = c;
+ len++;
+ }
+}
diff --git a/quotesys.h b/quotesys.h
new file mode 100644
index 0000000..0d0d825
--- /dev/null
+++ b/quotesys.h
@@ -0,0 +1,9 @@
+/* quotesys.h -- declarations for quoting system arguments */
+
+#if defined __STDC__ || __GNUC__
+# define __QUOTESYS_P(args) args
+#else
+# define __QUOTESYS_P(args) ()
+#endif
+
+size_t quote_system_arg __QUOTESYS_P ((char *, char const *));
diff --git a/realloc.c b/realloc.c
new file mode 100644
index 0000000..d0d3e4a
--- /dev/null
+++ b/realloc.c
@@ -0,0 +1,44 @@
+/* Work around bug on some systems where realloc (NULL, 0) fails.
+ Copyright (C) 1997 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* written by Jim Meyering */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+#undef realloc
+
+#include <sys/types.h>
+
+char *malloc ();
+char *realloc ();
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking. If N is zero, change it to 1. If P is NULL,
+ use malloc. */
+
+char *
+rpl_realloc (p, n)
+ char *p;
+ size_t n;
+{
+ if (n == 0)
+ n = 1;
+ if (p == 0)
+ return malloc (n);
+ return realloc (p, n);
+}
diff --git a/util.c b/util.c
index 03a8e16..aa31392 100644
--- a/util.c
+++ b/util.c
@@ -1,10 +1,10 @@
/* utility functions for `patch' */
-/* $Id: util.c,v 1.24 1997/07/10 08:16:12 eggert Exp $ */
+/* $Id: util.c,v 1.25 1998/03/15 14:44:47 eggert Exp $ */
/*
Copyright 1986 Larry Wall
-Copyright 1992, 1993, 1997 Free Software Foundation, Inc.
+Copyright 1992, 1993, 1997, 1998 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
@@ -26,10 +26,12 @@ If not, write to the Free Software Foundation,
#include <common.h>
#include <backupfile.h>
#include <quotearg.h>
+#include <quotesys.h>
#include <version.h>
#undef XTERN
#define XTERN
#include <util.h>
+#include <xalloc.h>
#include <maketime.h>
#include <partime.h>
@@ -38,7 +40,7 @@ If not, write to the Free Software Foundation,
#if !defined SIGCHLD && defined SIGCLD
#define SIGCHLD SIGCLD
#endif
-#if ! HAVE_RAISE
+#if ! HAVE_RAISE && ! defined raise
# define raise(sig) kill (getpid (), sig)
#endif
@@ -60,19 +62,24 @@ If not, write to the Free Software Foundation,
static void makedirs PARAMS ((char *));
-/* Move a file FROM to TO, renaming it if possible and copying it if necessary.
+/* Move a file FROM (where *FROM_NEEDS_REMOVAL is nonzero if FROM
+ needs removal when cleaning up at the end of execution)
+ to TO, renaming it if possible and copying it if necessary.
If we must create TO, use MODE to create it.
If FROM is null, remove TO (ignoring FROMSTAT).
+ FROM_NEEDS_REMOVAL must be nonnull if FROM is nonnull.
Back up TO if BACKUP is nonzero. */
#ifdef __STDC__
/* If mode_t doesn't promote to itself, we can't use old-style definition. */
void
-move_file (char const *from, char *to, mode_t mode, int backup)
+move_file (char const *from, int volatile *from_needs_removal,
+ char *to, mode_t mode, int backup)
#else
void
-move_file (from, to, mode, backup)
+move_file (from, from_needs_removal, to, mode, backup)
char const *from;
+ int volatile *from_needs_removal;
char *to;
mode_t mode;
int backup;
@@ -117,28 +124,32 @@ move_file (from, to, mode, backup)
if (to_errno)
{
int fd;
+
if (debug & 4)
- say ("creating empty unreadable file `%s'\n", bakname);
+ say ("Creating empty unreadable file %s\n", quotearg (bakname));
+
try_makedirs_errno = ENOENT;
unlink (bakname);
while ((fd = creat (bakname, 0)) < 0)
{
if (errno != try_makedirs_errno)
- pfatal ("can't create file `%s'", bakname);
+ pfatal ("Can't create file %s", quotearg (bakname));
makedirs (bakname);
try_makedirs_errno = 0;
}
if (close (fd) != 0)
- pfatal ("can't close `%s'", bakname);
+ pfatal ("Can't close file %s", quotearg (bakname));
}
else
{
if (debug & 4)
- say ("renaming `%s' to `%s'\n", to, bakname);
+ say ("Renaming file %s to %s\n",
+ quotearg_n (0, to), quotearg_n (1, bakname));
while (rename (to, bakname) != 0)
{
if (errno != try_makedirs_errno)
- pfatal ("can't rename `%s' to `%s'", to, bakname);
+ pfatal ("Can't rename file %s to %s",
+ quotearg_n (0, to), quotearg_n (1, bakname));
makedirs (bakname);
try_makedirs_errno = 0;
}
@@ -150,9 +161,12 @@ move_file (from, to, mode, backup)
if (from)
{
if (debug & 4)
- say ("renaming `%s' to `%s'\n", from, to);
+ say ("Renaming file %s to %s\n",
+ quotearg_n (0, from), quotearg_n (1, to));
- if (rename (from, to) != 0)
+ if (rename (from, to) == 0)
+ *from_needs_removal = 0;
+ else
{
int to_dir_known_to_exist = 0;
@@ -162,7 +176,10 @@ move_file (from, to, mode, backup)
makedirs (to);
to_dir_known_to_exist = 1;
if (rename (from, to) == 0)
- return;
+ {
+ *from_needs_removal = 0;
+ return;
+ }
}
if (errno == EXDEV)
@@ -172,23 +189,24 @@ move_file (from, to, mode, backup)
if (unlink (to) == 0)
to_dir_known_to_exist = 1;
else if (errno != ENOENT)
- pfatal ("can't remove `%s'", to);
+ pfatal ("Can't remove file %s", quotearg (to));
}
if (! to_dir_known_to_exist)
makedirs (to);
- copy_file (from, to, mode);
+ copy_file (from, to, 0, mode);
return;
}
- pfatal ("can't rename `%s' to `%s'", from, to);
+ pfatal ("Can't rename file %s to %s",
+ quotearg_n (0, from), quotearg_n (1, to));
}
}
else if (! backup)
{
if (debug & 4)
- say ("removing `%s'\n", to);
+ say ("Removing file %s\n", quotearg (to));
if (unlink (to) != 0)
- pfatal ("can't remove `%s'", to);
+ pfatal ("Can't remove file %s", quotearg (to));
}
}
@@ -214,7 +232,7 @@ create_file (file, open_flags, mode)
close (creat (file, mode));
fd = open (file, O_CREAT | O_TRUNC | open_flags, mode);
if (fd < 0)
- pfatal ("can't create `%s'", file);
+ pfatal ("Can't create file %s", quotearg (file));
return fd;
}
@@ -223,12 +241,13 @@ create_file (file, open_flags, mode)
#ifdef __STDC__
/* If mode_t doesn't promote to itself, we can't use old-style definition. */
void
-copy_file (char const *from, char const *to, mode_t mode)
+copy_file (char const *from, char const *to, int to_flags, mode_t mode)
#else
void
-copy_file (from, to, mode)
+copy_file (from, to, to_flags, mode)
char const *from;
char const *to;
+ int to_flags;
mode_t mode;
#endif
{
@@ -237,11 +256,11 @@ copy_file (from, to, mode)
size_t i;
if ((fromfd = open (from, O_RDONLY | O_BINARY)) < 0)
- pfatal ("can't reopen `%s'", from);
- tofd = create_file (to, O_WRONLY | O_BINARY, mode);
+ pfatal ("Can't reopen file %s", quotearg (from));
+ tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode);
while ((i = read (fromfd, buf, bufsize)) != 0)
{
- if (i == -1)
+ if (i == (size_t) -1)
read_fatal ();
if (write (tofd, buf, i) != i)
write_fatal ();
@@ -254,23 +273,27 @@ copy_file (from, to, mode)
static char const DEV_NULL[] = NULL_DEVICE;
+static char const RCSSUFFIX[] = ",v";
+static char const CHECKOUT[] = "co %s";
+static char const CHECKOUT_LOCKED[] = "co -l %s";
+static char const RCSDIFF1[] = "rcsdiff %s";
+
static char const SCCSPREFIX[] = "s.";
static char const GET[] = "get ";
static char const GET_LOCKED[] = "get -e ";
static char const SCCSDIFF1[] = "get -p ";
static char const SCCSDIFF2[] = "|diff - %s";
-static char const RCSSUFFIX[] = ",v";
-static char const CHECKOUT[] = "co %s";
-static char const CHECKOUT_LOCKED[] = "co -l %s";
-static char const RCSDIFF1[] = "rcsdiff %s";
+static char const CLEARTOOL_CO[] = "cleartool co -unr -nc ";
/* Return "RCS" if FILENAME is controlled by RCS,
- "SCCS" if it is controlled by SCCS, and 0 otherwise.
+ "SCCS" if it is controlled by SCCS,
+ "ClearCase" if it is controlled by Clearcase, and 0 otherwise.
READONLY is nonzero if we desire only readonly access to FILENAME.
FILESTAT describes FILENAME's status or is 0 if FILENAME does not exist.
If successful and if GETBUF is nonzero, set *GETBUF to a command
- that gets the file; similarly for DIFFBUF and a command to diff the file.
+ that gets the file; similarly for DIFFBUF and a command to diff the file
+ (but set *DIFFBUF to 0 if the diff operation is meaningless).
*GETBUF and *DIFFBUF must be freed by the caller. */
char const *
version_controller (filename, readonly, filestat, getbuf, diffbuf)
@@ -288,7 +311,7 @@ version_controller (filename, readonly, filestat, getbuf, diffbuf)
size_t maxfixlen = sizeof "SCCS/" - 1 + sizeof SCCSPREFIX - 1;
size_t maxtrysize = filenamelen + maxfixlen + 1;
size_t quotelen = quote_system_arg (0, filename);
- size_t maxgetsize = sizeof GET_LOCKED + quotelen + maxfixlen;
+ size_t maxgetsize = sizeof CLEARTOOL_CO + quotelen + maxfixlen;
size_t maxdiffsize =
(sizeof SCCSDIFF1 + sizeof SCCSDIFF2 + sizeof DEV_NULL - 1
+ 2 * quotelen + maxfixlen);
@@ -358,6 +381,23 @@ version_controller (filename, readonly, filestat, getbuf, diffbuf)
r = "SCCS";
}
+ else if (!readonly && filestat
+ && try1 ("%s@@", filebase) && S_ISDIR (cstat.st_mode))
+ {
+ if (getbuf)
+ {
+ char *p = *getbuf = xmalloc (maxgetsize);
+ strcpy (p, CLEARTOOL_CO);
+ p += sizeof CLEARTOOL_CO - 1;
+ p += quote_system_arg (p, filename);
+ *p = '\0';
+ }
+
+ if (diffbuf)
+ *diffbuf = 0;
+
+ r = "ClearCase";
+ }
free (trybuf);
return r;
@@ -379,8 +419,8 @@ version_get (filename, cs, exists, readonly, getbuf, filestat)
{
if (patch_get < 0)
{
- ask ("Get file `%s' from %s%s? [y] ", filename,
- cs, readonly ? "" : " with lock");
+ ask ("Get file %s from %s%s? [y] ",
+ quotearg (filename), cs, readonly ? "" : " with lock");
if (*buf == 'n')
return 0;
}
@@ -388,20 +428,20 @@ version_get (filename, cs, exists, readonly, getbuf, filestat)
if (dry_run)
{
if (! exists)
- fatal ("can't do dry run on nonexistent version-controlled file `%s'; invoke `%s' and try again",
- filename, getbuf);
+ fatal ("can't do dry run on nonexistent version-controlled file %s; invoke `%s' and try again",
+ quotearg (filename), getbuf);
}
else
{
if (verbosity == VERBOSE)
- say ("Getting file `%s' from %s%s...\n", filename,
+ say ("Getting file %s from %s%s...\n", quotearg (filename),
cs, readonly ? "" : " with lock");
if (systemic (getbuf) != 0)
- fatal ("can't get file `%s' from %s", filename, cs);
+ fatal ("Can't get file %s from %s", quotearg (filename), cs);
if (stat (filename, filestat) != 0)
- pfatal ("%s", filename);
+ pfatal ("%s", quotearg (filename));
}
-
+
return 1;
}
@@ -445,6 +485,32 @@ remove_prefix (p, prefixlen)
continue;
}
+char *
+format_linenum (numbuf, n)
+ char numbuf[LINENUM_LENGTH_BOUND + 1];
+ LINENUM n;
+{
+ char *p = numbuf + LINENUM_LENGTH_BOUND;
+ *p = '\0';
+
+ if (n < 0)
+ {
+ do
+ *--p = '0' - (int) (n % 10);
+ while ((n /= 10) != 0);
+
+ *--p = '-';
+ }
+ else
+ {
+ do
+ *--p = '0' + (int) (n % 10);
+ while ((n /= 10) != 0);
+ }
+
+ return p;
+}
+
#if !HAVE_VPRINTF
#define vfprintf my_vfprintf
static int vfprintf PARAMS ((FILE *, char const *, va_list));
@@ -977,7 +1043,7 @@ removedirs (filename)
{
filename[i] = '\0';
if (rmdir (filename) == 0 && verbosity == VERBOSE)
- say ("Removed empty directory `%s'.\n", filename);
+ say ("Removed empty directory %s\n", quotearg (filename));
filename[i] = '/';
}
}
@@ -1009,33 +1075,40 @@ time_t *pstamp;
say ("fetchname %s %d\n", at, strip_leading);
name = at;
- /* Strip off up to `sleading' leading slashes and null terminate. */
+ /* Strip up to `strip_leading' leading slashes and null terminate.
+ If `strip_leading' is negative, strip all leading slashes. */
for (t = at; *t; t++)
{
if (ISSLASH (*t))
{
while (ISSLASH (t[1]))
t++;
- if (--sleading >= 0)
+ if (strip_leading < 0 || --sleading >= 0)
name = t+1;
}
else if (ISSPACE ((unsigned char) *t))
{
+ char const *u = t;
+
if (set_time | set_utc)
- stamp = str2time (t, initial_time, set_utc ? 0L : TM_LOCAL_ZONE);
+ stamp = str2time (&u, initial_time,
+ set_utc ? 0L : TM_LOCAL_ZONE);
else
{
/* The head says the file is nonexistent if the timestamp
is the epoch; but the listed time is local time, not UTC,
- and POSIX.1 allows local time to be 24 hours away from UTC.
- So match any time within 24 hours of the epoch.
- Use a default time zone 24 hours behind UTC so that any
- non-zoned time within 24 hours of the epoch is valid. */
- stamp = str2time (t, initial_time, -24L * 60 * 60);
- if (0 <= stamp && stamp <= 2 * 24L * 60 * 60)
+ and POSIX.1 allows local time offset anywhere in the range
+ -25:00 < offset < +26:00. Match any time in that
+ range by assuming local time is -25:00 and then matching
+ any ``local'' time T in the range 0 < T < 25+26 hours. */
+ stamp = str2time (&u, initial_time, -25L * 60 * 60);
+ if (0 < stamp && stamp < (25 + 26) * 60L * 60)
stamp = 0;
}
+ if (*u && ! ISSPACE ((unsigned char) *u))
+ stamp = (time_t) -1;
+
*t = '\0';
break;
}
@@ -1044,8 +1117,9 @@ time_t *pstamp;
if (!*name)
return 0;
- /* Allow files to be created by diffing against /dev/null. */
- if (strcmp (at, "/dev/null") == 0)
+ /* Ignore the name if it doesn't have enough slashes to strip off,
+ or if it is "/dev/null". */
+ if (0 < sleading || strcmp (at, "/dev/null") == 0)
{
if (pstamp)
*pstamp = 0;
@@ -1058,16 +1132,6 @@ time_t *pstamp;
return savestr (name);
}
-GENERIC_OBJECT *
-xmalloc (size)
- size_t size;
-{
- register GENERIC_OBJECT *p = malloc (size);
- if (!p)
- memory_fatal ();
- return p;
-}
-
void
Fseek (stream, offset, ptrname)
FILE *stream;
diff --git a/util.h b/util.h
index 0484224..93353a0 100644
--- a/util.h
+++ b/util.h
@@ -1,6 +1,10 @@
/* utility functions for `patch' */
-/* $Id: util.h,v 1.15 1997/07/16 12:26:36 eggert Exp $ */
+/* $Id: util.h,v 1.16 1998/03/15 14:44:47 eggert Exp $ */
+
+/* An upper bound on the print length of a signed decimal line number.
+ Add one for the sign. */
+#define LINENUM_LENGTH_BOUND (sizeof (LINENUM) * CHAR_BIT / 3 + 1)
int ok_to_reverse PARAMS ((char const *, ...)) __attribute__ ((format (printf, 1, 2)));
void ask PARAMS ((char const *, ...)) __attribute__ ((format (printf, 1, 2)));
@@ -18,13 +22,14 @@ char const *version_controller PARAMS ((char const *, int, struct stat const *,
int version_get PARAMS ((char const *, char const *, int, int, char const *, struct stat *));
int create_file PARAMS ((char const *, int, mode_t));
int systemic PARAMS ((char const *));
+char *format_linenum PARAMS ((char[LINENUM_LENGTH_BOUND + 1], LINENUM));
void Fseek PARAMS ((FILE *, file_offset, int));
-void copy_file PARAMS ((char const *, char const *, mode_t));
+void copy_file PARAMS ((char const *, char const *, int, mode_t));
void exit_with_signal PARAMS ((int)) __attribute__ ((noreturn));
void ignore_signals PARAMS ((void));
void init_time PARAMS ((void));
void memory_fatal PARAMS ((void)) __attribute__ ((noreturn));
-void move_file PARAMS ((char const *, char *, mode_t, int));
+void move_file PARAMS ((char const *, int volatile *, char *, mode_t, int));
void read_fatal PARAMS ((void)) __attribute__ ((noreturn));
void remove_prefix PARAMS ((char *, size_t));
void removedirs PARAMS ((char *));
diff --git a/version.c b/version.c
index ea08437..b32fdd1 100644
--- a/version.c
+++ b/version.c
@@ -1,6 +1,6 @@
/* Print the version number. */
-/* $Id: version.c,v 1.5 1997/05/21 18:29:20 eggert Exp $ */
+/* $Id: version.c,v 1.6 1998/03/15 14:44:47 eggert Exp $ */
#define XTERN extern
#include <common.h>
@@ -10,8 +10,8 @@
#include <version.h>
static char const copyright_string[] = "\
-Copyright 1988 Larry Wall\n\
-Copyright 1997 Free Software Foundation, Inc.";
+Copyright 1984-1988 Larry Wall\n\
+Copyright 1989-1998 Free Software Foundation, Inc.";
static char const free_software_msgid[] = "\
This program comes with NO WARRANTY, to the extent permitted by law.\n\
diff --git a/xalloc.h b/xalloc.h
new file mode 100644
index 0000000..3f8d779
--- /dev/null
+++ b/xalloc.h
@@ -0,0 +1,21 @@
+#ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+#endif
+
+/* Exit value when the requested amount of memory is not available.
+ The caller may set it to some other value. */
+extern int xalloc_exit_failure;
+
+/* FIXME: describe */
+extern char *const xalloc_msg_memory_exhausted;
+
+/* FIXME: describe */
+extern void (*xalloc_fail_func) ();
+
+void *xmalloc PARAMS ((size_t n));
+void *xcalloc PARAMS ((size_t n, size_t s));
+void *xrealloc PARAMS ((void *p, size_t n));
diff --git a/xmalloc.c b/xmalloc.c
new file mode 100644
index 0000000..204469f
--- /dev/null
+++ b/xmalloc.c
@@ -0,0 +1,133 @@
+/* xmalloc.c -- malloc with out of memory checking
+ Copyright (C) 1990, 91, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if STDC_HEADERS
+# include <stdlib.h>
+#else
+void *calloc ();
+void *malloc ();
+void *realloc ();
+void free ();
+#endif
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(Text) gettext (Text)
+#else
+# define textdomain(Domain)
+# define _(Text) Text
+#endif
+#define N_(Text) Text
+
+#include "error.h"
+#include "xalloc.h"
+
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+/* Prototypes for functions defined here. */
+#if defined (__STDC__) && __STDC__
+void *xmalloc (size_t n);
+void *xcalloc (size_t n, size_t s);
+void *xrealloc (void *p, size_t n);
+#endif
+
+#ifndef HAVE_DONE_WORKING_MALLOC_CHECK
+you must run the autoconf test for a properly working malloc -- see malloc.m4
+#endif
+
+#ifndef HAVE_DONE_WORKING_REALLOC_CHECK
+you must run the autoconf test for a properly working realloc -- see realloc.m4
+#endif
+
+/* Exit value when the requested amount of memory is not available.
+ The caller may set it to some other value. */
+int xalloc_exit_failure = EXIT_FAILURE;
+
+/* FIXME: describe */
+char *const xalloc_msg_memory_exhausted = N_("Memory exhausted");
+
+/* FIXME: describe */
+void (*xalloc_fail_func) () = 0;
+
+#if __STDC__ && (HAVE_VPRINTF || HAVE_DOPRNT)
+void error (int, int, const char *, ...);
+#else
+void error ();
+#endif
+
+static void
+xalloc_fail ()
+{
+ if (xalloc_fail_func)
+ (*xalloc_fail_func) ();
+ error (xalloc_exit_failure, 0, xalloc_msg_memory_exhausted);
+}
+
+/* Allocate N bytes of memory dynamically, with error checking. */
+
+void *
+xmalloc (n)
+ size_t n;
+{
+ void *p;
+
+ p = malloc (n);
+ if (p == 0)
+ xalloc_fail ();
+ return p;
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking.
+ If P is NULL, run xmalloc. */
+
+void *
+xrealloc (p, n)
+ void *p;
+ size_t n;
+{
+ p = realloc (p, n);
+ if (p == 0)
+ xalloc_fail ();
+ return p;
+}
+
+#ifdef NOT_USED
+
+/* Allocate memory for N elements of S bytes, with error checking. */
+
+void *
+xcalloc (n, s)
+ size_t n, s;
+{
+ void *p;
+
+ p = calloc (n, s);
+ if (p == 0)
+ xalloc_fail ();
+ return p;
+}
+
+#endif /* NOT_USED */