summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2005-09-22 06:44:26 +0000
committerPaul Eggert <eggert@cs.ucla.edu>2005-09-22 06:44:26 +0000
commiteba2793d1131e5c03d6357d5a727120340836e8f (patch)
tree992c967b6e97d1793e15adfe32bda95b67b9c8f1
parentda6ced865126d933c839f19ce9dd002b71d1d5a3 (diff)
downloadcoreutils-eba2793d1131e5c03d6357d5a727120340836e8f.tar.xz
Nontrivial sync from gnulib.
-rw-r--r--lib/canon-host.c149
-rw-r--r--lib/getline.c48
-rw-r--r--lib/getline.h49
-rw-r--r--lib/getpass.c151
-rw-r--r--lib/strcasecmp.c98
-rw-r--r--lib/strncasecmp.c60
-rw-r--r--lib/strstr.c215
-rw-r--r--m4/canon-host.m419
-rw-r--r--m4/getline.m424
-rw-r--r--m4/mbrtowc.m420
-rw-r--r--m4/strcase.m415
-rw-r--r--m4/strstr.m416
12 files changed, 454 insertions, 410 deletions
diff --git a/lib/canon-host.c b/lib/canon-host.c
index 63c437e1e..e2bd1a773 100644
--- a/lib/canon-host.c
+++ b/lib/canon-host.c
@@ -1,9 +1,8 @@
/* Host name canonicalization
- Copyright (C) 1995, 1999, 2000, 2002, 2003, 2004, 2005 Free Software
- Foundation, Inc.
+ Copyright (C) 2005 Free Software Foundation, Inc.
- Written by Miles Bader <miles@gnu.ai.mit.edu>
+ Written by Derek Price <derek@ximbiot.com>.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -23,103 +22,69 @@
# include <config.h>
#endif
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
+#include "canon-host.h"
+#include "getaddrinfo.h"
#include "strdup.h"
-/* Returns the canonical hostname associated with HOST (allocated in a static
- buffer), or NULL if it can't be determined. */
+/* Store the last error for the single-threaded version of this function. */
+static int last_cherror;
+
+/* Single-threaded of wrapper for canon_host_r. After a NULL return, error
+ messages may be retrieved via ch_strerror(). */
char *
-canon_host (char const *host)
+canon_host (const char *host)
{
- char *h_addr_copy = NULL;
-
-#if HAVE_GETADDRINFO
- {
- struct addrinfo hint = { 0, };
- struct addrinfo *res = NULL;
- hint.ai_flags = AI_CANONNAME;
- if (getaddrinfo (host, NULL, &hint, &res) == 0)
- {
- h_addr_copy = strdup (res->ai_canonname);
- freeaddrinfo (res);
- }
- }
-#elif HAVE_GETHOSTBYNAME
- {
- struct hostent *he = gethostbyname (host);
-
- if (he)
- {
-# ifdef HAVE_GETHOSTBYADDR
- char *addr = NULL;
-
- /* Try and get an ascii version of the numeric host address. */
- switch (he->h_addrtype)
- {
-# ifdef HAVE_INET_NTOA
- case AF_INET:
- addr = inet_ntoa (*(struct in_addr *) he->h_addr);
- break;
-# endif /* HAVE_INET_NTOA */
- }
-
- if (addr && strcmp (he->h_name, addr) == 0)
- {
- /* gethostbyname has returned a string representation of the IP
- address, for example, "127.0.0.1". So now, look up the host
- name via the address. Although it may seem reasonable to look
- up the host name via the address, we must not pass `he->h_addr'
- directly to gethostbyaddr because on some systems he->h_addr
- is located in a static library buffer that is reused in the
- gethostbyaddr call. Make a copy and use that instead. */
- h_addr_copy = (char *) malloc (he->h_length);
- if (h_addr_copy == NULL)
- he = NULL;
- else
- {
- memcpy (h_addr_copy, he->h_addr, he->h_length);
- he = gethostbyaddr (h_addr_copy, he->h_length, he->h_addrtype);
- free (h_addr_copy);
- }
- }
-# endif /* HAVE_GETHOSTBYADDR */
-
- if (he)
- h_addr_copy = strdup (he->h_name);
- }
- }
-#endif /* HAVE_GETHOSTBYNAME */
-
- return h_addr_copy;
+ return canon_host_r (host, &last_cherror);
}
-#ifdef TEST_CANON_HOST
-int
-main (int argc, char **argv)
+/* Return a malloc'd string containing the canonical hostname associated with
+ HOST, or NULL if a canonical name cannot be determined. On NULL return,
+ if CHERROR is not NULL, set *CHERROR to an error code as returned by
+ getaddrinfo(). Use ch_strerror_r() or gai_strerror() to convert a *CHERROR
+ value to a string suitable for error messages.
+
+ WARNINGS
+ HOST must be a string representation of a resolvable name for this host.
+ Strings containing an IP address in dotted decimal notation will be
+ returned as-is, without further resolution.
+
+ The use of the word "canonical" in this context is unfortunate but
+ entrenched. The value returned by this function will be the end result
+ of the resolution of any CNAME chains in the DNS. There may only be one
+ such value for any given hostname, though the actual IP address
+ referenced by this value and the device using that IP address may each
+ actually have any number of such "canonical" hostnames. See the POSIX
+ getaddrinfo spec <http://www.opengroup.org/susv3xsh/getaddrinfo.html">,
+ RFC 1034 <http://www.faqs.org/rfcs/rfc1034.html>, & RFC 2181
+ <http://www.faqs.org/rfcs/rfc2181.html> for more on what this confusing
+ term really refers to. */
+char *
+canon_host_r (char const *host, int *cherror)
{
- int i;
- for (i = 1; i < argc; i++)
+ char *retval = NULL;
+ static struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ int status;
+
+ hints.ai_flags = AI_CANONNAME;
+ status = getaddrinfo (host, NULL, &hints, &res);
+ if (!status)
{
- char *s = canon_host (argv[i]);
- printf ("%s: %s\n", argv[i], (s ? s : "<undef>"));
+ retval = strdup (res->ai_canonname);
+ if (!retval && cherror)
+ *cherror = EAI_MEMORY;
+ freeaddrinfo (res);
}
- exit (0);
+ else if (cherror)
+ *cherror = status;
+
+ return retval;
+}
+
+/* Return a string describing the last error encountered by canon_host. */
+const char *
+ch_strerror (void)
+{
+ return gai_strerror (last_cherror);
}
-#endif /* TEST_CANON_HOST */
diff --git a/lib/getline.c b/lib/getline.c
index 5a7980ec9..ab054fba6 100644
--- a/lib/getline.c
+++ b/lib/getline.c
@@ -1,44 +1,32 @@
-/* getline.c -- Replacement for GNU C library function getline
+/* getline.c --- Implementation of replacement getline function.
+ Copyright (C) 2005 Free Software Foundation, Inc.
- Copyright (C) 1993, 1996, 1997, 1998, 2000, 2003, 2004 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 free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
-/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */
+/* Written by Simon Josefsson. */
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#include "getdelim.h"
#include "getline.h"
-#if ! (defined __GNU_LIBRARY__ && HAVE_GETDELIM)
-
-# include "getndelim2.h"
-
-ssize_t
-getdelim (char **lineptr, size_t *linesize, int delimiter, FILE *stream)
-{
- return getndelim2 (lineptr, linesize, 0, GETNLINE_NO_LIMIT, delimiter, EOF,
- stream);
-}
-#endif
-
ssize_t
-getline (char **lineptr, size_t *linesize, FILE *stream)
+getline (char **lineptr, size_t *n, FILE *stream)
{
- return getdelim (lineptr, linesize, '\n', stream);
+ return getdelim (lineptr, n, '\n', stream);
}
diff --git a/lib/getline.h b/lib/getline.h
index b58e93f4f..f0f61c4b2 100644
--- a/lib/getline.h
+++ b/lib/getline.h
@@ -1,39 +1,28 @@
-/* Replacement for GNU C library function getline
+/* getline.h --- Prototype for replacement getline function.
+ Copyright (C) 2005 Free Software Foundation, Inc.
- Copyright (C) 1995, 1997, 1999, 2000, 2001, 2002, 2003 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 free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-
-#ifndef GETLINE_H_
-# define GETLINE_H_ 1
+/* Written by Simon Josefsson. */
+/* Get size_t, FILE, ssize_t. And getline, if available. */
# include <stddef.h>
# include <stdio.h>
-
-/* Get ssize_t. */
# include <sys/types.h>
-/* glibc2 has these functions declared in <stdio.h>. Avoid redeclarations. */
-# if __GLIBC__ < 2
-
-extern ssize_t getline (char **_lineptr, size_t *_linesize, FILE *_stream);
-
-extern ssize_t getdelim (char **_lineptr, size_t *_linesize, int _delimiter,
- FILE *_stream);
-
-# endif
-
-#endif /* not GETLINE_H_ */
+#if !HAVE_DECL_GETLINE
+ssize_t getline (char **lineptr, size_t *n, FILE *stream);
+#endif /* !HAVE_GETLINE */
diff --git a/lib/getpass.c b/lib/getpass.c
index 7367251e2..f0b3184ee 100644
--- a/lib/getpass.c
+++ b/lib/getpass.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1992-2001, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1992-2001, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
@@ -15,47 +15,32 @@
with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#if !_LIBC
-# include "getpass.h"
-#endif
+#include "getpass.h"
-#if _LIBC
-# define HAVE_STDIO_EXT_H 1
-#endif
+#include <stdio.h>
+
+#if !defined _WIN32
#include <stdbool.h>
-#include <stdio.h>
#if HAVE_STDIO_EXT_H
# include <stdio_ext.h>
-#else
-# define __fsetlocking(stream, type) /* empty */
#endif
-#if !_LIBC
-# include "getline.h"
+#if !HAVE___FSETLOCKING
+# define __fsetlocking(stream, type) /* empty */
#endif
-#include <termios.h>
-#include <unistd.h>
-
-#if _LIBC
-# include <wchar.h>
+#if HAVE_TERMIOS_H
+# include <termios.h>
#endif
-#if _LIBC
-# define NOTCANCEL_MODE "c"
-#else
-# define NOTCANCEL_MODE
-#endif
+#include "getline.h"
-#if _LIBC
-# define flockfile(s) _IO_flockfile (s)
-# define funlockfile(s) _IO_funlockfile (s)
-#elif USE_UNLOCKED_IO
+#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#else
# if !HAVE_DECL_FFLUSH_UNLOCKED
@@ -80,18 +65,6 @@
# endif
#endif
-#if _LIBC
-# include <bits/libc-lock.h>
-#else
-# define __libc_cleanup_push(function, arg) /* empty */
-# define __libc_cleanup_pop(execute) /* empty */
-#endif
-
-#if !_LIBC
-# define __getline getline
-# define __tcgetattr tcgetattr
-#endif
-
/* It is desirable to use this bit on systems that have it.
The only bit of terminal state we want to twiddle is echoing, which is
done in software; there is no need to change the state of the terminal
@@ -114,7 +87,7 @@ getpass (const char *prompt)
FILE *tty;
FILE *in, *out;
struct termios s, t;
- bool tty_changed;
+ bool tty_changed = false;
static char *buf;
static size_t bufsize;
ssize_t nread;
@@ -122,7 +95,7 @@ getpass (const char *prompt)
/* Try to write to and read from the terminal if we can.
If we can't open the terminal, use stderr and stdin. */
- tty = fopen ("/dev/tty", "w+" NOTCANCEL_MODE);
+ tty = fopen ("/dev/tty", "w+");
if (tty == NULL)
{
in = stdin;
@@ -136,39 +109,26 @@ getpass (const char *prompt)
out = in = tty;
}
- /* Make sure the stream we opened is closed even if the thread is
- canceled. */
- __libc_cleanup_push (call_fclose, tty);
-
flockfile (out);
/* Turn echoing off if it is on now. */
-
- if (__tcgetattr (fileno (in), &t) == 0)
+#if HAVE_TCGETATTR
+ if (tcgetattr (fileno (in), &t) == 0)
{
/* Save the old one. */
s = t;
/* Tricky, tricky. */
- t.c_lflag &= ~(ECHO|ISIG);
- tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0);
+ t.c_lflag &= ~(ECHO | ISIG);
+ tty_changed = (tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &t) == 0);
}
- else
- tty_changed = false;
+#endif
/* Write the prompt. */
-#ifdef USE_IN_LIBIO
- if (_IO_fwide (out, 0) > 0)
- __fwprintf (out, L"%s", prompt);
- else
-#endif
- fputs_unlocked (prompt, out);
+ fputs_unlocked (prompt, out);
fflush_unlocked (out);
/* Read the password. */
- nread = __getline (&buf, &bufsize, in);
-
-#if !_LIBC
- /* As far as is known, glibc doesn't need this no-op fseek. */
+ nread = getline (&buf, &bufsize, in);
/* According to the C standard, input may not be followed by output
on the same stream without an intervening call to a file
@@ -180,7 +140,6 @@ getpass (const char *prompt)
from POSIX version to POSIX version, so play it safe and invoke
fseek even if in != out. */
fseek (out, 0, SEEK_CUR);
-#endif
if (buf != NULL)
{
@@ -193,25 +152,75 @@ getpass (const char *prompt)
if (tty_changed)
{
/* Write the newline that was not echoed. */
-#ifdef USE_IN_LIBIO
- if (_IO_fwide (out, 0) > 0)
- putwc_unlocked (L'\n', out);
- else
-#endif
- putc_unlocked ('\n', out);
+ putc_unlocked ('\n', out);
}
}
}
/* Restore the original setting. */
+#if HAVE_TCSETATTR
if (tty_changed)
- (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s);
+ tcsetattr (fileno (in), TCSAFLUSH | TCSASOFT, &s);
+#endif
funlockfile (out);
- __libc_cleanup_pop (0);
-
call_fclose (tty);
return buf;
}
+
+#else /* WIN32 */
+
+/* Windows implementation by Martin Lambers <marlam@marlam.de>,
+ improved by Simon Josefsson. */
+
+/* For PASS_MAX. */
+#include <limits.h>
+
+#ifndef PASS_MAX
+# define PASS_MAX 512
+#endif
+
+char *
+getpass (const char *prompt)
+{
+ char getpassbuf[PASS_MAX + 1];
+ size_t i = 0;
+ int c;
+
+ if (prompt)
+ {
+ fputs (prompt, stderr);
+ fflush (stderr);
+ }
+
+ for (;;)
+ {
+ c = _getch ();
+ if (c == '\r')
+ {
+ getpassbuf[i] = '\0';
+ break;
+ }
+ else if (i < PASS_MAX)
+ {
+ getpassbuf[i++] = c;
+ }
+
+ if (i >= PASS_MAX)
+ {
+ getpassbuf[i] = '\0';
+ break;
+ }
+ }
+
+ if (prompt)
+ {
+ fputs ("\r\n", stderr);
+ fflush (stderr);
+ }
+
+ return strdup (getpassbuf);
+}
+#endif
diff --git a/lib/strcasecmp.c b/lib/strcasecmp.c
index aa269c617..71f2eca7c 100644
--- a/lib/strcasecmp.c
+++ b/lib/strcasecmp.c
@@ -1,5 +1,7 @@
-/* strcasecmp.c -- case insensitive string comparator
- Copyright (C) 1998, 1999 Free Software Foundation, Inc.
+/* Case-insensitive string comparison function.
+ Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2005,
+ based on earlier glibc code.
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,52 +17,82 @@
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-#if HAVE_CONFIG_H
+#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#ifdef LENGTH_LIMIT
-# define STRXCASECMP_FUNCTION strncasecmp
-# define STRXCASECMP_DECLARE_N , size_t n
-# define LENGTH_LIMIT_EXPR(Expr) Expr
-#else
-# define STRXCASECMP_FUNCTION strcasecmp
-# define STRXCASECMP_DECLARE_N /* empty */
-# define LENGTH_LIMIT_EXPR(Expr) 0
-#endif
+/* Specification. */
+#include "strcase.h"
-#include <stddef.h>
#include <ctype.h>
-#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+#if HAVE_MBRTOWC
+# include "mbuiter.h"
+#endif
-/* Compare {{no more than N characters of }}strings S1 and S2,
- ignoring case, returning less than, equal to or
- greater than zero if S1 is lexicographically less
- than, equal to or greater than S2. */
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+/* Compare strings S1 and S2, ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less than, equal to or greater
+ than S2.
+ Note: This function may, in multibyte locales, return 0 for strings of
+ different lengths! */
int
-STRXCASECMP_FUNCTION (const char *s1, const char *s2 STRXCASECMP_DECLARE_N)
+strcasecmp (const char *s1, const char *s2)
{
- register const unsigned char *p1 = (const unsigned char *) s1;
- register const unsigned char *p2 = (const unsigned char *) s2;
- unsigned char c1, c2;
-
- if (p1 == p2 || LENGTH_LIMIT_EXPR (n == 0))
+ if (s1 == s2)
return 0;
- do
+ /* Be careful not to look at the entire extent of s1 or s2 until needed.
+ This is useful because when two strings differ, the difference is
+ most often already in the very few first characters. */
+#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1)
{
- c1 = TOLOWER (*p1);
- c2 = TOLOWER (*p2);
+ mbui_iterator_t iter1;
+ mbui_iterator_t iter2;
+
+ mbui_init (iter1, s1);
+ mbui_init (iter2, s2);
+
+ while (mbui_avail (iter1) && mbui_avail (iter2))
+ {
+ int cmp = mb_casecmp (mbui_cur (iter1), mbui_cur (iter2));
- if (LENGTH_LIMIT_EXPR (--n == 0) || c1 == '\0')
- break;
+ if (cmp != 0)
+ return cmp;
- ++p1;
- ++p2;
+ mbui_advance (iter1);
+ mbui_advance (iter2);
+ }
+ if (mbui_avail (iter1))
+ /* s2 terminated before s1. */
+ return 1;
+ if (mbui_avail (iter2))
+ /* s1 terminated before s2. */
+ return -1;
+ return 0;
}
- while (c1 == c2);
+ else
+#endif
+ {
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ do
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
- return c1 - c2;
+ if (c1 == '\0')
+ break;
+
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ return c1 - c2;
+ }
}
diff --git a/lib/strncasecmp.c b/lib/strncasecmp.c
index 68d95aacc..72ead013b 100644
--- a/lib/strncasecmp.c
+++ b/lib/strncasecmp.c
@@ -1,2 +1,58 @@
-#define LENGTH_LIMIT
-#include "strcasecmp.c"
+/* strncasecmp.c -- case insensitive string comparator
+ Copyright (C) 1998, 1999 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "strcase.h"
+
+#include <ctype.h>
+
+#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))
+
+/* Compare no more than N bytes of strings S1 and S2,
+ ignoring case, returning less than, equal to or
+ greater than zero if S1 is lexicographically less
+ than, equal to or greater than S2. */
+
+int
+strncasecmp (const char *s1, const char *s2, size_t n)
+{
+ register const unsigned char *p1 = (const unsigned char *) s1;
+ register const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+
+ if (p1 == p2 || n == 0)
+ return 0;
+
+ do
+ {
+ c1 = TOLOWER (*p1);
+ c2 = TOLOWER (*p2);
+
+ if (--n == 0 || c1 == '\0')
+ break;
+
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ return c1 - c2;
+}
diff --git a/lib/strstr.c b/lib/strstr.c
index 8f82b4589..e94cef756 100644
--- a/lib/strstr.c
+++ b/lib/strstr.c
@@ -1,119 +1,128 @@
-/* Copyright (C) 1994, 1999, 2002-2003 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
-
-/*
- * My personal strstr() implementation that beats most other algorithms.
- * Until someone tells me otherwise, I assume that this is the
- * fastest implementation of strstr() in C.
- * I deliberately chose not to comment it. You should have at least
- * as much fun trying to understand it, as I had to write it :-).
- *
- * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
-
-#if HAVE_CONFIG_H
+/* Searching in a string.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2005.
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include <string.h>
+/* Specification. */
+#include "strstr.h"
-typedef unsigned chartype;
+#include <stddef.h> /* for NULL */
-#undef strstr
+#if HAVE_MBRTOWC
+# include "mbuiter.h"
+#endif
+/* Find the first occurrence of NEEDLE in HAYSTACK. */
char *
-strstr (const char *phaystack, const char *pneedle)
+strstr (const char *haystack, const char *needle)
{
- register const unsigned char *haystack, *needle;
- register chartype b, c;
+ /* Be careful not to look at the entire extent of haystack or needle
+ until needed. This is useful because of these two cases:
+ - haystack may be very long, and a match of needle found early,
+ - needle may be very long, and not even a short initial segment of
+ needle may be found in haystack. */
+#if HAVE_MBRTOWC
+ if (MB_CUR_MAX > 1)
+ {
+ mbui_iterator_t iter_needle;
- haystack = (const unsigned char *) phaystack;
- needle = (const unsigned char *) pneedle;
+ mbui_init (iter_needle, needle);
+ if (mbui_avail (iter_needle))
+ {
+ mbui_iterator_t iter_haystack;
- b = *needle;
- if (b != '\0')
+ mbui_init (iter_haystack, haystack);
+ for (;; mbui_advance (iter_haystack))
+ {
+ if (!mbui_avail (iter_haystack))
+ /* No match. */
+ return NULL;
+
+ if (mb_equal (mbui_cur (iter_haystack), mbui_cur (iter_needle)))
+ /* The first character matches. */
+ {
+ mbui_iterator_t rhaystack;
+ mbui_iterator_t rneedle;
+
+ memcpy (&rhaystack, &iter_haystack, sizeof (mbui_iterator_t));
+ mbui_advance (rhaystack);
+
+ mbui_init (rneedle, needle);
+ if (!mbui_avail (rneedle))
+ abort ();
+ mbui_advance (rneedle);
+
+ for (;; mbui_advance (rhaystack), mbui_advance (rneedle))
+ {
+ if (!mbui_avail (rneedle))
+ /* Found a match. */
+ return (char *) mbui_cur_ptr (iter_haystack);
+ if (!mbui_avail (rhaystack))
+ /* No match. */
+ return NULL;
+ if (!mb_equal (mbui_cur (rhaystack), mbui_cur (rneedle)))
+ /* Nothing in this round. */
+ break;
+ }
+ }
+ }
+ }
+ else
+ return (char *) haystack;
+ }
+ else
+#endif
{
- haystack--; /* possible ANSI violation */
- do
+ if (*needle != '\0')
{
- c = *++haystack;
- if (c == '\0')
- goto ret0;
- }
- while (c != b);
+ /* Speed up the following searches of needle by caching its first
+ character. */
+ char b = *needle++;
- c = *++needle;
- if (c == '\0')
- goto foundneedle;
- ++needle;
- goto jin;
-
- for (;;)
- {
- register chartype a;
- register const unsigned char *rhaystack, *rneedle;
-
- do
+ for (;; haystack++)
{
- a = *++haystack;
- if (a == '\0')
- goto ret0;
- if (a == b)
- break;
- a = *++haystack;
- if (a == '\0')
- goto ret0;
-shloop:; }
- while (a != b);
-
-jin: a = *++haystack;
- if (a == '\0')
- goto ret0;
-
- if (a != c)
- goto shloop;
-
- rhaystack = haystack-- + 1;
- rneedle = needle;
- a = *rneedle;
-
- if (*rhaystack == a)
- do
- {
- if (a == '\0')
- goto foundneedle;
- ++rhaystack;
- a = *++needle;
- if (*rhaystack != a)
- break;
- if (a == '\0')
- goto foundneedle;
- ++rhaystack;
- a = *++needle;
- }
- while (*rhaystack == a);
-
- needle = rneedle; /* took the register-poor approach */
-
- if (a == '\0')
- break;
- }
+ if (*haystack == '\0')
+ /* No match. */
+ return NULL;
+ if (*haystack == b)
+ /* The first character matches. */
+ {
+ const char *rhaystack = haystack + 1;
+ const char *rneedle = needle;
+
+ for (;; rhaystack++, rneedle++)
+ {
+ if (*rneedle == '\0')
+ /* Found a match. */
+ return (char *) haystack;
+ if (*rhaystack == '\0')
+ /* No match. */
+ return NULL;
+ if (*rhaystack != *rneedle)
+ /* Nothing in this round. */
+ break;
+ }
+ }
+ }
+ }
+ else
+ return (char *) haystack;
}
-foundneedle:
- return (char*) haystack;
-ret0:
- return 0;
}
diff --git a/m4/canon-host.m4 b/m4/canon-host.m4
index 1e1275ab3..b41610471 100644
--- a/m4/canon-host.m4
+++ b/m4/canon-host.m4
@@ -1,4 +1,4 @@
-# canon-host.m4 serial 6
+# canon-host.m4 serial 7
dnl Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -6,18 +6,11 @@ dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_CANON_HOST],
[
- AC_LIBSOURCES([canon-host.c])
+ AC_LIBSOURCES([canon-host.c, canon-host.h])
AC_LIBOBJ([canon-host])
+ gl_PREREQ_CANON_HOST
+])
- dnl Prerequisites of lib/canon-host.c.
- AC_CHECK_HEADERS_ONCE(unistd.h)
- AC_CHECK_HEADERS(netdb.h sys/socket.h netinet/in.h arpa/inet.h)
-
- dnl Add any libraries as early as possible.
- dnl In particular, inet_ntoa needs -lnsl at least on Solaris 2.5.1,
- dnl so we have to add -lnsl to LIBS before checking for that function.
- AC_SEARCH_LIBS(gethostbyname, [inet nsl])
-
- dnl These come from -lnsl on Solaris 2.5.1.
- AC_CHECK_FUNCS(getaddrinfo gethostbyname gethostbyaddr inet_ntoa)
+AC_DEFUN([gl_PREREQ_CANON_HOST], [
+ AC_REQUIRE([gl_GETADDRINFO])
])
diff --git a/m4/getline.m4 b/m4/getline.m4
index 983f26146..ff255a366 100644
--- a/m4/getline.m4
+++ b/m4/getline.m4
@@ -1,4 +1,4 @@
-# getline.m4 serial 12
+# getline.m4 serial 13
dnl Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free Software
dnl Foundation, Inc.
@@ -13,19 +13,21 @@ dnl See if there's a working, system-supplied version of the getline function.
dnl We can't just do AC_REPLACE_FUNCS(getline) because some systems
dnl have a function by that name in -linet that doesn't have anything
dnl to do with the function we need.
-AC_DEFUN([AM_FUNC_GETLINE],
+AC_DEFUN([gl_FUNC_GETLINE],
[
AC_LIBSOURCES([getline.c, getline.h])
- dnl Persuade glibc <stdio.h> to declare getline() and getdelim().
+ dnl Persuade glibc <stdio.h> to declare getline().
AC_REQUIRE([AC_GNU_SOURCE])
- am_getline_needs_run_time_check=no
+ AC_CHECK_DECLS([getline])
+
+ gl_getline_needs_run_time_check=no
AC_CHECK_FUNC(getline,
dnl Found it in some library. Verify that it works.
- am_getline_needs_run_time_check=yes,
+ gl_getline_needs_run_time_check=yes,
am_cv_func_working_getline=no)
- if test $am_getline_needs_run_time_check = yes; then
+ if test $gl_getline_needs_run_time_check = yes; then
AC_CACHE_CHECK([for working getline function], am_cv_func_working_getline,
[echo fooN |tr -d '\012'|tr N '\012' > conftest.data
AC_TRY_RUN([
@@ -57,20 +59,12 @@ AC_DEFUN([AM_FUNC_GETLINE],
[Define to a replacement function name for getline().])
AC_LIBOBJ(getline)
- # Avoid multiple inclusions of getndelim2.o into LIBOBJS.
- # This hack won't be needed after gnulib requires Autoconf 2.58 or later.
- case " $LIB@&t@OBJS " in
- *" getndelim2.$ac_objext "* ) ;;
- *) AC_LIBOBJ(getndelim2);;
- esac
-
gl_PREREQ_GETLINE
- gl_PREREQ_GETNDELIM2
fi
])
# Prerequisites of lib/getline.c.
AC_DEFUN([gl_PREREQ_GETLINE],
[
- AC_CHECK_FUNCS(getdelim)
+ gl_FUNC_GETDELIM
])
diff --git a/m4/mbrtowc.m4 b/m4/mbrtowc.m4
index 2eee1a64f..a3bd9114c 100644
--- a/m4/mbrtowc.m4
+++ b/m4/mbrtowc.m4
@@ -1,5 +1,5 @@
-# mbrtowc.m4 serial 7
-dnl Copyright (C) 2001-2002, 2004 Free Software Foundation, Inc.
+# mbrtowc.m4 serial 8
+dnl Copyright (C) 2001-2002, 2004-2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
@@ -7,19 +7,25 @@ dnl with or without modifications, as long as this notice is preserved.
dnl From Paul Eggert
dnl This file can be removed, and gl_FUNC_MBRTOWC replaced with
-dnl AC_FUNC_MBRTOWC, when autoconf 2.57 can be assumed everywhere.
+dnl AC_FUNC_MBRTOWC, when autoconf 2.60 can be assumed everywhere.
AC_DEFUN([gl_FUNC_MBRTOWC],
[
+ dnl Same as AC_FUNC_MBRTOWC in autoconf-2.60.
AC_CACHE_CHECK([whether mbrtowc and mbstate_t are properly declared],
gl_cv_func_mbrtowc,
- [AC_TRY_LINK(
- [#include <wchar.h>],
- [mbstate_t state; return ! (sizeof state && mbrtowc);],
+ [AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <wchar.h>]],
+ [[wchar_t wc;
+ char const s[] = "";
+ size_t n = 1;
+ mbstate_t state;
+ return ! (sizeof state && (mbrtowc) (&wc, s, n, &state));]])],
gl_cv_func_mbrtowc=yes,
gl_cv_func_mbrtowc=no)])
if test $gl_cv_func_mbrtowc = yes; then
- AC_DEFINE(HAVE_MBRTOWC, 1,
+ AC_DEFINE([HAVE_MBRTOWC], 1,
[Define to 1 if mbrtowc and mbstate_t are properly declared.])
fi
])
diff --git a/m4/strcase.m4 b/m4/strcase.m4
index 40ace46a7..8a8ff3a45 100644
--- a/m4/strcase.m4
+++ b/m4/strcase.m4
@@ -1,5 +1,5 @@
-# strcase.m4 serial 1
-dnl Copyright (C) 2002 Free Software Foundation, Inc.
+# strcase.m4 serial 2
+dnl Copyright (C) 2002, 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
@@ -12,10 +12,11 @@ AC_DEFUN([gl_STRCASE],
AC_DEFUN([gl_FUNC_STRCASECMP],
[
- AC_REPLACE_FUNCS(strcasecmp)
- if test $ac_cv_func_strcasecmp = no; then
- gl_PREREQ_STRCASECMP
- fi
+ dnl No known system has a strcasecmp() function that works correctly in
+ dnl multibyte locales. Therefore we use our version always.
+ AC_LIBOBJ(strcasecmp)
+ AC_DEFINE(strcasecmp, rpl_strcasecmp, [Define to rpl_strcasecmp always.])
+ gl_PREREQ_STRCASECMP
])
AC_DEFUN([gl_FUNC_STRNCASECMP],
@@ -28,7 +29,7 @@ AC_DEFUN([gl_FUNC_STRNCASECMP],
# Prerequisites of lib/strcasecmp.c.
AC_DEFUN([gl_PREREQ_STRCASECMP], [
- :
+ gl_FUNC_MBRTOWC
])
# Prerequisites of lib/strncasecmp.c.
diff --git a/m4/strstr.m4 b/m4/strstr.m4
index 0fe0f73cd..aea809ebd 100644
--- a/m4/strstr.m4
+++ b/m4/strstr.m4
@@ -1,16 +1,18 @@
-# strstr.m4 serial 2
-dnl Copyright (C) 2002-2003 Free Software Foundation, Inc.
+# strstr.m4 serial 4
+dnl Copyright (C) 2002-2003, 2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
AC_DEFUN([gl_FUNC_STRSTR],
[
- AC_REPLACE_FUNCS(strstr)
- if test $ac_cv_func_strstr = no; then
- gl_PREREQ_STRSTR
- fi
+ dnl No known system has a strstr() function that works correctly in
+ dnl multibyte locales. Therefore we use our version always.
+ AC_LIBOBJ(strstr)
+ gl_PREREQ_STRSTR
])
# Prerequisites of lib/strstr.c.
-AC_DEFUN([gl_PREREQ_STRSTR], [:])
+AC_DEFUN([gl_PREREQ_STRSTR], [
+ gl_FUNC_MBRTOWC
+])