summaryrefslogtreecommitdiff
path: root/gl
diff options
context:
space:
mode:
Diffstat (limited to 'gl')
-rw-r--r--gl/lib/buffer-lcm.c59
-rw-r--r--gl/lib/buffer-lcm.h2
-rw-r--r--gl/lib/fd-reopen.c46
-rw-r--r--gl/lib/fd-reopen.h22
-rw-r--r--gl/lib/strintcmp.c32
-rw-r--r--gl/lib/strnumcmp-in.h244
-rw-r--r--gl/lib/strnumcmp.c31
-rw-r--r--gl/lib/strnumcmp.h2
-rw-r--r--gl/lib/xfts.c65
-rw-r--r--gl/lib/xfts.h10
-rw-r--r--gl/modules/buffer-lcm23
-rw-r--r--gl/modules/fd-reopen23
-rw-r--r--gl/modules/strnumcmp26
-rw-r--r--gl/modules/xfts23
14 files changed, 608 insertions, 0 deletions
diff --git a/gl/lib/buffer-lcm.c b/gl/lib/buffer-lcm.c
new file mode 100644
index 000000000..1d22dac7d
--- /dev/null
+++ b/gl/lib/buffer-lcm.c
@@ -0,0 +1,59 @@
+/* buffer-lcm.c - compute a good buffer size for dealing with two files
+
+ Copyright (C) 2002-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+#include "buffer-lcm.h"
+
+/* Return a buffer size suitable for doing I/O with files whose block
+ sizes are A and B. However, never return a value greater than
+ LCM_MAX. */
+
+size_t
+buffer_lcm (size_t a, size_t b, size_t lcm_max)
+{
+ size_t size;
+
+ /* Use reasonable values if buffer sizes are zero. */
+ if (!a)
+ size = b ? b : 8 * 1024;
+ else
+ {
+ if (b)
+ {
+ /* Return lcm (A, B) if it is in range; otherwise, fall back
+ on A. */
+
+ size_t lcm, m, n, q, r;
+
+ /* N = gcd (A, B). */
+ for (m = a, n = b; (r = m % n) != 0; m = n, n = r)
+ continue;
+
+ /* LCM = lcm (A, B), if in range. */
+ q = a / n;
+ lcm = q * b;
+ if (lcm <= lcm_max && lcm / b == q)
+ return lcm;
+ }
+
+ size = a;
+ }
+
+ return size <= lcm_max ? size : lcm_max;
+}
diff --git a/gl/lib/buffer-lcm.h b/gl/lib/buffer-lcm.h
new file mode 100644
index 000000000..454c65be8
--- /dev/null
+++ b/gl/lib/buffer-lcm.h
@@ -0,0 +1,2 @@
+#include <stddef.h>
+size_t buffer_lcm (size_t, size_t, size_t) _GL_ATTRIBUTE_CONST;
diff --git a/gl/lib/fd-reopen.c b/gl/lib/fd-reopen.c
new file mode 100644
index 000000000..fd4b92bea
--- /dev/null
+++ b/gl/lib/fd-reopen.c
@@ -0,0 +1,46 @@
+/* Invoke open, but return either a desired file descriptor or -1.
+
+ Copyright (C) 2005-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "fd-reopen.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* Open a file to a particular file descriptor. This is like standard
+ 'open', except it always returns DESIRED_FD if successful. */
+
+int
+fd_reopen (int desired_fd, char const *file, int flags, mode_t mode)
+{
+ int fd = open (file, flags, mode);
+
+ if (fd == desired_fd || fd < 0)
+ return fd;
+ else
+ {
+ int fd2 = dup2 (fd, desired_fd);
+ int saved_errno = errno;
+ close (fd);
+ errno = saved_errno;
+ return fd2;
+ }
+}
diff --git a/gl/lib/fd-reopen.h b/gl/lib/fd-reopen.h
new file mode 100644
index 000000000..b80f09862
--- /dev/null
+++ b/gl/lib/fd-reopen.h
@@ -0,0 +1,22 @@
+/* Invoke open, but return either a desired file descriptor or -1.
+
+ Copyright (C) 2005-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <sys/types.h>
+
+int fd_reopen (int, char const *, int, mode_t);
diff --git a/gl/lib/strintcmp.c b/gl/lib/strintcmp.c
new file mode 100644
index 000000000..6e4901e22
--- /dev/null
+++ b/gl/lib/strintcmp.c
@@ -0,0 +1,32 @@
+/* Compare integer strings.
+
+ Copyright (C) 2005-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "strnumcmp-in.h"
+
+/* Compare strings A and B as integers without explicitly converting
+ them to machine numbers, to avoid overflow problems and perhaps
+ improve performance. */
+
+int
+strintcmp (char const *a, char const *b)
+{
+ return numcompare (a, b, -1, -1);
+}
diff --git a/gl/lib/strnumcmp-in.h b/gl/lib/strnumcmp-in.h
new file mode 100644
index 000000000..95ab55fdc
--- /dev/null
+++ b/gl/lib/strnumcmp-in.h
@@ -0,0 +1,244 @@
+/* Compare numeric strings. This is an internal include file.
+
+ Copyright (C) 1988-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Mike Haertel. */
+
+#ifndef STRNUMCMP_IN_H
+# define STRNUMCMP_IN_H 1
+
+# include "strnumcmp.h"
+
+# include <stddef.h>
+
+# define NEGATION_SIGN '-'
+# define NUMERIC_ZERO '0'
+
+/* ISDIGIT differs from isdigit, as follows:
+ - Its arg may be any int or unsigned int; it need not be an unsigned char
+ or EOF.
+ - It's typically faster.
+ POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
+ isdigit unless it's important to use the locale's definition
+ of 'digit' even when the host does not conform to POSIX. */
+# define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
+
+
+/* Compare strings A and B containing decimal fractions < 1.
+ DECIMAL_POINT is the decimal point. Each string
+ should begin with a decimal point followed immediately by the digits
+ of the fraction. Strings not of this form are treated as zero. */
+
+/* The goal here, is to take two numbers a and b... compare these
+ in parallel. Instead of converting each, and then comparing the
+ outcome. Most likely stopping the comparison before the conversion
+ is complete. The algorithm used, in the old "sort" utility:
+
+ Algorithm: fraccompare
+ Action : compare two decimal fractions
+ accepts : char *a, char *b
+ returns : -1 if a<b, 0 if a=b, 1 if a>b.
+ implement:
+
+ if *a == decimal_point AND *b == decimal_point
+ find first character different in a and b.
+ if both are digits, return the difference *a - *b.
+ if *a is a digit
+ skip past zeros
+ if digit return 1, else 0
+ if *b is a digit
+ skip past zeros
+ if digit return -1, else 0
+ if *a is a decimal_point
+ skip past decimal_point and zeros
+ if digit return 1, else 0
+ if *b is a decimal_point
+ skip past decimal_point and zeros
+ if digit return -1, else 0
+ return 0 */
+
+static inline int _GL_ATTRIBUTE_PURE
+fraccompare (char const *a, char const *b, char decimal_point)
+{
+ if (*a == decimal_point && *b == decimal_point)
+ {
+ while (*++a == *++b)
+ if (! ISDIGIT (*a))
+ return 0;
+ if (ISDIGIT (*a) && ISDIGIT (*b))
+ return *a - *b;
+ if (ISDIGIT (*a))
+ goto a_trailing_nonzero;
+ if (ISDIGIT (*b))
+ goto b_trailing_nonzero;
+ return 0;
+ }
+ else if (*a++ == decimal_point)
+ {
+ a_trailing_nonzero:
+ while (*a == NUMERIC_ZERO)
+ a++;
+ return ISDIGIT (*a);
+ }
+ else if (*b++ == decimal_point)
+ {
+ b_trailing_nonzero:
+ while (*b == NUMERIC_ZERO)
+ b++;
+ return - ISDIGIT (*b);
+ }
+ return 0;
+}
+
+/* Compare strings A and B as numbers without explicitly converting
+ them to machine numbers, to avoid overflow problems and perhaps
+ improve performance. DECIMAL_POINT is the decimal point and
+ THOUSANDS_SEP the thousands separator. A DECIMAL_POINT of -1
+ causes comparisons to act as if there is no decimal point
+ character, and likewise for THOUSANDS_SEP. */
+
+static inline int _GL_ATTRIBUTE_PURE
+numcompare (char const *a, char const *b,
+ int decimal_point, int thousands_sep)
+{
+ unsigned char tmpa = *a;
+ unsigned char tmpb = *b;
+ int tmp;
+ size_t log_a;
+ size_t log_b;
+
+ if (tmpa == NEGATION_SIGN)
+ {
+ do
+ tmpa = *++a;
+ while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep);
+ if (tmpb != NEGATION_SIGN)
+ {
+ if (tmpa == decimal_point)
+ do
+ tmpa = *++a;
+ while (tmpa == NUMERIC_ZERO);
+ if (ISDIGIT (tmpa))
+ return -1;
+ while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep)
+ tmpb = *++b;
+ if (tmpb == decimal_point)
+ do
+ tmpb = *++b;
+ while (tmpb == NUMERIC_ZERO);
+ return - ISDIGIT (tmpb);
+ }
+ do
+ tmpb = *++b;
+ while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep);
+
+ while (tmpa == tmpb && ISDIGIT (tmpa))
+ {
+ do
+ tmpa = *++a;
+ while (tmpa == thousands_sep);
+ do
+ tmpb = *++b;
+ while (tmpb == thousands_sep);
+ }
+
+ if ((tmpa == decimal_point && !ISDIGIT (tmpb))
+ || (tmpb == decimal_point && !ISDIGIT (tmpa)))
+ return fraccompare (b, a, decimal_point);
+
+ tmp = tmpb - tmpa;
+
+ for (log_a = 0; ISDIGIT (tmpa); ++log_a)
+ do
+ tmpa = *++a;
+ while (tmpa == thousands_sep);
+
+ for (log_b = 0; ISDIGIT (tmpb); ++log_b)
+ do
+ tmpb = *++b;
+ while (tmpb == thousands_sep);
+
+ if (log_a != log_b)
+ return log_a < log_b ? 1 : -1;
+
+ if (!log_a)
+ return 0;
+
+ return tmp;
+ }
+ else if (tmpb == NEGATION_SIGN)
+ {
+ do
+ tmpb = *++b;
+ while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep);
+ if (tmpb == decimal_point)
+ do
+ tmpb = *++b;
+ while (tmpb == NUMERIC_ZERO);
+ if (ISDIGIT (tmpb))
+ return 1;
+ while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep)
+ tmpa = *++a;
+ if (tmpa == decimal_point)
+ do
+ tmpa = *++a;
+ while (tmpa == NUMERIC_ZERO);
+ return ISDIGIT (tmpa);
+ }
+ else
+ {
+ while (tmpa == NUMERIC_ZERO || tmpa == thousands_sep)
+ tmpa = *++a;
+ while (tmpb == NUMERIC_ZERO || tmpb == thousands_sep)
+ tmpb = *++b;
+
+ while (tmpa == tmpb && ISDIGIT (tmpa))
+ {
+ do
+ tmpa = *++a;
+ while (tmpa == thousands_sep);
+ do
+ tmpb = *++b;
+ while (tmpb == thousands_sep);
+ }
+
+ if ((tmpa == decimal_point && !ISDIGIT (tmpb))
+ || (tmpb == decimal_point && !ISDIGIT (tmpa)))
+ return fraccompare (a, b, decimal_point);
+
+ tmp = tmpa - tmpb;
+
+ for (log_a = 0; ISDIGIT (tmpa); ++log_a)
+ do
+ tmpa = *++a;
+ while (tmpa == thousands_sep);
+
+ for (log_b = 0; ISDIGIT (tmpb); ++log_b)
+ do
+ tmpb = *++b;
+ while (tmpb == thousands_sep);
+
+ if (log_a != log_b)
+ return log_a < log_b ? -1 : 1;
+
+ if (!log_a)
+ return 0;
+
+ return tmp;
+ }
+}
+
+#endif
diff --git a/gl/lib/strnumcmp.c b/gl/lib/strnumcmp.c
new file mode 100644
index 000000000..115ab598a
--- /dev/null
+++ b/gl/lib/strnumcmp.c
@@ -0,0 +1,31 @@
+/* Compare numeric strings.
+
+ Copyright (C) 2005-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Paul Eggert. */
+
+#include <config.h>
+
+#include "strnumcmp-in.h"
+
+/* Externally-visible name for numcompare. */
+
+int _GL_ATTRIBUTE_PURE
+strnumcmp (char const *a, char const *b,
+ int decimal_point, int thousands_sep)
+{
+ return numcompare (a, b, decimal_point, thousands_sep);
+}
diff --git a/gl/lib/strnumcmp.h b/gl/lib/strnumcmp.h
new file mode 100644
index 000000000..4deef82bd
--- /dev/null
+++ b/gl/lib/strnumcmp.h
@@ -0,0 +1,2 @@
+int strintcmp (char const *, char const *) _GL_ATTRIBUTE_PURE;
+int strnumcmp (char const *, char const *, int, int);
diff --git a/gl/lib/xfts.c b/gl/lib/xfts.c
new file mode 100644
index 000000000..b19200e20
--- /dev/null
+++ b/gl/lib/xfts.c
@@ -0,0 +1,65 @@
+/* xfts.c -- a wrapper for fts_open
+
+ Copyright (C) 2003-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */
+
+/* Written by Jim Meyering. */
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "xalloc.h"
+#include "xfts.h"
+
+/* Fail with a proper diagnostic if fts_open fails. */
+
+FTS *
+xfts_open (char * const *argv, int options,
+ int (*compar) (const FTSENT **, const FTSENT **))
+{
+ FTS *fts = fts_open (argv, options | FTS_CWDFD, compar);
+ if (fts == NULL)
+ {
+ /* This can fail in two ways: out of memory or with errno==EINVAL,
+ which indicates it was called with invalid bit_flags. */
+ assert (errno != EINVAL);
+ xalloc_die ();
+ }
+
+ return fts;
+}
+
+/* When fts_read returns FTS_DC to indicate a directory cycle,
+ it may or may not indicate a real problem. When a program like
+ chgrp performs a recursive traversal that requires traversing
+ symbolic links, it is *not* a problem. However, when invoked
+ with "-P -R", it deserves a warning. The fts_options member
+ records the options that control this aspect of fts's behavior,
+ so test that. */
+bool
+cycle_warning_required (FTS const *fts, FTSENT const *ent)
+{
+#define ISSET(Fts,Opt) ((Fts)->fts_options & (Opt))
+ /* When dereferencing no symlinks, or when dereferencing only
+ those listed on the command line and we're not processing
+ a command-line argument, then a cycle is a serious problem. */
+ return ((ISSET (fts, FTS_PHYSICAL) && !ISSET (fts, FTS_COMFOLLOW))
+ || (ISSET (fts, FTS_PHYSICAL) && ISSET (fts, FTS_COMFOLLOW)
+ && ent->fts_level != FTS_ROOTLEVEL));
+}
diff --git a/gl/lib/xfts.h b/gl/lib/xfts.h
new file mode 100644
index 000000000..f903f4804
--- /dev/null
+++ b/gl/lib/xfts.h
@@ -0,0 +1,10 @@
+#include <stdbool.h>
+#include "fts_.h"
+
+FTS *
+xfts_open (char * const *, int options,
+ int (*) (const FTSENT **, const FTSENT **));
+
+bool
+cycle_warning_required (FTS const *fts, FTSENT const *ent)
+ _GL_ATTRIBUTE_PURE;
diff --git a/gl/modules/buffer-lcm b/gl/modules/buffer-lcm
new file mode 100644
index 000000000..1d86f715e
--- /dev/null
+++ b/gl/modules/buffer-lcm
@@ -0,0 +1,23 @@
+Description:
+Compute a good buffer size for dealing with two files.
+
+Files:
+lib/buffer-lcm.c
+lib/buffer-lcm.h
+
+Depends-on:
+stddef
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += buffer-lcm.c buffer-lcm.h
+
+Include:
+"buffer-lcm.h"
+
+License:
+GPL
+
+Maintainer:
+Paul Eggert
diff --git a/gl/modules/fd-reopen b/gl/modules/fd-reopen
new file mode 100644
index 000000000..70a21c317
--- /dev/null
+++ b/gl/modules/fd-reopen
@@ -0,0 +1,23 @@
+Description:
+Open a file to a particular file descriptor.
+
+Files:
+lib/fd-reopen.c
+lib/fd-reopen.h
+
+Depends-on:
+fcntl-h
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += fd-reopen.c fd-reopen.h
+
+Include:
+"fd-reopen.h"
+
+License:
+GPL
+
+Maintainer:
+Paul Eggert
diff --git a/gl/modules/strnumcmp b/gl/modules/strnumcmp
new file mode 100644
index 000000000..83f4e7c38
--- /dev/null
+++ b/gl/modules/strnumcmp
@@ -0,0 +1,26 @@
+Description:
+Compare numeric strings.
+
+Files:
+lib/strintcmp.c
+lib/strnumcmp.c
+lib/strnumcmp.h
+lib/strnumcmp-in.h
+
+Depends-on:
+inline
+stddef
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += strintcmp.c strnumcmp.c strnumcmp.h
+
+Include:
+"strnumcmp.h"
+
+License:
+GPL
+
+Maintainer:
+Paul Eggert
diff --git a/gl/modules/xfts b/gl/modules/xfts
new file mode 100644
index 000000000..335946e2f
--- /dev/null
+++ b/gl/modules/xfts
@@ -0,0 +1,23 @@
+Description:
+a wrapper for fts_open
+
+Files:
+lib/xfts.c
+lib/xfts.h
+
+Depends-on:
+stddef
+
+configure.ac:
+
+Makefile.am:
+lib_SOURCES += xfts.c xfts.h
+
+Include:
+"xfts.h"
+
+License:
+GPL
+
+Maintainer:
+Jim Meyering