summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornate <nate@FreeBSD.org>1996-02-12 06:39:49 +0000
committernate <nate@FreeBSD.org>1996-02-12 06:39:49 +0000
commit4778ca641d25e08c667c809693e9d1d8a79098e3 (patch)
treefe122026c636513a566062a1bcde393469cac56b
parent3c2e7478e1136c470620ae4525a8aceaf8db8b8c (diff)
downloadFreeBSD-src-4778ca641d25e08c667c809693e9d1d8a79098e3.zip
FreeBSD-src-4778ca641d25e08c667c809693e9d1d8a79098e3.tar.gz
Sort from GNU textutils 1.14
-rw-r--r--gnu/usr.bin/sort/config.h123
-rw-r--r--gnu/usr.bin/sort/error.c110
-rw-r--r--gnu/usr.bin/sort/error.h44
-rw-r--r--gnu/usr.bin/sort/getopt.c271
-rw-r--r--gnu/usr.bin/sort/getopt.h12
-rw-r--r--gnu/usr.bin/sort/getopt1.c11
-rw-r--r--gnu/usr.bin/sort/long-options.c22
-rw-r--r--gnu/usr.bin/sort/long-options.h11
-rw-r--r--gnu/usr.bin/sort/sort.115
-rw-r--r--gnu/usr.bin/sort/sort.c966
-rw-r--r--gnu/usr.bin/sort/system.h117
-rw-r--r--gnu/usr.bin/sort/version.c12
-rw-r--r--gnu/usr.bin/sort/xstrtod.c48
-rw-r--r--gnu/usr.bin/sort/xstrtod.h15
14 files changed, 1192 insertions, 585 deletions
diff --git a/gnu/usr.bin/sort/config.h b/gnu/usr.bin/sort/config.h
new file mode 100644
index 0000000..27f201bb
--- /dev/null
+++ b/gnu/usr.bin/sort/config.h
@@ -0,0 +1,123 @@
+/* config.h. Generated automatically by configure. */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if on AIX 3.
+ System headers sometimes define this.
+ We just want to avoid a redefinition error message. */
+#ifndef _ALL_SOURCE
+/* #undef _ALL_SOURCE */
+#endif
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you don't have vprintf but do have _doprnt. */
+/* #undef HAVE_DOPRNT */
+
+/* Define if the `long double' type works. */
+#define HAVE_LONG_DOUBLE 1
+
+/* Define if your struct stat has st_blksize. */
+#define HAVE_ST_BLKSIZE 1
+
+/* Define if you have the vprintf function. */
+#define HAVE_VPRINTF 1
+
+/* Define as __inline if that's what the C compiler calls it. */
+/* #undef inline */
+
+/* Define if on MINIX. */
+/* #undef _MINIX */
+
+/* Define to `long' if <sys/types.h> doesn't define. */
+/* #undef off_t */
+
+/* Define if the system does not provide POSIX.1 features except
+ with this defined. */
+/* #undef _POSIX_1_SOURCE */
+
+/* Define if you need to in order for stat and other things to work. */
+/* #undef _POSIX_SOURCE */
+
+/* Define as the return type of signal handlers (int or void). */
+#define RETSIGTYPE void
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly. */
+/* #undef STAT_MACROS_BROKEN */
+
+/* Define if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if your processor stores words with the most significant
+ byte first (like Motorola and SPARC, unlike Intel and VAX). */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to 1 if ANSI function prototypes are usable. */
+#define PROTOTYPES 1
+
+/* Define to 1 if GNU regex should be used instead of GNU rx. */
+/* #undef WITH_REGEX */
+
+/* Define if you have the isascii function. */
+#define HAVE_ISASCII 1
+
+/* Define if you have the strchr function. */
+#define HAVE_STRCHR 1
+
+/* Define if you have the strerror function. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the strrchr function. */
+#define HAVE_STRRCHR 1
+
+/* Define if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the <ndir.h> header file. */
+/* #undef HAVE_NDIR_H */
+
+/* Define if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the <sys/dir.h> header file. */
+/* #undef HAVE_SYS_DIR_H */
+
+/* Define if you have the <sys/ndir.h> header file. */
+/* #undef HAVE_SYS_NDIR_H */
+
+/* Define if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
diff --git a/gnu/usr.bin/sort/error.c b/gnu/usr.bin/sort/error.c
index e849c5b..a36198b 100644
--- a/gnu/usr.bin/sort/error.c
+++ b/gnu/usr.bin/sort/error.c
@@ -1,5 +1,5 @@
/* error.c -- error handler for noninteractive utilities
- Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91, 92, 93, 94, 95 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
@@ -15,42 +15,55 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* Written by David MacKenzie. */
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
-#include <stdio.h>
-
-#ifdef HAVE_VPRINTF
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
-#if __STDC__
-#include <stdarg.h>
-#define VA_START(args, lastarg) va_start(args, lastarg)
-#else /* !__STDC__ */
-#include <varargs.h>
-#define VA_START(args, lastarg) va_start(args)
-#endif /* !__STDC__ */
+#include <stdio.h>
-#else /* !HAVE_VPRINTF */
+#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
-#ifdef HAVE_DOPRNT
-#define va_alist args
-#define va_dcl int args;
-#else /* !HAVE_DOPRNT */
-#define va_alist a1, a2, a3, a4, a5, a6, a7, a8
-#define va_dcl char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
-#endif /* !HAVE_DOPRNT */
+/* This variable is incremented each time `error' is called. */
+unsigned int error_message_count;
-#endif /* !HAVE_VPRINTF */
+/* 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) () = NULL;
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else /* !STDC_HEADERS */
-void exit ();
-#endif /* !STDC_HEADERS */
+#ifdef _LIBC
+#define program_name program_invocation_name
+#endif
+/* The calling program should define program_name and set it to the
+ name of the executing program. */
extern char *program_name;
-#ifndef HAVE_STRERROR
+#if HAVE_STRERROR || _LIBC
+# ifndef strerror /* On some systems, strerror is a macro */
+char *strerror ();
+# endif
+#else
static char *
private_strerror (errnum)
int errnum;
@@ -63,40 +76,51 @@ private_strerror (errnum)
return "Unknown system error";
}
#define strerror private_strerror
-#endif /* !HAVE_STRERROR */
+#endif
/* 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 (HAVE_VPRINTF) && __STDC__
-error (int status, int errnum, char *message, ...)
-#else /* !HAVE_VPRINTF or !__STDC__ */
+#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 /* !HAVE_VPRINTF or !__STDC__ */
+#endif
{
-#ifdef HAVE_VPRINTF
+#ifdef VA_START
va_list args;
-#endif /* HAVE_VPRINTF */
+#endif
+
+ if (error_print_progname)
+ (*error_print_progname) ();
+ else
+ {
+ fflush (stdout);
+ fprintf (stderr, "%s: ", program_name);
+ }
- fprintf (stderr, "%s: ", program_name);
-#ifdef HAVE_VPRINTF
+#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 /* !HAVE_VPRINTF */
-#ifdef HAVE_DOPRNT
- _doprnt (message, &args, stderr);
-#else /* !HAVE_DOPRNT */
+#else
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
-#endif /* !HAVE_DOPRNT */
-#endif /* !HAVE_VPRINTF */
+#endif
+
+ ++error_message_count;
+
if (errnum)
fprintf (stderr, ": %s", strerror (errnum));
putc ('\n', stderr);
diff --git a/gnu/usr.bin/sort/error.h b/gnu/usr.bin/sort/error.h
new file mode 100644
index 0000000..481c54d
--- /dev/null
+++ b/gnu/usr.bin/sort/error.h
@@ -0,0 +1,44 @@
+/* error.h -- declaration for error-reporting function
+ Copyright (C) 1995 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. */
+
+#ifndef _error_h_
+#define _error_h_
+
+#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
+
+#if __STDC__
+void error (int, int, const char *, ...) \
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+#else
+void error ();
+#endif
+
+/* This variable is incremented each time `error' is called. */
+extern unsigned int error_message_count;
+
+#endif /* _error_h_ */
diff --git a/gnu/usr.bin/sort/getopt.c b/gnu/usr.bin/sort/getopt.c
index 7a4673b..8bcf559 100644
--- a/gnu/usr.bin/sort/getopt.c
+++ b/gnu/usr.bin/sort/getopt.c
@@ -3,7 +3,7 @@
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
- Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -20,18 +20,17 @@
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+#define _NO_PROTO
+#endif
+
#ifdef HAVE_CONFIG_H
-#if defined (emacs) || defined (CONFIG_BROKETS)
-/* We use <config.h> instead of "config.h" so that a compilation
- using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
- (which it would do because it found this file in $srcdir). */
#include <config.h>
-#else
-#include "config.h"
-#endif
#endif
-#ifndef __STDC__
+#if !defined (__STDC__) || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
@@ -39,11 +38,6 @@
#endif
#endif
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */
-#ifndef _NO_PROTO
-#define _NO_PROTO
-#endif
-
#include <stdio.h>
/* Comment out all this code if we are using the GNU C Library, and are not
@@ -65,10 +59,16 @@
#include <stdlib.h>
#endif /* GNU C library. */
-/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
- long-named option. Because this is not POSIX.2 compliant, it is
- being phased out. */
-/* #define GETOPT_COMPAT */
+#ifndef _
+/* This is for other GNU distributions with internationalized messages.
+ When compiling libc, the _ macro is predefined. */
+#ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(msgid) gettext (msgid)
+#else
+# define _(msgid) (msgid)
+#endif
+#endif
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
@@ -92,7 +92,7 @@
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
-char *optarg = 0;
+char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
@@ -162,6 +162,9 @@ static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
@@ -192,19 +195,18 @@ my_index (str, chr)
}
/* If using GCC, we can safely declare strlen this way.
- If not using GCC, it is ok not to declare it.
- (Supposedly there are some machines where it might get a warning,
- but changing this conditional to __STDC__ is too risky.) */
+ If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
-#ifdef IN_GCC
-#include "gstddef.h"
-#else
-#include <stddef.h>
-#endif
-extern size_t strlen (const char *);
-#endif
-
-#endif /* GNU C library. */
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+#if !defined (__STDC__) || !__STDC__
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+#endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
/* Handle permutation of arguments. */
@@ -279,6 +281,42 @@ exchange (argv)
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
+
+/* Initialize the internal data when the first call is made. */
+
+static const char *
+_getopt_initialize (optstring)
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind = 1;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+ return optstring;
+}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
@@ -345,41 +383,18 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int *longind;
int long_only;
{
- int option_index;
-
- optarg = 0;
-
- /* Initialize the internal data when the first call is made.
- Start processing options with ARGV-element 1 (since ARGV-element 0
- is the program name); the sequence of previously skipped
- non-option ARGV-elements is empty. */
+ optarg = NULL;
if (optind == 0)
{
- first_nonopt = last_nonopt = optind = 1;
-
- nextchar = NULL;
-
- /* Determine how to handle the ordering of options and nonoptions. */
-
- if (optstring[0] == '-')
- {
- ordering = RETURN_IN_ORDER;
- ++optstring;
- }
- else if (optstring[0] == '+')
- {
- ordering = REQUIRE_ORDER;
- ++optstring;
- }
- else if (getenv ("POSIXLY_CORRECT") != NULL)
- ordering = REQUIRE_ORDER;
- else
- ordering = PERMUTE;
+ optstring = _getopt_initialize (optstring);
+ optind = 1; /* Don't scan ARGV[0], the program name. */
}
if (nextchar == NULL || *nextchar == '\0')
{
+ /* Advance to the next ARGV-element. */
+
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
@@ -390,21 +405,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else if (last_nonopt != optind)
first_nonopt = optind;
- /* Now skip any additional non-options
+ /* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
- && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
+ && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
- /* Special ARGV-element `--' means premature end of options.
+ /* The special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
@@ -437,12 +447,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
- if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
- && (longopts == NULL
- || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif /* GETOPT_COMPAT */
- )
+ if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
@@ -451,36 +456,53 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
/* We have found another option-ARGV-element.
- Start decoding its characters. */
+ Skip the initial punctuation. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
if (longopts != NULL
- && ((argv[optind][0] == '-'
- && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
- ))
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2]
+ || !my_index (optstring, argv[optind][1])))))
{
+ char *nameend;
const struct option *p;
- char *s = nextchar;
+ const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
- const struct option *pfound = NULL;
int indfound;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
- while (*s && *s != '=')
- s++;
+#ifdef lint
+ indfound = 0; /* Avoid spurious compiler warning. */
+#endif
- /* Test all options for either exact match or abbreviated matches. */
- for (p = longopts, option_index = 0; p->name;
- p++, option_index++)
- if (!strncmp (p->name, nextchar, s - nextchar))
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
{
- if (s - nextchar == strlen (p->name))
+ if (nameend - nextchar == strlen (p->name))
{
/* Exact match found. */
pfound = p;
@@ -495,14 +517,14 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
indfound = option_index;
}
else
- /* Second nonexact match found. */
+ /* Second or later nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
- fprintf (stderr, "%s: option `%s' is ambiguous\n",
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
@@ -513,27 +535,26 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
option_index = indfound;
optind++;
- if (*s)
+ if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
- optarg = s + 1;
+ optarg = nameend + 1;
else
{
if (opterr)
- {
- if (argv[optind - 1][1] == '-')
- /* --option */
- fprintf (stderr,
- "%s: option `--%s' doesn't allow an argument\n",
- argv[0], pfound->name);
- else
- /* +option or -option */
- fprintf (stderr,
- "%s: option `%c%s' doesn't allow an argument\n",
- argv[0], argv[optind - 1][0], pfound->name);
- }
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+
nextchar += strlen (nextchar);
return '?';
}
@@ -545,8 +566,9 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
else
{
if (opterr)
- fprintf (stderr, "%s: option `%s' requires an argument\n",
- argv[0], argv[optind - 1]);
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
@@ -561,25 +583,23 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
return pfound->val;
}
+
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
-#ifdef GETOPT_COMPAT
- || argv[optind][0] == '+'
-#endif /* GETOPT_COMPAT */
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
- fprintf (stderr, "%s: unrecognized option `--%s'\n",
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
argv[0], nextchar);
else
/* +option or -option */
- fprintf (stderr, "%s: unrecognized option `%c%s'\n",
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
@@ -588,7 +608,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
}
- /* Look at and handle the next option-character. */
+ /* Look at and handle the next short option-character. */
{
char c = *nextchar++;
@@ -602,16 +622,13 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (opterr)
{
-#if 0
- if (c < 040 || c >= 0177)
- fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
argv[0], c);
else
- fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
-#else
- /* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
-#endif
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
}
optopt = c;
return '?';
@@ -627,7 +644,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
optind++;
}
else
- optarg = 0;
+ optarg = NULL;
nextchar = NULL;
}
else
@@ -644,14 +661,10 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
if (opterr)
{
-#if 0
- fprintf (stderr, "%s: option `-%c' requires an argument\n",
- argv[0], c);
-#else
/* 1003.2 specifies the format of this message. */
- fprintf (stderr, "%s: option requires an argument -- %c\n",
- argv[0], c);
-#endif
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
diff --git a/gnu/usr.bin/sort/getopt.h b/gnu/usr.bin/sort/getopt.h
index 45541f5..4ac33b7 100644
--- a/gnu/usr.bin/sort/getopt.h
+++ b/gnu/usr.bin/sort/getopt.h
@@ -1,5 +1,5 @@
/* Declarations for getopt.
- Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1989, 90, 91, 92, 93, 94 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
@@ -76,7 +76,7 @@ extern int optopt;
struct option
{
-#if __STDC__
+#if defined (__STDC__) && __STDC__
const char *name;
#else
char *name;
@@ -94,15 +94,15 @@ struct option
#define required_argument 1
#define optional_argument 2
-#if __STDC__
-#if defined(__GNU_LIBRARY__)
+#if defined (__STDC__) && __STDC__
+#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int argc, char *const *argv, const char *shortopts);
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
-#endif /* not __GNU_LIBRARY__ */
+#endif /* __GNU_LIBRARY__ */
extern int getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *longopts, int *longind);
extern int getopt_long_only (int argc, char *const *argv,
@@ -120,7 +120,7 @@ extern int getopt_long ();
extern int getopt_long_only ();
extern int _getopt_internal ();
-#endif /* not __STDC__ */
+#endif /* __STDC__ */
#ifdef __cplusplus
}
diff --git a/gnu/usr.bin/sort/getopt1.c b/gnu/usr.bin/sort/getopt1.c
index f784b57..4580211 100644
--- a/gnu/usr.bin/sort/getopt1.c
+++ b/gnu/usr.bin/sort/getopt1.c
@@ -1,5 +1,5 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -17,19 +17,12 @@
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef HAVE_CONFIG_H
-#if defined (emacs) || defined (CONFIG_BROKETS)
-/* We use <config.h> instead of "config.h" so that a compilation
- using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
- (which it would do because it found this file in $srcdir). */
#include <config.h>
-#else
-#include "config.h"
-#endif
#endif
#include "getopt.h"
-#ifndef __STDC__
+#if !defined (__STDC__) || !__STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
diff --git a/gnu/usr.bin/sort/long-options.c b/gnu/usr.bin/sort/long-options.c
index 03305aa..dd7a8ca 100644
--- a/gnu/usr.bin/sort/long-options.c
+++ b/gnu/usr.bin/sort/long-options.c
@@ -1,5 +1,5 @@
/* Utility to accept --help and --version options as unobtrusively as possible.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -18,21 +18,11 @@
/* Jim Meyering (meyering@comco.com) */
#ifdef HAVE_CONFIG_H
-#if defined (CONFIG_BROKETS)
-/* We use <config.h> instead of "config.h" so that a compilation
- using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
- (which it would do because it found this file in $srcdir). */
#include <config.h>
-#else
-#include "config.h"
-#endif
#endif
#include <stdio.h>
#include <getopt.h>
-#include <sys/types.h>
-#include "system.h"
-#include "version.h"
#include "long-options.h"
static struct option const long_options[] =
@@ -46,9 +36,11 @@ static struct option const long_options[] =
Be careful not to gobble up `--'. */
void
-parse_long_options (argc, argv, usage)
+parse_long_options (argc, argv, command_name, version_string, usage)
int argc;
char **argv;
+ const char *command_name;
+ const char *version_string;
void (*usage)();
{
int c;
@@ -67,12 +59,12 @@ parse_long_options (argc, argv, usage)
switch (c)
{
case 'h':
- usage (0);
+ (*usage) (0);
case 'v':
- printf ("%s\n", version_string);
+ printf ("%s - %s\n", command_name, version_string);
exit (0);
-
+
default:
/* Don't process any other long-named options. */
break;
diff --git a/gnu/usr.bin/sort/long-options.h b/gnu/usr.bin/sort/long-options.h
index 9d1a9c7..986a52d 100644
--- a/gnu/usr.bin/sort/long-options.h
+++ b/gnu/usr.bin/sort/long-options.h
@@ -1 +1,10 @@
-void parse_long_options ();
+#undef __P
+#if defined (__STDC__) && __STDC__
+#define __P(args) args
+#else
+#define __P(args) ()
+#endif
+
+void
+ parse_long_options __P ((int _argc, char **_argv, const char *_command_name,
+ const char *_version_string, void (*_usage) (int)));
diff --git a/gnu/usr.bin/sort/sort.1 b/gnu/usr.bin/sort/sort.1
index 3acc398..e9f4b1e 100644
--- a/gnu/usr.bin/sort/sort.1
+++ b/gnu/usr.bin/sort/sort.1
@@ -1,10 +1,13 @@
-.TH SORT 1L \" -*- nroff -*-
+.TH SORT 1 "GNU Text Utilities" "FSF" \" -*- nroff -*-
.SH NAME
sort \- sort lines of text files
.SH SYNOPSIS
.B sort
[\-cmus] [\-t separator] [\-o output-file] [\-T tempdir] [\-bdfiMnr]
[+POS1 [\-POS2]] [\-k POS1[,POS2]] [file...]
+.br
+.B sort
+{\-\-help,\-\-version}
.SH DESCRIPTION
This manual page
documents the GNU version of
@@ -187,6 +190,16 @@ option, the
.I \-b
option is taken to apply to both the \fI+pos\fP and the \fI\-pos\fP
parts of a key specification. Keys may span multiple fields.
+.PP
+In addition, when GNU
+.B sort
+is invoked with exactly one argument, the following options are recognized:
+.TP
+.I "\-\-help"
+Print a usage message on standard output and exit successfully.
+.TP
+.I "\-\-version"
+Print version information on standard output then exit successfully.
.SH COMPATIBILITY
.PP
Historical (BSD and System V) implementations of
diff --git a/gnu/usr.bin/sort/sort.c b/gnu/usr.bin/sort/sort.c
index 42e0b8e..dc3addb 100644
--- a/gnu/usr.bin/sort/sort.c
+++ b/gnu/usr.bin/sort/sort.c
@@ -1,5 +1,5 @@
/* sort - sort lines of text (with all kinds of options).
- Copyright (C) 1988, 1991 Free Software Foundation
+ Copyright (C) 1988, 1991, 1992, 1993, 1994, 1995 Free Software Foundation
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
@@ -13,12 +13,14 @@
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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Written December 1988 by Mike Haertel.
The author may be reached (Email) at the address mike@gnu.ai.mit.edu,
or (US mail) as Mike Haertel c/o Free Software Foundation. */
+#include <config.h>
+
/* Get isblank from GNU libc. */
#define _GNU_SOURCE
@@ -26,7 +28,12 @@
#include <signal.h>
#include <stdio.h>
#include "system.h"
-#ifdef _POSIX_VERSION
+#include "version.h"
+#include "long-options.h"
+#include "error.h"
+#include "xstrtod.h"
+
+#ifdef HAVE_LIMITS_H
#include <limits.h>
#else
#ifndef UCHAR_MAX
@@ -39,16 +46,73 @@ char *realloc ();
void free ();
#endif
-void error ();
-static void usage ();
-
+/* Undefine, to avoid warning about redefinition on some systems. */
+#undef min
#define min(a, b) ((a) < (b) ? (a) : (b))
+
#define UCHAR_LIM (UCHAR_MAX + 1)
#define UCHAR(c) ((unsigned char) (c))
+#ifndef DEFAULT_TMPDIR
+#define DEFAULT_TMPDIR "/tmp"
+#endif
+
/* The kind of blanks for '-b' to skip in various options. */
enum blanktype { bl_start, bl_end, bl_both };
+/* Lines are held in core as counted strings. */
+struct line
+{
+ char *text; /* Text of the line. */
+ int length; /* Length not including final newline. */
+ char *keybeg; /* Start of first key. */
+ char *keylim; /* Limit of first key. */
+};
+
+/* Arrays of lines. */
+struct lines
+{
+ struct line *lines; /* Dynamically allocated array of lines. */
+ int used; /* Number of slots used. */
+ int alloc; /* Number of slots allocated. */
+ int limit; /* Max number of slots to allocate. */
+};
+
+/* Input buffers. */
+struct buffer
+{
+ char *buf; /* Dynamically allocated buffer. */
+ int used; /* Number of bytes used. */
+ int alloc; /* Number of bytes allocated. */
+ int left; /* Number of bytes left after line parsing. */
+};
+
+struct keyfield
+{
+ int sword; /* Zero-origin 'word' to start at. */
+ int schar; /* Additional characters to skip. */
+ int skipsblanks; /* Skip leading white space at start. */
+ int eword; /* Zero-origin first word after field. */
+ int echar; /* Additional characters in field. */
+ int skipeblanks; /* Skip trailing white space at finish. */
+ int *ignore; /* Boolean array of characters to ignore. */
+ char *translate; /* Translation applied to characters. */
+ int numeric; /* Flag for numeric comparison. Handle
+ strings of digits with optional decimal
+ point, but no exponential notation. */
+ int general_numeric; /* Flag for general, numeric comparison.
+ Handle numbers in exponential notation. */
+ int month; /* Flag for comparison by month name. */
+ int reverse; /* Reverse the sense of comparison. */
+ struct keyfield *next; /* Next keyfield to try. */
+};
+
+struct month
+{
+ char *name;
+ int val;
+};
+
/* The name this program was run with. */
char *program_name;
@@ -69,11 +133,7 @@ static char fold_toupper[UCHAR_LIM];
/* Table mapping 3-letter month names to integers.
Alphabetic order allows binary search. */
-static struct month
-{
- char *name;
- int val;
-} const monthtab[] =
+static struct month const monthtab[] =
{
{"APR", 4},
{"AUG", 8},
@@ -94,17 +154,17 @@ static struct month
/* Initial buffer size for in core sorting. Will not grow unless a
line longer than this is seen. */
-static int sortalloc = 524288;
+static int sortalloc = 512 * 1024;
/* Initial buffer size for in core merge buffers. Bear in mind that
up to NMERGE * mergealloc bytes may be allocated for merge buffers. */
-static int mergealloc = 16384;
+static int mergealloc = 16 * 1024;
/* Guess of average line length. */
static int linelength = 30;
/* Maximum number of elements for the array(s) of struct line's, in bytes. */
-#define LINEALLOC 262144
+#define LINEALLOC (256 * 1024)
/* Prefix for temporary file names. */
static char *temp_file_prefix;
@@ -129,49 +189,55 @@ static int unique;
/* Nonzero if any of the input files are the standard input. */
static int have_read_stdin;
-/* Lines are held in core as counted strings. */
-struct line
-{
- char *text; /* Text of the line. */
- int length; /* Length not including final newline. */
- char *keybeg; /* Start of first key. */
- char *keylim; /* Limit of first key. */
-};
-
-/* Arrays of lines. */
-struct lines
-{
- struct line *lines; /* Dynamically allocated array of lines. */
- int used; /* Number of slots used. */
- int alloc; /* Number of slots allocated. */
- int limit; /* Max number of slots to allocate. */
-};
-
-/* Input buffers. */
-struct buffer
-{
- char *buf; /* Dynamically allocated buffer. */
- int used; /* Number of bytes used. */
- int alloc; /* Number of bytes allocated. */
- int left; /* Number of bytes left after line parsing. */
-};
-
/* Lists of key field comparisons to be tried. */
-static struct keyfield
+static struct keyfield keyhead;
+
+static void
+usage (int status)
{
- int sword; /* Zero-origin 'word' to start at. */
- int schar; /* Additional characters to skip. */
- int skipsblanks; /* Skip leading white space at start. */
- int eword; /* Zero-origin first word after field. */
- int echar; /* Additional characters in field. */
- int skipeblanks; /* Skip trailing white space at finish. */
- int *ignore; /* Boolean array of characters to ignore. */
- char *translate; /* Translation applied to characters. */
- int numeric; /* Flag for numeric comparison. */
- int month; /* Flag for comparison by month name. */
- int reverse; /* Reverse the sense of comparison. */
- struct keyfield *next; /* Next keyfield to try. */
-} keyhead;
+ if (status != 0)
+ fprintf (stderr, _("Try `%s --help' for more information.\n"),
+ program_name);
+ else
+ {
+ printf (_("\
+Usage: %s [OPTION]... [FILE]...\n\
+"),
+ program_name);
+ printf (_("\
+Write sorted concatenation of all FILE(s) to standard output.\n\
+\n\
+ +POS1 [-POS2] start a key at POS1, end it before POS2\n\
+ -M compare (unknown) < `JAN' < ... < `DEC', imply -b\n\
+ -T DIRECT use DIRECT for temporary files, not $TMPDIR or %s\n\
+ -b ignore leading blanks in sort fields or keys\n\
+ -c check if given files already sorted, do not sort\n\
+ -d consider only [a-zA-Z0-9 ] characters in keys\n\
+ -f fold lower case to upper case characters in keys\n\
+ -g compare according to general numerical value, imply -b\n\
+ -i consider only [\\040-\\0176] characters in keys\n\
+ -k POS1[,POS2] same as +POS1 [-POS2], but all positions counted from 1\n\
+ -m merge already sorted files, do not sort\n\
+ -n compare according to string numerical value, imply -b\n\
+ -o FILE write result on FILE instead of standard output\n\
+ -r reverse the result of comparisons\n\
+ -s stabilize sort by disabling last resort comparison\n\
+ -t SEP use SEParator instead of non- to whitespace transition\n\
+ -u with -c, check for strict ordering\n\
+ -u with -m, only output the first of an equal sequence\n\
+ --help display this help and exit\n\
+ --version output version information and exit\n\
+\n\
+POS is F[.C][OPTS], where F is the field number and C the character\n\
+position in the field, both counted from zero. OPTS is made up of one\n\
+or more of Mbdfinr, this effectively disable global -Mbdfinr settings\n\
+for that key. If no key given, use the entire line as key. With no\n\
+FILE, or when FILE is -, read standard input.\n\
+")
+ , DEFAULT_TMPDIR);
+ }
+ exit (status);
+}
/* The list of temporary files. */
static struct tempnode
@@ -183,7 +249,7 @@ static struct tempnode
/* Clean up any remaining temporary files. */
static void
-cleanup ()
+cleanup (void)
{
struct tempnode *node;
@@ -193,16 +259,15 @@ cleanup ()
/* Allocate N bytes of memory dynamically, with error checking. */
-char *
-xmalloc (n)
- unsigned n;
+static char *
+xmalloc (unsigned int n)
{
char *p;
p = malloc (n);
if (p == 0)
{
- error (0, 0, "virtual memory exhausted");
+ error (0, 0, _("virtual memory exhausted"));
cleanup ();
exit (2);
}
@@ -214,10 +279,8 @@ xmalloc (n)
If P is NULL, run xmalloc.
If N is 0, run free and return NULL. */
-char *
-xrealloc (p, n)
- char *p;
- unsigned n;
+static char *
+xrealloc (char *p, unsigned int n)
{
if (p == 0)
return xmalloc (n);
@@ -229,7 +292,7 @@ xrealloc (p, n)
p = realloc (p, n);
if (p == 0)
{
- error (0, 0, "virtual memory exhausted");
+ error (0, 0, _("virtual memory exhausted"));
cleanup ();
exit (2);
}
@@ -237,50 +300,81 @@ xrealloc (p, n)
}
static FILE *
-xfopen (file, how)
- char *file, *how;
+xtmpfopen (const char *file)
{
- FILE *fp = strcmp (file, "-") ? fopen (file, how) : stdin;
+ FILE *fp;
+ int fd;
- if (fp == 0)
+ fd = open (file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd < 0 || (fp = fdopen (fd, "w")) == NULL)
{
error (0, errno, "%s", file);
cleanup ();
exit (2);
}
+
+ return fp;
+}
+
+static FILE *
+xfopen (const char *file, const char *how)
+{
+ FILE *fp;
+
+ if (strcmp (file, "-") == 0)
+ {
+ fp = stdin;
+ }
+ else
+ {
+ if ((fp = fopen (file, how)) == NULL)
+ {
+ error (0, errno, "%s", file);
+ cleanup ();
+ exit (2);
+ }
+ }
+
if (fp == stdin)
have_read_stdin = 1;
return fp;
}
static void
-xfclose (fp)
- FILE *fp;
+xfclose (FILE *fp)
{
- fflush (fp);
- if (fp != stdin && fp != stdout)
+ if (fp == stdin)
{
- if (fclose (fp) != 0)
+ /* Allow reading stdin from tty more than once. */
+ if (feof (fp))
+ clearerr (fp);
+ }
+ else if (fp == stdout)
+ {
+ if (fflush (fp) != 0)
{
- error (0, errno, "error closing file");
+ error (0, errno, _("flushing file"));
cleanup ();
exit (2);
}
}
else
- /* Allow reading stdin from tty more than once. */
- clearerr (fp);
+ {
+ if (fclose (fp) != 0)
+ {
+ error (0, errno, _("error closing file"));
+ cleanup ();
+ exit (2);
+ }
+ }
}
static void
-xfwrite (buf, size, nelem, fp)
- char *buf;
- int size, nelem;
- FILE *fp;
+xfwrite (const char *buf, int size, int nelem, FILE *fp)
{
if (fwrite (buf, size, nelem, fp) != nelem)
{
- error (0, errno, "write error");
+ error (0, errno, _("write error"));
cleanup ();
exit (2);
}
@@ -289,18 +383,25 @@ xfwrite (buf, size, nelem, fp)
/* Return a name for a temporary file. */
static char *
-tempname ()
+tempname (void)
{
- static int seq;
+ static unsigned int seq;
int len = strlen (temp_file_prefix);
- char *name = xmalloc (len + 16);
- struct tempnode *node =
- (struct tempnode *) xmalloc (sizeof (struct tempnode));
+ char *name = xmalloc (len + 1 + sizeof ("sort") - 1 + 5 + 5 + 1);
+ struct tempnode *node;
+
+ node = (struct tempnode *) xmalloc (sizeof (struct tempnode));
+ sprintf (name,
+ "%s%ssort%5.5d%5.5d",
+ temp_file_prefix,
+ (len && temp_file_prefix[len - 1] != '/') ? "/" : "",
+ (unsigned int) getpid () & 0xffff, seq);
+
+ /* Make sure that SEQ's value fits in 5 digits. */
+ ++seq;
+ if (seq >= 100000)
+ seq = 0;
- if (len && temp_file_prefix[len - 1] != '/')
- sprintf (name, "%s/sort%5.5d%5.5d", temp_file_prefix, getpid (), ++seq);
- else
- sprintf (name, "%ssort%5.5d%5.5d", temp_file_prefix, getpid (), ++seq);
node->name = name;
node->next = temphead.next;
temphead.next = node;
@@ -311,8 +412,7 @@ tempname ()
remove it if it is found on the list. */
static void
-zaptemp (name)
- char *name;
+zaptemp (char *name)
{
struct tempnode *node, *temp;
@@ -332,7 +432,7 @@ zaptemp (name)
/* Initialize the character class tables. */
static void
-inittables ()
+inittables (void)
{
int i;
@@ -356,9 +456,7 @@ inittables ()
/* Initialize BUF, allocating ALLOC bytes initially. */
static void
-initbuf (buf, alloc)
- struct buffer *buf;
- int alloc;
+initbuf (struct buffer *buf, int alloc)
{
buf->alloc = alloc;
buf->buf = xmalloc (buf->alloc);
@@ -371,13 +469,11 @@ initbuf (buf, alloc)
of bytes buffered. */
static int
-fillbuf (buf, fp)
- struct buffer *buf;
- FILE *fp;
+fillbuf (struct buffer *buf, FILE *fp)
{
int cc;
- bcopy (buf->buf + buf->used - buf->left, buf->buf, buf->left);
+ memmove (buf->buf, buf->buf + buf->used - buf->left, buf->left);
buf->used = buf->left;
while (!feof (fp) && (buf->used == 0 || !memchr (buf->buf, '\n', buf->used)))
@@ -390,7 +486,7 @@ fillbuf (buf, fp)
cc = fread (buf->buf + buf->used, 1, buf->alloc - buf->used, fp);
if (ferror (fp))
{
- error (0, errno, "read error");
+ error (0, errno, _("read error"));
cleanup ();
exit (2);
}
@@ -415,10 +511,7 @@ fillbuf (buf, fp)
for, ever. */
static void
-initlines (lines, alloc, limit)
- struct lines *lines;
- int alloc;
- int limit;
+initlines (struct lines *lines, int alloc, int limit)
{
lines->alloc = alloc;
lines->lines = (struct line *) xmalloc (lines->alloc * sizeof (struct line));
@@ -430,9 +523,7 @@ initlines (lines, alloc, limit)
by KEY in LINE. */
static char *
-begfield (line, key)
- struct line *line;
- struct keyfield *key;
+begfield (const struct line *line, const struct keyfield *key)
{
register char *ptr = line->text, *lim = ptr + line->length;
register int sword = key->sword, schar = key->schar;
@@ -458,8 +549,10 @@ begfield (line, key)
while (ptr < lim && blanks[UCHAR (*ptr)])
++ptr;
- while (ptr < lim && schar--)
- ++ptr;
+ if (ptr + schar <= lim)
+ ptr += schar;
+ else
+ ptr = lim;
return ptr;
}
@@ -468,19 +561,28 @@ begfield (line, key)
in LINE specified by KEY. */
static char *
-limfield (line, key)
- struct line *line;
- struct keyfield *key;
+limfield (const struct line *line, const struct keyfield *key)
{
register char *ptr = line->text, *lim = ptr + line->length;
register int eword = key->eword, echar = key->echar;
+ /* Note: from the POSIX spec:
+ The leading field separator itself is included in
+ a field when -t is not used. FIXME: move this comment up... */
+
+ /* Move PTR past EWORD fields or to one past the last byte on LINE,
+ whichever comes first. If there are more than EWORD fields, leave
+ PTR pointing at the beginning of the field having zero-based index,
+ EWORD. If a delimiter character was specified (via -t), then that
+ `beginning' is the first character following the delimiting TAB.
+ Otherwise, leave PTR pointing at the first `blank' character after
+ the preceding field. */
if (tab)
while (ptr < lim && eword--)
{
while (ptr < lim && *ptr != tab)
++ptr;
- if (ptr < lim && (eword || key->skipeblanks))
+ if (ptr < lim && (eword || echar > 0))
++ptr;
}
else
@@ -492,23 +594,54 @@ limfield (line, key)
++ptr;
}
- if (key->skipeblanks)
+ /* Make LIM point to the end of (one byte past) the current field. */
+ if (tab)
+ {
+ char *newlim;
+ newlim = memchr (ptr, tab, lim - ptr);
+ if (newlim)
+ lim = newlim;
+ }
+ else
+ {
+ char *newlim;
+ newlim = ptr;
+ while (newlim < lim && blanks[UCHAR (*newlim)])
+ ++newlim;
+ while (newlim < lim && !blanks[UCHAR (*newlim)])
+ ++newlim;
+ lim = newlim;
+ }
+
+ /* If we're skipping leading blanks, don't start counting characters
+ until after skipping past any leading blanks. */
+ if (key->skipsblanks)
while (ptr < lim && blanks[UCHAR (*ptr)])
++ptr;
- while (ptr < lim && echar--)
- ++ptr;
+ /* Advance PTR by ECHAR (if possible), but no further than LIM. */
+ if (ptr + echar <= lim)
+ ptr += echar;
+ else
+ ptr = lim;
return ptr;
}
+/* FIXME */
+
+void
+trim_trailing_blanks (const char *a_start, char **a_end)
+{
+ while (*a_end > a_start && blanks[UCHAR (*(*a_end - 1))])
+ --(*a_end);
+}
+
/* Find the lines in BUF, storing pointers and lengths in LINES.
- Also replace newlines with NULs. */
+ Also replace newlines in BUF with NULs. */
static void
-findlines (buf, lines)
- struct buffer *buf;
- struct lines *lines;
+findlines (struct buffer *buf, struct lines *lines)
{
register char *beg = buf->buf, *lim = buf->buf + buf->used, *ptr;
struct keyfield *key = keyhead.next;
@@ -553,6 +686,11 @@ findlines (buf, lines)
++beg;
lines->lines[lines->used].keybeg = beg;
}
+ if (key->skipeblanks)
+ {
+ trim_trailing_blanks (lines->lines[lines->used].keybeg,
+ &lines->lines[lines->used].keylim);
+ }
}
else
{
@@ -572,8 +710,7 @@ findlines (buf, lines)
of the fraction. Strings not of this form are considered to be zero. */
static int
-fraccompare (a, b)
- register char *a, *b;
+fraccompare (register const char *a, register const char *b)
{
register tmpa = UCHAR (*a), tmpb = UCHAR (*b);
@@ -628,12 +765,12 @@ fraccompare (a, b)
hideously fast. */
static int
-numcompare (a, b)
- register char *a, *b;
+numcompare (register const char *a, register const char *b)
{
register int tmpa, tmpb, loga, logb, tmp;
- tmpa = UCHAR (*a), tmpb = UCHAR (*b);
+ tmpa = UCHAR (*a);
+ tmpb = UCHAR (*b);
while (blanks[tmpa])
tmpa = UCHAR (*++a);
@@ -642,19 +779,30 @@ numcompare (a, b)
if (tmpa == '-')
{
- tmpa = UCHAR (*++a);
+ do
+ tmpa = UCHAR (*++a);
+ while (tmpa == '0');
if (tmpb != '-')
{
- if (digits[tmpa] && digits[tmpb])
+ if (tmpa == '.')
+ do
+ tmpa = UCHAR (*++a);
+ while (tmpa == '0');
+ if (digits[tmpa])
+ return -1;
+ while (tmpb == '0')
+ tmpb = UCHAR (*++b);
+ if (tmpb == '.')
+ do
+ tmpb = *++b;
+ while (tmpb == '0');
+ if (digits[tmpb])
return -1;
return 0;
}
- tmpb = UCHAR (*++b);
-
- while (tmpa == '0')
- tmpa = UCHAR (*++a);
- while (tmpb == '0')
+ do
tmpb = UCHAR (*++b);
+ while (tmpb == '0');
while (tmpa == tmpb && digits[tmpa])
tmpa = UCHAR (*++a), tmpb = UCHAR (*++b);
@@ -684,7 +832,22 @@ numcompare (a, b)
}
else if (tmpb == '-')
{
- if (digits[UCHAR (tmpa)] && digits[UCHAR (*++b)])
+ do
+ tmpb = UCHAR (*++b);
+ while (tmpb == '0');
+ if (tmpb == '.')
+ do
+ tmpb = *++b;
+ while (tmpb == '0');
+ if (digits[tmpb])
+ return 1;
+ while (tmpa == '0')
+ tmpa = UCHAR (*++a);
+ if (tmpa == '.')
+ do
+ tmpa = UCHAR (*++a);
+ while (tmpa == '0');
+ if (digits[tmpa])
return 1;
return 0;
}
@@ -723,13 +886,29 @@ numcompare (a, b)
}
}
+static int
+general_numcompare (const char *sa, const char *sb)
+{
+ double a, b;
+ /* FIXME: add option to warn about failed conversions. */
+ /* FIXME: maybe add option to try expensive FP conversion
+ only if A and B can't be compared more cheaply/accurately. */
+ if (xstrtod (sa, NULL, &a))
+ {
+ a = 0;
+ }
+ if (xstrtod (sb, NULL, &b))
+ {
+ b = 0;
+ }
+ return a == b ? 0 : a < b ? -1 : 1;
+}
+
/* Return an integer <= 12 associated with month name S with length LEN,
0 if the name in S is not recognized. */
static int
-getmonth (s, len)
- char *s;
- int len;
+getmonth (const char *s, int len)
{
char month[4];
register int i, lo = 0, hi = 12;
@@ -758,8 +937,7 @@ getmonth (s, len)
are no more keys or a difference is found. */
static int
-keycompare (a, b)
- struct line *a, *b;
+keycompare (const struct line *a, const struct line *b)
{
register char *texta, *textb, *lima, *limb, *translate;
register int *ignore;
@@ -808,6 +986,16 @@ keycompare (a, b)
if (lenb < 0)
lenb = 0;
+ if (key->skipeblanks)
+ {
+ char *a_end = texta + lena;
+ char *b_end = textb + lenb;
+ trim_trailing_blanks (texta, &a_end);
+ trim_trailing_blanks (textb, &b_end);
+ lena = a_end - texta;
+ lenb = b_end - textb;
+ }
+
/* Actually compare the fields. */
if (key->numeric)
{
@@ -826,6 +1014,23 @@ keycompare (a, b)
return key->reverse ? -diff : diff;
continue;
}
+ else if (key->general_numeric)
+ {
+ if (*lima || *limb)
+ {
+ char savea = *lima, saveb = *limb;
+
+ *lima = *limb = '\0';
+ diff = general_numcompare (texta, textb);
+ *lima = savea, *limb = saveb;
+ }
+ else
+ diff = general_numcompare (texta, textb);
+
+ if (diff)
+ return key->reverse ? -diff : diff;
+ continue;
+ }
else if (key->month)
{
diff = getmonth (texta, lena) - getmonth (textb, lenb);
@@ -834,38 +1039,64 @@ keycompare (a, b)
continue;
}
else if (ignore && translate)
- while (texta < lima && textb < limb)
- {
- while (texta < lima && ignore[UCHAR (*texta)])
- ++texta;
- while (textb < limb && ignore[UCHAR (*textb)])
- ++textb;
- if (texta < lima && textb < limb &&
- translate[UCHAR (*texta++)] != translate[UCHAR (*textb++)])
- {
- diff = translate[UCHAR (*--texta)] - translate[UCHAR (*--textb)];
- break;
- }
- }
+
+#define CMP_WITH_IGNORE(A, B) \
+ do \
+ { \
+ while (texta < lima && textb < limb) \
+ { \
+ while (texta < lima && ignore[UCHAR (*texta)]) \
+ ++texta; \
+ while (textb < limb && ignore[UCHAR (*textb)]) \
+ ++textb; \
+ if (texta < lima && textb < limb) \
+ { \
+ if ((A) != (B)) \
+ { \
+ diff = (A) - (B); \
+ break; \
+ } \
+ ++texta; \
+ ++textb; \
+ } \
+ \
+ if (texta == lima && textb < limb && !ignore[UCHAR (*textb)]) \
+ diff = -1; \
+ else if (texta < lima && textb == limb \
+ && !ignore[UCHAR (*texta)]) \
+ diff = 1; \
+ } \
+ \
+ if (diff == 0) \
+ { \
+ while (texta < lima && ignore[UCHAR (*texta)]) \
+ ++texta; \
+ while (textb < limb && ignore[UCHAR (*textb)]) \
+ ++textb; \
+ \
+ if (texta == lima && textb < limb) \
+ diff = -1; \
+ else if (texta < lima && textb == limb) \
+ diff = 1; \
+ } \
+ /* Relative lengths are meaningless if characters were ignored. \
+ Handling this case here avoids what might be an invalid length \
+ comparison below. */ \
+ if (diff == 0 && texta == lima && textb == limb) \
+ return 0; \
+ } \
+ while (0)
+
+ CMP_WITH_IGNORE (translate[UCHAR (*texta)], translate[UCHAR (*textb)]);
else if (ignore)
- while (texta < lima && textb < limb)
- {
- while (texta < lima && ignore[UCHAR (*texta)])
- ++texta;
- while (textb < limb && ignore[UCHAR (*textb)])
- ++textb;
- if (texta < lima && textb < limb && *texta++ != *textb++)
- {
- diff = *--texta - *--textb;
- break;
- }
- }
+ CMP_WITH_IGNORE (*texta, *textb);
else if (translate)
while (texta < lima && textb < limb)
{
if (translate[UCHAR (*texta++)] != translate[UCHAR (*textb++)])
{
- diff = translate[UCHAR (*--texta)] - translate[UCHAR (*--textb)];
+ diff = (translate[UCHAR (*--texta)]
+ - translate[UCHAR (*--textb)]);
break;
}
}
@@ -885,8 +1116,7 @@ keycompare (a, b)
depending on whether A compares less than, equal to, or greater than B. */
static int
-compare (a, b)
- register struct line *a, *b;
+compare (register const struct line *a, register const struct line *b)
{
int diff, tmpa, tmpb, mini;
@@ -925,18 +1155,17 @@ compare (a, b)
}
/* Check that the lines read from the given FP come in order. Return
- 1 if they do and 0 if there is a disorder. */
+ 1 if they do and 0 if there is a disorder.
+ FIXME: return number of first out-of-order line if not sorted. */
static int
-checkfp (fp)
- FILE *fp;
+checkfp (FILE *fp)
{
struct buffer buf; /* Input buffer. */
struct lines lines; /* Lines scanned from the buffer. */
struct line temp; /* Copy of previous line. */
int cc; /* Character count. */
- int cmp; /* Result of calling compare. */
- int alloc, i, success = 1;
+ int alloc, sorted = 1;
initbuf (&buf, mergealloc);
initlines (&lines, mergealloc / linelength + 1,
@@ -945,64 +1174,69 @@ checkfp (fp)
temp.text = xmalloc (alloc);
cc = fillbuf (&buf, fp);
+ if (cc == 0)
+ goto finish;
+
findlines (&buf, &lines);
- if (cc)
- do
- {
- /* Compare each line in the buffer with its successor. */
- for (i = 0; i < lines.used - 1; ++i)
- {
- cmp = compare (&lines.lines[i], &lines.lines[i + 1]);
- if ((unique && cmp >= 0) || (cmp > 0))
- {
- success = 0;
- goto finish;
- }
- }
+ while (1)
+ {
+ struct line *prev_line; /* Pointer to previous line. */
+ int cmp; /* Result of calling compare. */
+ int i;
- /* Save the last line of the buffer and refill the buffer. */
- if (lines.lines[lines.used - 1].length > alloc)
- {
- while (lines.lines[lines.used - 1].length + 1 > alloc)
- alloc *= 2;
- temp.text = xrealloc (temp.text, alloc);
- }
- bcopy (lines.lines[lines.used - 1].text, temp.text,
- lines.lines[lines.used - 1].length + 1);
- temp.length = lines.lines[lines.used - 1].length;
+ /* Compare each line in the buffer with its successor. */
+ for (i = 0; i < lines.used - 1; ++i)
+ {
+ cmp = compare (&lines.lines[i], &lines.lines[i + 1]);
+ if ((unique && cmp >= 0) || (cmp > 0))
+ {
+ sorted = 0;
+ goto finish;
+ }
+ }
- cc = fillbuf (&buf, fp);
- if (cc)
- {
- findlines (&buf, &lines);
- /* Make sure the line saved from the old buffer contents is
- less than or equal to the first line of the new buffer. */
- cmp = compare (&temp, &lines.lines[0]);
- if ((unique && cmp >= 0) || (cmp > 0))
- {
- success = 0;
- break;
- }
- }
- }
- while (cc);
+ /* Save the last line of the buffer and refill the buffer. */
+ prev_line = lines.lines + (lines.used - 1);
+ if (prev_line->length > alloc)
+ {
+ while (prev_line->length + 1 > alloc)
+ alloc *= 2;
+ temp.text = xrealloc (temp.text, alloc);
+ }
+ memcpy (temp.text, prev_line->text, prev_line->length + 1);
+ temp.length = prev_line->length;
+ temp.keybeg = temp.text + (prev_line->keybeg - prev_line->text);
+ temp.keylim = temp.text + (prev_line->keylim - prev_line->text);
+
+ cc = fillbuf (&buf, fp);
+ if (cc == 0)
+ break;
+
+ findlines (&buf, &lines);
+ /* Make sure the line saved from the old buffer contents is
+ less than or equal to the first line of the new buffer. */
+ cmp = compare (&temp, &lines.lines[0]);
+ if ((unique && cmp >= 0) || (cmp > 0))
+ {
+ sorted = 0;
+ break;
+ }
+ }
finish:
xfclose (fp);
free (buf.buf);
free ((char *) lines.lines);
free (temp.text);
- return success;
+ return sorted;
}
/* Merge lines from FPS onto OFP. NFPS cannot be greater than NMERGE.
Close FPS before returning. */
static void
-mergefps (fps, nfps, ofp)
- FILE *fps[], *ofp;
- register int nfps;
+mergefps (FILE **fps, register int nfps, FILE *ofp)
{
struct buffer buffer[NMERGE]; /* Input buffers for each file. */
struct lines lines[NMERGE]; /* Line tables for each buffer. */
@@ -1016,6 +1250,10 @@ mergefps (fps, nfps, ofp)
output. */
register int i, j, t;
+#ifdef lint /* Suppress `used before initialized' warning. */
+ savealloc = 0;
+#endif
+
/* Allocate space for a saved line if necessary. */
if (unique)
{
@@ -1059,7 +1297,7 @@ mergefps (fps, nfps, ofp)
/* Repeatedly output the smallest line until no input remains. */
while (nfps)
{
- /* If uniqified output is turned out, output only the first of
+ /* If uniqified output is turned on, output only the first of
an identical series of lines. */
if (unique)
{
@@ -1078,7 +1316,7 @@ mergefps (fps, nfps, ofp)
saved.text = xrealloc (saved.text, savealloc);
}
saved.length = lines[ord[0]].lines[cur[ord[0]]].length;
- bcopy (lines[ord[0]].lines[cur[ord[0]]].text, saved.text,
+ memcpy (saved.text, lines[ord[0]].lines[cur[ord[0]]].text,
saved.length + 1);
if (lines[ord[0]].lines[cur[ord[0]]].keybeg != NULL)
{
@@ -1160,9 +1398,7 @@ mergefps (fps, nfps, ofp)
/* Sort the array LINES with NLINES members, using TEMP for temporary space. */
static void
-sortlines (lines, nlines, temp)
- struct line *lines, *temp;
- int nlines;
+sortlines (struct line *lines, int nlines, struct line *temp)
{
register struct line *lo, *hi, *t;
register int nlo, nhi;
@@ -1203,9 +1439,7 @@ sortlines (lines, nlines, temp)
Return a count of disordered files. */
static int
-check (files, nfiles)
- char *files[];
- int nfiles;
+check (char **files, int nfiles)
{
int i, disorders = 0;
FILE *fp;
@@ -1215,7 +1449,7 @@ check (files, nfiles)
fp = xfopen (files[i], "r");
if (!checkfp (fp))
{
- printf ("%s: disorder on %s\n", program_name, files[i]);
+ fprintf (stderr, _("%s: disorder on %s\n"), program_name, files[i]);
++disorders;
}
}
@@ -1225,10 +1459,7 @@ check (files, nfiles)
/* Merge NFILES FILES onto OFP. */
static void
-merge (files, nfiles, ofp)
- char *files[];
- int nfiles;
- FILE *ofp;
+merge (char **files, int nfiles, FILE *ofp)
{
int i, j, t;
char *temp;
@@ -1241,7 +1472,7 @@ merge (files, nfiles, ofp)
{
for (j = 0; j < NMERGE; ++j)
fps[j] = xfopen (files[i * NMERGE + j], "r");
- tfp = xfopen (temp = tempname (), "w");
+ tfp = xtmpfopen (temp = tempname ());
mergefps (fps, NMERGE, tfp);
xfclose (tfp);
for (j = 0; j < NMERGE; ++j)
@@ -1250,7 +1481,7 @@ merge (files, nfiles, ofp)
}
for (j = 0; j < nfiles % NMERGE; ++j)
fps[j] = xfopen (files[i * NMERGE + j], "r");
- tfp = xfopen (temp = tempname (), "w");
+ tfp = xtmpfopen (temp = tempname ());
mergefps (fps, nfiles % NMERGE, tfp);
xfclose (tfp);
for (j = 0; j < nfiles % NMERGE; ++j)
@@ -1269,10 +1500,7 @@ merge (files, nfiles, ofp)
/* Sort NFILES FILES onto OFP. */
static void
-sort (files, nfiles, ofp)
- char **files;
- int nfiles;
- FILE *ofp;
+sort (char **files, int nfiles, FILE *ofp)
{
struct buffer buf;
struct lines lines;
@@ -1280,7 +1508,7 @@ sort (files, nfiles, ofp)
int i, ntmp;
FILE *fp, *tfp;
struct tempnode *node;
- int ntemp = 0;
+ int n_temp_files = 0;
char **tempfiles;
initbuf (&buf, sortalloc);
@@ -1303,12 +1531,12 @@ sort (files, nfiles, ofp)
xrealloc ((char *) tmp, ntmp * sizeof (struct line));
}
sortlines (lines.lines, lines.used, tmp);
- if (feof (fp) && !nfiles && !ntemp && !buf.left)
+ if (feof (fp) && !nfiles && !n_temp_files && !buf.left)
tfp = ofp;
else
{
- ++ntemp;
- tfp = xfopen (tempname (), "w");
+ ++n_temp_files;
+ tfp = xtmpfopen (tempname ());
}
for (i = 0; i < lines.used; ++i)
if (!unique || i == 0
@@ -1327,13 +1555,13 @@ sort (files, nfiles, ofp)
free ((char *) lines.lines);
free ((char *) tmp);
- if (ntemp)
+ if (n_temp_files)
{
- tempfiles = (char **) xmalloc (ntemp * sizeof (char *));
- i = ntemp;
+ tempfiles = (char **) xmalloc (n_temp_files * sizeof (char *));
+ i = n_temp_files;
for (node = temphead.next; i > 0; node = node->next)
tempfiles[--i] = node->name;
- merge (tempfiles, ntemp, ofp);
+ merge (tempfiles, n_temp_files, ofp);
free ((char *) tempfiles);
}
}
@@ -1341,8 +1569,7 @@ sort (files, nfiles, ofp)
/* Insert key KEY at the end of the list (`keyhead'). */
static void
-insertkey (key)
- struct keyfield *key;
+insertkey (struct keyfield *key)
{
struct keyfield *k = &keyhead;
@@ -1353,28 +1580,26 @@ insertkey (key)
}
static void
-badfieldspec (s)
- char *s;
+badfieldspec (const char *s)
{
- error (2, 0, "invalid field specification `%s'", s);
+ error (2, 0, _("invalid field specification `%s'"), s);
}
/* Handle interrupts and hangups. */
static void
-sighandler (sig)
- int sig;
+sighandler (int sig)
{
-#ifdef _POSIX_VERSION
+#ifdef SA_INTERRUPT
struct sigaction sigact;
sigact.sa_handler = SIG_DFL;
sigemptyset (&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction (sig, &sigact, NULL);
-#else /* !_POSIX_VERSION */
+#else /* !SA_INTERRUPT */
signal (sig, SIG_DFL);
-#endif /* _POSIX_VERSION */
+#endif /* SA_INTERRUPT */
cleanup ();
kill (getpid (), sig);
}
@@ -1385,10 +1610,8 @@ sighandler (sig)
BLANKTYPE is the kind of blanks that 'b' should skip. */
static char *
-set_ordering (s, key, blanktype)
- register char *s;
- struct keyfield *key;
- enum blanktype blanktype;
+set_ordering (register const char *s, struct keyfield *key,
+ enum blanktype blanktype)
{
while (*s)
{
@@ -1406,11 +1629,9 @@ set_ordering (s, key, blanktype)
case 'f':
key->translate = fold_toupper;
break;
-#if 0
case 'g':
- /* Reserved for comparing floating-point numbers. */
+ key->general_numeric = 1;
break;
-#endif
case 'i':
key->ignore = nonprinting;
break;
@@ -1419,22 +1640,24 @@ set_ordering (s, key, blanktype)
break;
case 'n':
key->numeric = 1;
+ if (blanktype == bl_start || blanktype == bl_both)
+ key->skipsblanks = 1;
+ if (blanktype == bl_end || blanktype == bl_both)
+ key->skipeblanks = 1;
break;
case 'r':
key->reverse = 1;
break;
default:
- return s;
+ return (char *) s;
}
++s;
}
- return s;
+ return (char *) s;
}
void
-main (argc, argv)
- int argc;
- char *argv[];
+main (int argc, char **argv)
{
struct keyfield *key = NULL, gkey;
char *s;
@@ -1442,19 +1665,22 @@ main (argc, argv)
int checkonly = 0, mergeonly = 0, nfiles = 0;
char *minus = "-", *outfile = minus, **files, *tmp;
FILE *ofp;
-#ifdef _POSIX_VERSION
+#ifdef SA_INTERRUPT
struct sigaction oldact, newact;
-#endif /* _POSIX_VERSION */
+#endif /* SA_INTERRUPT */
program_name = argv[0];
+
+ parse_long_options (argc, argv, "sort", version_string, usage);
+
have_read_stdin = 0;
inittables ();
temp_file_prefix = getenv ("TMPDIR");
if (temp_file_prefix == NULL)
- temp_file_prefix = "/tmp";
+ temp_file_prefix = DEFAULT_TMPDIR;
-#ifdef _POSIX_VERSION
+#ifdef SA_INTERRUPT
newact.sa_handler = sighandler;
sigemptyset (&newact.sa_mask);
newact.sa_flags = 0;
@@ -1471,7 +1697,7 @@ main (argc, argv)
sigaction (SIGTERM, NULL, &oldact);
if (oldact.sa_handler != SIG_IGN)
sigaction (SIGTERM, &newact, NULL);
-#else /* !_POSIX_VERSION */
+#else /* !SA_INTERRUPT */
if (signal (SIGINT, SIG_IGN) != SIG_IGN)
signal (SIGINT, sighandler);
if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
@@ -1480,12 +1706,12 @@ main (argc, argv)
signal (SIGPIPE, sighandler);
if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
signal (SIGTERM, sighandler);
-#endif /* !_POSIX_VERSION */
+#endif /* !SA_INTERRUPT */
gkey.sword = gkey.eword = -1;
gkey.ignore = NULL;
gkey.translate = NULL;
- gkey.numeric = gkey.month = gkey.reverse = 0;
+ gkey.numeric = gkey.general_numeric = gkey.month = gkey.reverse = 0;
gkey.skipsblanks = gkey.skipeblanks = 0;
files = (char **) xmalloc (sizeof (char *) * argc);
@@ -1501,9 +1727,9 @@ main (argc, argv)
key->ignore = NULL;
key->translate = NULL;
key->skipsblanks = key->skipeblanks = 0;
- key->numeric = key->month = key->reverse = 0;
+ key->numeric = key->general_numeric = key->month = key->reverse = 0;
s = argv[i] + 1;
- if (!digits[UCHAR (*s)])
+ if (! (digits[UCHAR (*s)] || (*s == '.' && digits[UCHAR (s[1])])))
badfieldspec (argv[i]);
for (t = 0; digits[UCHAR (*s)]; ++s)
t = 10 * t + *s - '0';
@@ -1525,10 +1751,10 @@ main (argc, argv)
else if (argv[i][0] == '-' && argv[i][1])
{
s = argv[i] + 1;
- if (digits[UCHAR (*s)])
+ if (digits[UCHAR (*s)] || (*s == '.' && digits[UCHAR (s[1])]))
{
if (!key)
- usage ();
+ usage (2);
for (t = 0; digits[UCHAR (*s)]; ++s)
t = t * 10 + *s - '0';
t2 = 0;
@@ -1560,7 +1786,7 @@ main (argc, argv)
else
{
if (i == argc - 1)
- error (2, 0, "option `-k' requires an argument");
+ error (2, 0, _("option `-k' requires an argument"));
else
s = argv[++i];
}
@@ -1578,15 +1804,34 @@ main (argc, argv)
badfieldspec (argv[i]);
for (t = 0; digits[UCHAR (*s)]; ++s)
t = 10 * t + *s - '0';
- if (t)
- t--;
+ if (t == 0)
+ {
+ /* Provoke with `sort -k0' */
+ error (0, 0, _("the starting field number argument \
+to the `-k' option must be positive"));
+ badfieldspec (argv[i]);
+ }
+ --t;
t2 = 0;
if (*s == '.')
{
+ if (!digits[UCHAR (s[1])])
+ {
+ /* Provoke with `sort -k1.' */
+ error (0, 0, _("starting field spec has `.' but \
+lacks following character offset"));
+ badfieldspec (argv[i]);
+ }
for (++s; digits[UCHAR (*s)]; ++s)
t2 = 10 * t2 + *s - '0';
- if (t2)
- t2--;
+ if (t2 == 0)
+ {
+ /* Provoke with `sort -k1.0' */
+ error (0, 0, _("starting field character offset \
+argument to the `-k' option\nmust be positive"));
+ badfieldspec (argv[i]);
+ }
+ --t2;
}
if (t2 || t)
{
@@ -1596,20 +1841,52 @@ main (argc, argv)
else
key->sword = -1;
s = set_ordering (s, key, bl_start);
- if (*s && *s != ',')
+ if (*s == 0)
+ {
+ key->eword = -1;
+ key->echar = 0;
+ }
+ else if (*s != ',')
badfieldspec (argv[i]);
- else if (*s++)
+ else if (*s == ',')
{
+ /* Skip over comma. */
+ ++s;
+ if (*s == 0)
+ {
+ /* Provoke with `sort -k1,' */
+ error (0, 0, _("field specification has `,' but \
+lacks following field spec"));
+ badfieldspec (argv[i]);
+ }
/* Get POS2. */
for (t = 0; digits[UCHAR (*s)]; ++s)
t = t * 10 + *s - '0';
+ if (t == 0)
+ {
+ /* Provoke with `sort -k1,0' */
+ error (0, 0, _("ending field number argument \
+to the `-k' option must be positive"));
+ badfieldspec (argv[i]);
+ }
+ --t;
t2 = 0;
if (*s == '.')
{
+ if (!digits[UCHAR (s[1])])
+ {
+ /* Provoke with `sort -k1,1.' */
+ error (0, 0, _("ending field spec has `.' \
+but lacks following character offset"));
+ badfieldspec (argv[i]);
+ }
for (++s; digits[UCHAR (*s)]; ++s)
t2 = t2 * 10 + *s - '0';
- if (t2)
- t--;
+ }
+ else
+ {
+ /* `-k 2,3' is equivalent to `+1 -3'. */
+ ++t;
}
key->eword = t;
key->echar = t2;
@@ -1629,7 +1906,7 @@ main (argc, argv)
else
{
if (i == argc - 1)
- error (2, 0, "option `-o' requires an argument");
+ error (2, 0, _("option `-o' requires an argument"));
else
outfile = argv[++i];
}
@@ -1646,26 +1923,31 @@ main (argc, argv)
goto outer;
}
else
- error (2, 0, "option `-t' requires an argument");
+ error (2, 0, _("option `-t' requires an argument"));
break;
case 'T':
if (s[1])
temp_file_prefix = ++s;
- else if (i < argc - 1)
+ else
{
- temp_file_prefix = argv[++i];
- goto outer;
+ if (i < argc - 1)
+ temp_file_prefix = argv[++i];
+ else
+ error (2, 0, _("option `-T' requires an argument"));
}
- else
- error (2, 0, "option `-T' requires an argument");
- break;
+ goto outer;
+ /* break; */
case 'u':
unique = 1;
break;
+ case 'y':
+ /* Accept and ignore e.g. -y0 for compatibility with
+ Solaris 2. */
+ goto outer;
default:
- fprintf (stderr, "%s: unrecognized option `-%c'\n",
+ fprintf (stderr, _("%s: unrecognized option `-%c'\n"),
argv[0], *s);
- usage ();
+ usage (2);
}
if (*s)
++s;
@@ -1684,7 +1966,8 @@ main (argc, argv)
/* Inheritance of global options to individual keys. */
for (key = keyhead.next; key; key = key->next)
if (!key->ignore && !key->translate && !key->skipsblanks && !key->reverse
- && !key->skipeblanks && !key->month && !key->numeric)
+ && !key->skipeblanks && !key->month && !key->numeric
+ && !key->general_numeric)
{
key->ignore = gkey.ignore;
key->translate = gkey.translate;
@@ -1692,11 +1975,13 @@ main (argc, argv)
key->skipeblanks = gkey.skipeblanks;
key->month = gkey.month;
key->numeric = gkey.numeric;
+ key->general_numeric = gkey.general_numeric;
key->reverse = gkey.reverse;
}
if (!keyhead.next && (gkey.ignore || gkey.translate || gkey.skipsblanks
- || gkey.skipeblanks || gkey.month || gkey.numeric))
+ || gkey.skipeblanks || gkey.month || gkey.numeric
+ || gkey.general_numeric))
insertkey (&gkey);
reverse = gkey.reverse;
@@ -1711,32 +1996,61 @@ main (argc, argv)
if (strcmp (outfile, "-"))
{
- for (i = 0; i < nfiles; ++i)
- if (!strcmp (outfile, files[i]))
- break;
- if (i == nfiles)
- ofp = xfopen (outfile, "w");
- else
+ struct stat outstat;
+ if (stat (outfile, &outstat) == 0)
{
- char buf[8192];
- FILE *fp = xfopen (outfile, "r");
- int cc;
-
- tmp = tempname ();
- ofp = xfopen (tmp, "w");
- while ((cc = fread (buf, 1, sizeof buf, fp)) > 0)
- xfwrite (buf, 1, cc, ofp);
- if (ferror (fp))
+ /* The following code prevents a race condition when
+ people use the brain dead shell programming idiom:
+ cat file | sort -o file
+ This feature is provided for historical compatibility,
+ but we strongly discourage ever relying on this in
+ new shell programs. */
+
+ /* Temporarily copy each input file that might be another name
+ for the output file. When in doubt (e.g. a pipe), copy. */
+ for (i = 0; i < nfiles; ++i)
{
- error (0, errno, "%s", outfile);
- cleanup ();
- exit (2);
+ char buf[8192];
+ FILE *fp;
+ int cc;
+
+ if (S_ISREG (outstat.st_mode) && strcmp (outfile, files[i]))
+ {
+ struct stat instat;
+ if ((strcmp (files[i], "-")
+ ? stat (files[i], &instat)
+ : fstat (fileno (stdin), &instat)) != 0)
+ {
+ error (0, errno, "%s", files[i]);
+ cleanup ();
+ exit (2);
+ }
+ if (S_ISREG (instat.st_mode)
+ && (instat.st_ino != outstat.st_ino
+ || instat.st_dev != outstat.st_dev))
+ {
+ /* We know the files are distinct. */
+ continue;
+ }
+ }
+
+ fp = xfopen (files[i], "r");
+ tmp = tempname ();
+ ofp = xtmpfopen (tmp);
+ while ((cc = fread (buf, 1, sizeof buf, fp)) > 0)
+ xfwrite (buf, 1, cc, ofp);
+ if (ferror (fp))
+ {
+ error (0, errno, "%s", files[i]);
+ cleanup ();
+ exit (2);
+ }
+ xfclose (ofp);
+ xfclose (fp);
+ files[i] = tmp;
}
- xfclose (ofp);
- xfclose (fp);
- files[i] = tmp;
- ofp = xfopen (outfile, "w");
}
+ ofp = xfopen (outfile, "w");
}
else
ofp = stdout;
@@ -1753,22 +2067,12 @@ main (argc, argv)
Solaris, Ultrix, and Irix. This premature fflush makes the output
reappear. --karl@cs.umb.edu */
if (fflush (ofp) < 0)
- error (1, errno, "fflush", outfile);
+ error (1, errno, _("%s: write error"), outfile);
if (have_read_stdin && fclose (stdin) == EOF)
- error (1, errno, "-");
+ error (1, errno, outfile);
if (ferror (stdout) || fclose (stdout) == EOF)
- error (1, errno, "write error");
+ error (1, errno, _("%s: write error"), outfile);
exit (0);
}
-
-static void
-usage ()
-{
- fprintf (stderr, "\
-Usage: %s [-cmus] [-t separator] [-o output-file] [-T tempdir] [-bdfiMnr]\n\
- [+POS1 [-POS2]] [-k POS1[,POS2]] [file...]\n",
- program_name);
- exit (2);
-}
diff --git a/gnu/usr.bin/sort/system.h b/gnu/usr.bin/sort/system.h
index 2e03ea8..bfb19e1 100644
--- a/gnu/usr.bin/sort/system.h
+++ b/gnu/usr.bin/sort/system.h
@@ -13,14 +13,25 @@
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Include sys/types.h before this file. */
#include <sys/stat.h>
-#ifndef S_ISREG /* Doesn't have POSIX.1 stat stuff. */
-#define mode_t unsigned short
-#endif
+
+#ifdef STAT_MACROS_BROKEN
+#undef S_ISBLK
+#undef S_ISCHR
+#undef S_ISDIR
+#undef S_ISFIFO
+#undef S_ISLNK
+#undef S_ISMPB
+#undef S_ISMPC
+#undef S_ISNWK
+#undef S_ISREG
+#undef S_ISSOCK
+#endif /* STAT_MACROS_BROKEN. */
+
#if !defined(S_ISBLK) && defined(S_IFBLK)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
@@ -56,42 +67,56 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+
#ifndef _POSIX_VERSION
off_t lseek ();
#endif
-#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
-#if !defined(STDC_HEADERS) && defined(HAVE_MEMORY_H)
-#include <memory.h>
-#endif
-#include <string.h>
-#ifndef index
-#define index strchr
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
#endif
-#ifndef rindex
-#define rindex strrchr
-#endif
-/* Don't define bcopy; we need one that can handle overlaps. */
-#ifndef bzero
-#define bzero(s, n) memset ((s), 0, (n))
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
#endif
-#ifndef bcmp
-#define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
#endif
+
+/* Don't use bcopy! Use memmove if source and destination may overlap,
+ memcpy otherwise. */
+
+#ifdef HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
#else
-#include <strings.h>
+# include <strings.h>
char *memchr ();
#endif
#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+
#ifdef STDC_HEADERS
#include <stdlib.h>
#else
char *getenv ();
-extern int errno;
#endif
-#if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION)
+#ifndef EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+#ifndef EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+
+#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#else
#include <sys/file.h>
@@ -139,28 +164,42 @@ extern int errno;
#include <ctype.h>
-#ifndef isascii
-#define isascii(c) 1
+#if defined (STDC_HEADERS) || (!defined (isascii) && !defined (HAVE_ISASCII))
+#define ISASCII(c) 1
+#else
+#define ISASCII(c) isascii(c)
#endif
#ifdef isblank
-#define ISBLANK(c) (isascii (c) && isblank (c))
+#define ISBLANK(c) (ISASCII (c) && isblank (c))
#else
#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
#endif
#ifdef isgraph
-#define ISGRAPH(c) (isascii (c) && isgraph (c))
+#define ISGRAPH(c) (ISASCII (c) && isgraph (c))
#else
-#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c))
-#endif
-
-#define ISPRINT(c) (isascii (c) && isprint (c))
-#define ISDIGIT(c) (isascii (c) && isdigit (c))
-#define ISALNUM(c) (isascii (c) && isalnum (c))
-#define ISALPHA(c) (isascii (c) && isalpha (c))
-#define ISCNTRL(c) (isascii (c) && iscntrl (c))
-#define ISLOWER(c) (isascii (c) && islower (c))
-#define ISPUNCT(c) (isascii (c) && ispunct (c))
-#define ISSPACE(c) (isascii (c) && isspace (c))
-#define ISUPPER(c) (isascii (c) && isupper (c))
-#define ISXDIGIT(c) (isascii (c) && isxdigit (c))
+#define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
+#endif
+
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+/* Disable string localization for the time being. */
+#undef _
+#define _(String) String
+
+#ifndef __P
+# if PROTOTYPES
+# define __P(Args) Args
+# else
+# define __P(Args) ()
+# endif
+#endif
diff --git a/gnu/usr.bin/sort/version.c b/gnu/usr.bin/sort/version.c
index 64c62b19..0289fcb 100644
--- a/gnu/usr.bin/sort/version.c
+++ b/gnu/usr.bin/sort/version.c
@@ -1,13 +1,3 @@
-#ifdef HAVE_CONFIG_H
-#if defined (CONFIG_BROKETS)
-/* We use <config.h> instead of "config.h" so that a compilation
- using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
- (which it would do because it found this file in $srcdir). */
#include <config.h>
-#else
-#include "config.h"
-#endif
-#endif
-
#include "version.h"
-const char *version_string = "GNU textutils 1.9";
+const char *version_string = "GNU textutils 1.14";
diff --git a/gnu/usr.bin/sort/xstrtod.c b/gnu/usr.bin/sort/xstrtod.c
new file mode 100644
index 0000000..838c5c4
--- /dev/null
+++ b/gnu/usr.bin/sort/xstrtod.c
@@ -0,0 +1,48 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#else
+double strtod ();
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <limits.h>
+#include <ctype.h>
+#include "xstrtod.h"
+
+int
+xstrtod (str, ptr, result)
+ const char *str;
+ const char **ptr;
+ double *result;
+{
+ double val;
+ char *terminator;
+ int fail;
+
+ fail = 0;
+ errno = 0;
+ val = strtod (str, &terminator);
+
+ /* Having a non-zero terminator is an error only when PTR is NULL. */
+ if (terminator == str || (ptr == NULL && *terminator != '\0'))
+ fail = 1;
+ else
+ {
+ /* Allow underflow (in which case strtod returns zero),
+ but flag overflow as an error. */
+ if (val != 0.0 && errno == ERANGE)
+ fail = 1;
+ }
+
+ if (ptr != NULL)
+ *ptr = terminator;
+
+ *result = val;
+ return fail;
+}
+
diff --git a/gnu/usr.bin/sort/xstrtod.h b/gnu/usr.bin/sort/xstrtod.h
new file mode 100644
index 0000000..15b85f4
--- /dev/null
+++ b/gnu/usr.bin/sort/xstrtod.h
@@ -0,0 +1,15 @@
+#ifndef XSTRTOD_H
+#define XSTRTOD_H 1
+
+#ifndef __P
+# if defined (__GNUC__) || (defined (__STDC__) && __STDC__)
+# define __P(args) args
+# else
+# define __P(args) ()
+# endif /* GCC. */
+#endif /* Not __P. */
+
+int
+ xstrtod __P ((const char *str, const char **ptr, double *result));
+
+#endif /* XSTRTOD_H */
OpenPOWER on IntegriCloud