mirror of
https://github.com/coreutils/coreutils.git
synced 2025-01-21 15:43:30 +08:00
New file, from gnulib.
This commit is contained in:
parent
0ed6bb9a65
commit
3833e2bc34
30
lib/canon-host.h
Normal file
30
lib/canon-host.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* Host name canonicalization
|
||||
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
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. */
|
||||
|
||||
#ifndef CANON_HOST_H
|
||||
# define CANON_HOST_H 1
|
||||
|
||||
char *canon_host (char const *host);
|
||||
char *canon_host_r (char const *host, int *cherror);
|
||||
|
||||
const char *ch_strerror (void);
|
||||
# define ch_strerror_r(cherror) gai_strerror (cherror);
|
||||
|
||||
#endif /* !CANON_HOST_H */
|
78
lib/gai_strerror.c
Normal file
78
lib/gai_strerror.c
Normal file
@ -0,0 +1,78 @@
|
||||
/* Copyright (C) 1997, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Philip Blundell <pjb27@cam.ac.uk>, 1997.
|
||||
|
||||
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
|
||||
|
||||
#ifndef _LIBC
|
||||
# include "getaddrinfo.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# include "gettext.h"
|
||||
# define _(String) gettext (String)
|
||||
# define N_(String) String
|
||||
#endif
|
||||
|
||||
static struct
|
||||
{
|
||||
int code;
|
||||
const char *msg;
|
||||
}
|
||||
values[] =
|
||||
{
|
||||
{ EAI_ADDRFAMILY, N_("Address family for hostname not supported") },
|
||||
{ EAI_AGAIN, N_("Temporary failure in name resolution") },
|
||||
{ EAI_BADFLAGS, N_("Bad value for ai_flags") },
|
||||
{ EAI_FAIL, N_("Non-recoverable failure in name resolution") },
|
||||
{ EAI_FAMILY, N_("ai_family not supported") },
|
||||
{ EAI_MEMORY, N_("Memory allocation failure") },
|
||||
{ EAI_NODATA, N_("No address associated with hostname") },
|
||||
{ EAI_NONAME, N_("Name or service not known") },
|
||||
{ EAI_SERVICE, N_("Servname not supported for ai_socktype") },
|
||||
{ EAI_SOCKTYPE, N_("ai_socktype not supported") },
|
||||
{ EAI_SYSTEM, N_("System error") },
|
||||
#ifdef __USE_GNU
|
||||
{ EAI_INPROGRESS, N_("Processing request in progress") },
|
||||
{ EAI_CANCELED, N_("Request canceled") },
|
||||
{ EAI_NOTCANCELED, N_("Request not canceled") },
|
||||
{ EAI_ALLDONE, N_("All requests done") },
|
||||
{ EAI_INTR, N_("Interrupted by a signal") },
|
||||
{ EAI_IDN_ENCODE, N_("Parameter string not correctly encoded") }
|
||||
#endif
|
||||
};
|
||||
|
||||
const char *
|
||||
gai_strerror (int code)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i)
|
||||
if (values[i].code == code)
|
||||
return _(values[i].msg);
|
||||
|
||||
return _("Unknown error");
|
||||
}
|
||||
#ifdef _LIBC
|
||||
libc_hidden_def (gai_strerror)
|
||||
#endif
|
210
lib/getaddrinfo.c
Normal file
210
lib/getaddrinfo.c
Normal file
@ -0,0 +1,210 @@
|
||||
/* Get address information (partial implementation).
|
||||
Copyright (C) 1997, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
|
||||
Contributed by Simon Josefsson <simon@josefsson.org>.
|
||||
|
||||
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 "getaddrinfo.h"
|
||||
|
||||
/* Get calloc. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Get memcpy. */
|
||||
#include <string.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "gettext.h"
|
||||
#define _(String) gettext (String)
|
||||
#define N_(String) String
|
||||
|
||||
#include "strdup.h"
|
||||
|
||||
static inline bool
|
||||
validate_family (int family)
|
||||
{
|
||||
/* FIXME: Support more families. */
|
||||
#if HAVE_IPV4
|
||||
if (family == PF_INET)
|
||||
return true;
|
||||
#endif
|
||||
#if HAVE_IPV6
|
||||
if (family == PF_INET6)
|
||||
return true;
|
||||
#endif
|
||||
if (family == PF_UNSPEC)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Translate name of a service location and/or a service name to set of
|
||||
socket addresses. */
|
||||
int
|
||||
getaddrinfo (const char *restrict nodename,
|
||||
const char *restrict servname,
|
||||
const struct addrinfo *restrict hints,
|
||||
struct addrinfo **restrict res)
|
||||
{
|
||||
struct addrinfo *tmp;
|
||||
struct servent *se;
|
||||
struct hostent *he;
|
||||
size_t sinlen;
|
||||
|
||||
if (hints && (hints->ai_flags & ~AI_CANONNAME))
|
||||
/* FIXME: Support more flags. */
|
||||
return EAI_BADFLAGS;
|
||||
|
||||
if (hints && !validate_family (hints->ai_family))
|
||||
return EAI_FAMILY;
|
||||
|
||||
if (hints &&
|
||||
hints->ai_socktype != SOCK_STREAM && hints->ai_socktype != SOCK_DGRAM)
|
||||
/* FIXME: Support other socktype. */
|
||||
return EAI_SOCKTYPE; /* FIXME: Better return code? */
|
||||
|
||||
if (!nodename)
|
||||
/* FIXME: Support server bind mode. */
|
||||
return EAI_NONAME;
|
||||
|
||||
if (servname)
|
||||
{
|
||||
const char *proto =
|
||||
(hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
|
||||
|
||||
/* FIXME: Use getservbyname_r if available. */
|
||||
se = getservbyname (servname, proto);
|
||||
|
||||
if (!se)
|
||||
return EAI_SERVICE;
|
||||
}
|
||||
|
||||
/* FIXME: Use gethostbyname_r if available. */
|
||||
he = gethostbyname (nodename);
|
||||
if (!he || he->h_addr_list[0] == NULL)
|
||||
return EAI_NONAME;
|
||||
|
||||
switch (he->h_addrtype)
|
||||
{
|
||||
#if HAVE_IPV6
|
||||
case PF_INET6:
|
||||
sinlen = sizeof (struct sockaddr_in6);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAVE_IPV4
|
||||
case PF_INET:
|
||||
sinlen = sizeof (struct sockaddr_in);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return EAI_NODATA;
|
||||
}
|
||||
|
||||
tmp = calloc (1, sizeof (*tmp) + sinlen);
|
||||
if (!tmp)
|
||||
return EAI_MEMORY;
|
||||
|
||||
switch (he->h_addrtype)
|
||||
{
|
||||
#if HAVE_IPV6
|
||||
case PF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sinp = (char *) tmp + sizeof (*tmp);
|
||||
|
||||
if (se)
|
||||
sinp->sin6_port = se->s_port;
|
||||
|
||||
if (he->h_length != sizeof (sinp->sin6_addr))
|
||||
return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */
|
||||
|
||||
memcpy (&sinp->sin6_addr, he->h_addr_list[0], he->h_length);
|
||||
|
||||
tmp->ai_addr = (struct sockaddr *) sinp;
|
||||
tmp->ai_addrlen = sinlen;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAVE_IPV4
|
||||
case PF_INET:
|
||||
{
|
||||
struct sockaddr_in *sinp = (char *) tmp + sizeof (*tmp);
|
||||
|
||||
if (se)
|
||||
sinp->sin_port = se->s_port;
|
||||
|
||||
if (he->h_length != sizeof (sinp->sin_addr))
|
||||
return EAI_SYSTEM; /* FIXME: Better return code? Set errno? */
|
||||
|
||||
memcpy (&sinp->sin_addr, he->h_addr_list[0], he->h_length);
|
||||
|
||||
tmp->ai_addr = (struct sockaddr *) sinp;
|
||||
tmp->ai_addrlen = sinlen;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
free (tmp);
|
||||
return EAI_NODATA;
|
||||
}
|
||||
|
||||
if (hints && hints->ai_flags & AI_CANONNAME)
|
||||
{
|
||||
const char *cn;
|
||||
if (he->h_name)
|
||||
cn = he->h_name;
|
||||
else
|
||||
cn = nodename;
|
||||
|
||||
tmp->ai_canonname = strdup (cn);
|
||||
if (!tmp->ai_canonname)
|
||||
{
|
||||
free (tmp);
|
||||
return EAI_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
tmp->ai_protocol = (hints) ? hints->ai_protocol : 0;
|
||||
tmp->ai_socktype = (hints) ? hints->ai_socktype : 0;
|
||||
tmp->ai_addr->sa_family = he->h_addrtype;
|
||||
|
||||
/* FIXME: If more than one address, create linked list of addrinfo's. */
|
||||
|
||||
*res = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free `addrinfo' structure AI including associated storage. */
|
||||
void
|
||||
freeaddrinfo (struct addrinfo *ai)
|
||||
{
|
||||
while (ai)
|
||||
{
|
||||
struct addrinfo *cur;
|
||||
|
||||
cur = ai;
|
||||
ai = ai->ai_next;
|
||||
|
||||
if (cur->ai_canonname) free (cur->ai_canonname);
|
||||
free (cur);
|
||||
}
|
||||
}
|
95
lib/getaddrinfo.h
Normal file
95
lib/getaddrinfo.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* Get address information.
|
||||
Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Contributed by Simon Josefsson <simon@josefsson.org>.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef GETADDRINFO_H
|
||||
# define GETADDRINFO_H
|
||||
|
||||
/* Get getaddrinfo declarations, if available. Also get 'socklen_t',
|
||||
and 'struct sockaddr' via sys/types.h which are used below. */
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netdb.h>
|
||||
|
||||
# if !HAVE_GETADDRINFO
|
||||
|
||||
/* Structure to contain information about address of a service provider. */
|
||||
struct addrinfo
|
||||
{
|
||||
int ai_flags; /* Input flags. */
|
||||
int ai_family; /* Protocol family for socket. */
|
||||
int ai_socktype; /* Socket type. */
|
||||
int ai_protocol; /* Protocol for socket. */
|
||||
socklen_t ai_addrlen; /* Length of socket address. */
|
||||
struct sockaddr *ai_addr; /* Socket address for socket. */
|
||||
char *ai_canonname; /* Canonical name for service location. */
|
||||
struct addrinfo *ai_next; /* Pointer to next in list. */
|
||||
};
|
||||
|
||||
/* Possible values for `ai_flags' field in `addrinfo' structure. */
|
||||
# define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */
|
||||
# define AI_CANONNAME 0x0002 /* Request for canonical name. */
|
||||
# define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */
|
||||
# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */
|
||||
# define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */
|
||||
# define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose
|
||||
returned address type.. */
|
||||
|
||||
/* Error values for `getaddrinfo' function. */
|
||||
# define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */
|
||||
# define EAI_NONAME -2 /* NAME or SERVICE is unknown. */
|
||||
# define EAI_AGAIN -3 /* Temporary failure in name resolution. */
|
||||
# define EAI_FAIL -4 /* Non-recoverable failure in name res. */
|
||||
# define EAI_NODATA -5 /* No address associated with NAME. */
|
||||
# define EAI_FAMILY -6 /* `ai_family' not supported. */
|
||||
# define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */
|
||||
# define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */
|
||||
# define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */
|
||||
# define EAI_MEMORY -10 /* Memory allocation failure. */
|
||||
# define EAI_SYSTEM -11 /* System error returned in `errno'. */
|
||||
# define EAI_OVERFLOW -12 /* Argument buffer overflow. */
|
||||
# ifdef __USE_GNU
|
||||
# define EAI_INPROGRESS -100 /* Processing request in progress. */
|
||||
# define EAI_CANCELED -101 /* Request canceled. */
|
||||
# define EAI_NOTCANCELED -102 /* Request not canceled. */
|
||||
# define EAI_ALLDONE -103 /* All requests done. */
|
||||
# define EAI_INTR -104 /* Interrupted by a signal. */
|
||||
# define EAI_IDN_ENCODE -105 /* IDN encoding failed. */
|
||||
# endif
|
||||
|
||||
/* Translate name of a service location and/or a service name to set of
|
||||
socket addresses.
|
||||
For more details, see the POSIX:2001 specification
|
||||
<http://www.opengroup.org/susv3xsh/getaddrinfo.html>. */
|
||||
extern int getaddrinfo (const char *restrict nodename,
|
||||
const char *restrict servname,
|
||||
const struct addrinfo *restrict hints,
|
||||
struct addrinfo **restrict res);
|
||||
|
||||
/* Free `addrinfo' structure AI including associated storage.
|
||||
For more details, see the POSIX:2001 specification
|
||||
<http://www.opengroup.org/susv3xsh/getaddrinfo.html>. */
|
||||
extern void freeaddrinfo (struct addrinfo *ai);
|
||||
|
||||
/* Convert error return from getaddrinfo() to a string.
|
||||
For more details, see the POSIX:2001 specification
|
||||
<http://www.opengroup.org/susv3xsh/gai_strerror.html>. */
|
||||
extern const char *gai_strerror (int ecode);
|
||||
|
||||
# endif /* !HAVE_GETADDRINFO */
|
||||
|
||||
#endif /* GETADDRINFO_H */
|
119
lib/getdelim.c
Normal file
119
lib/getdelim.c
Normal file
@ -0,0 +1,119 @@
|
||||
/* getdelim.c --- Implementation of replacement getdelim function.
|
||||
Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005 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. */
|
||||
|
||||
/* Ported from glibc by Simon Josefsson. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "getdelim.h"
|
||||
|
||||
#if !HAVE_FLOCKFILE
|
||||
# undef flockfile
|
||||
# define flockfile(x) ((void) 0)
|
||||
#endif
|
||||
#if !HAVE_FUNLOCKFILE
|
||||
# undef funlockfile
|
||||
# define funlockfile(x) ((void) 0)
|
||||
#endif
|
||||
|
||||
/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and
|
||||
NUL-terminate it). *LINEPTR is a pointer returned from malloc (or
|
||||
NULL), pointing to *N characters of space. It is realloc'ed as
|
||||
necessary. Returns the number of characters read (not including
|
||||
the null terminator), or -1 on error or EOF. */
|
||||
|
||||
ssize_t
|
||||
getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp)
|
||||
{
|
||||
int result = 0;
|
||||
ssize_t cur_len = 0;
|
||||
ssize_t len;
|
||||
|
||||
if (lineptr == NULL || n == NULL || fp == NULL)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
flockfile (fp);
|
||||
|
||||
if (*lineptr == NULL || *n == 0)
|
||||
{
|
||||
*n = 120;
|
||||
*lineptr = (char *) malloc (*n);
|
||||
if (*lineptr == NULL)
|
||||
{
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char *t;
|
||||
int i;
|
||||
|
||||
i = getc (fp);
|
||||
if (i == EOF)
|
||||
{
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make enough space for len+1 (for final NUL) bytes. */
|
||||
if (cur_len + 1 >= *n)
|
||||
{
|
||||
size_t needed = 2 * (cur_len + 1) + 1; /* Be generous. */
|
||||
char *new_lineptr;
|
||||
|
||||
if (needed < cur_len)
|
||||
{
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
new_lineptr = (char *) realloc (*lineptr, needed);
|
||||
if (new_lineptr == NULL)
|
||||
{
|
||||
result = -1;
|
||||
goto unlock_return;
|
||||
}
|
||||
|
||||
*lineptr = new_lineptr;
|
||||
*n = needed;
|
||||
}
|
||||
|
||||
(*lineptr)[cur_len] = i;
|
||||
cur_len++;
|
||||
|
||||
if (i == delimiter)
|
||||
break;
|
||||
}
|
||||
(*lineptr)[cur_len] = '\0';
|
||||
result = cur_len ? cur_len : result;
|
||||
|
||||
unlock_return:
|
||||
funlockfile (fp);
|
||||
return result;
|
||||
}
|
28
lib/getdelim.h
Normal file
28
lib/getdelim.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* getdelim.h --- Prototype for replacement getdelim function.
|
||||
Copyright (C) 2005 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. */
|
||||
|
||||
/* Written by Simon Josefsson. */
|
||||
|
||||
/* Get size_t, FILE, ssize_t. And getdelim, if available. */
|
||||
# include <stddef.h>
|
||||
# include <stdio.h>
|
||||
# include <sys/types.h>
|
||||
|
||||
#if !HAVE_DECL_GETDELIM
|
||||
ssize_t getdelim (char **lineptr, size_t *n, int delimiter, FILE *stream);
|
||||
#endif /* !HAVE_GETDELIM */
|
38
lib/mbchar.c
Normal file
38
lib/mbchar.c
Normal file
@ -0,0 +1,38 @@
|
||||
/* Copyright (C) 2001 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. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "mbchar.h"
|
||||
|
||||
#if IS_BASIC_ASCII
|
||||
|
||||
/* Bit table of characters in the ISO C "basic character set". */
|
||||
unsigned int is_basic_table [UCHAR_MAX / 32 + 1] =
|
||||
{
|
||||
0x00001a00, /* '\t' '\v' '\f' */
|
||||
0xffffffef, /* ' '...'#' '%'...'?' */
|
||||
0xfffffffe, /* 'A'...'Z' '[' '\\' ']' '^' '_' */
|
||||
0x7ffffffe /* 'a'...'z' '{' '|' '}' '~' */
|
||||
/* The remaining bits are 0. */
|
||||
};
|
||||
|
||||
#endif /* IS_BASIC_ASCII */
|
352
lib/mbchar.h
Normal file
352
lib/mbchar.h
Normal file
@ -0,0 +1,352 @@
|
||||
/* Multibyte character data type.
|
||||
Copyright (C) 2001, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Bruno Haible <bruno@clisp.org>. */
|
||||
|
||||
/* A multibyte character is a short subsequence of a char* string,
|
||||
representing a single wide character.
|
||||
|
||||
We use multibyte characters instead of wide characters because of
|
||||
the following goals:
|
||||
1) correct multibyte handling, i.e. operate according to the LC_CTYPE
|
||||
locale,
|
||||
2) ease of maintenance, i.e. the maintainer needs not know all details
|
||||
of the ISO C 99 standard,
|
||||
3) don't fail grossly if the input is not in the encoding set by the
|
||||
locale, because often different encodings are in use in the same
|
||||
countries (ISO-8859-1/UTF-8, EUC-JP/Shift_JIS, ...),
|
||||
4) fast in the case of ASCII characters,
|
||||
5) portability, i.e. don't make unportable assumptions about wchar_t.
|
||||
|
||||
Multibyte characters are only accessed through the mb* macros.
|
||||
|
||||
mb_ptr (mbc)
|
||||
return a pointer to the beginning of the multibyte sequence.
|
||||
|
||||
mb_len (mbc)
|
||||
returns the number of bytes occupied by the multibyte sequence.
|
||||
Always > 0.
|
||||
|
||||
mb_iseq (mbc, sc)
|
||||
returns true if mbc is the standard ASCII character sc.
|
||||
|
||||
mb_isnul (mbc)
|
||||
returns true if mbc is the nul character.
|
||||
|
||||
mb_cmp (mbc1, mbc2)
|
||||
returns a positive, zero, or negative value depending on whether mbc1
|
||||
sorts after, same or before mbc2.
|
||||
|
||||
mb_casecmp (mbc1, mbc2)
|
||||
returns a positive, zero, or negative value depending on whether mbc1
|
||||
sorts after, same or before mbc2, modulo upper/lowercase conversion.
|
||||
|
||||
mb_equal (mbc1, mbc2)
|
||||
returns true if mbc1 and mbc2 are equal.
|
||||
|
||||
mb_caseequal (mbc1, mbc2)
|
||||
returns true if mbc1 and mbc2 are equal modulo upper/lowercase conversion.
|
||||
|
||||
mb_isalnum (mbc)
|
||||
returns true if mbc is alphanumeric.
|
||||
|
||||
mb_isalpha (mbc)
|
||||
returns true if mbc is alphabetic.
|
||||
|
||||
mb_isascii(mbc)
|
||||
returns true if mbc is plain ASCII.
|
||||
|
||||
mb_isblank (mbc)
|
||||
returns true if mbc is a blank.
|
||||
|
||||
mb_iscntrl (mbc)
|
||||
returns true if mbc is a control character.
|
||||
|
||||
mb_isdigit (mbc)
|
||||
returns true if mbc is a decimal digit.
|
||||
|
||||
mb_isgraph (mbc)
|
||||
returns true if mbc is a graphic character.
|
||||
|
||||
mb_islower (mbc)
|
||||
returns true if mbc is lowercase.
|
||||
|
||||
mb_isprint (mbc)
|
||||
returns true if mbc is a printable character.
|
||||
|
||||
mb_ispunct (mbc)
|
||||
returns true if mbc is a punctuation character.
|
||||
|
||||
mb_isspace (mbc)
|
||||
returns true if mbc is a space character.
|
||||
|
||||
mb_isupper (mbc)
|
||||
returns true if mbc is uppercase.
|
||||
|
||||
mb_isxdigit (mbc)
|
||||
returns true if mbc is a hexadecimal digit.
|
||||
|
||||
mb_width (mbc)
|
||||
returns the number of columns on the output device occupied by mbc.
|
||||
Always >= 0.
|
||||
|
||||
mb_putc (mbc, stream)
|
||||
outputs mbc on stream, a byte oriented FILE stream opened for output.
|
||||
|
||||
mb_setascii (&mbc, sc)
|
||||
assigns the standard ASCII character sc to mbc.
|
||||
|
||||
mb_copy (&destmbc, &srcmbc)
|
||||
copies srcmbc to destmbc.
|
||||
|
||||
Here are the function prototypes of the macros.
|
||||
|
||||
extern const char * mb_ptr (const mbchar_t mbc);
|
||||
extern size_t mb_len (const mbchar_t mbc);
|
||||
extern bool mb_iseq (const mbchar_t mbc, char sc);
|
||||
extern bool mb_isnul (const mbchar_t mbc);
|
||||
extern int mb_cmp (const mbchar_t mbc1, const mbchar_t mbc2);
|
||||
extern int mb_casecmp (const mbchar_t mbc1, const mbchar_t mbc2);
|
||||
extern bool mb_equal (const mbchar_t mbc1, const mbchar_t mbc2);
|
||||
extern bool mb_caseequal (const mbchar_t mbc1, const mbchar_t mbc2);
|
||||
extern bool mb_isalnum (const mbchar_t mbc);
|
||||
extern bool mb_isalpha (const mbchar_t mbc);
|
||||
extern bool mb_isascii (const mbchar_t mbc);
|
||||
extern bool mb_isblank (const mbchar_t mbc);
|
||||
extern bool mb_iscntrl (const mbchar_t mbc);
|
||||
extern bool mb_isdigit (const mbchar_t mbc);
|
||||
extern bool mb_isgraph (const mbchar_t mbc);
|
||||
extern bool mb_islower (const mbchar_t mbc);
|
||||
extern bool mb_isprint (const mbchar_t mbc);
|
||||
extern bool mb_ispunct (const mbchar_t mbc);
|
||||
extern bool mb_isspace (const mbchar_t mbc);
|
||||
extern bool mb_isupper (const mbchar_t mbc);
|
||||
extern bool mb_isxdigit (const mbchar_t mbc);
|
||||
extern int mb_width (const mbchar_t mbc);
|
||||
extern void mb_putc (const mbchar_t mbc, FILE *stream);
|
||||
extern void mb_setascii (mbchar_t *new, char sc);
|
||||
extern void mb_copy (mbchar_t *new, const mbchar_t *old);
|
||||
*/
|
||||
|
||||
#ifndef _MBCHAR_H
|
||||
#define _MBCHAR_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
|
||||
<wchar.h>.
|
||||
BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
|
||||
<wchar.h>. */
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <wctype.h>
|
||||
|
||||
#define MBCHAR_BUF_SIZE 24
|
||||
|
||||
struct mbchar
|
||||
{
|
||||
const char *ptr; /* pointer to current character */
|
||||
size_t bytes; /* number of bytes of current character, > 0 */
|
||||
bool wc_valid; /* true if wc is a valid wide character */
|
||||
wchar_t wc; /* if wc_valid: the current character */
|
||||
char buf[MBCHAR_BUF_SIZE]; /* room for the bytes, used for file input only */
|
||||
};
|
||||
|
||||
/* EOF (not a real character) is represented with bytes = 0 and
|
||||
wc_valid = false. */
|
||||
|
||||
typedef struct mbchar mbchar_t;
|
||||
|
||||
/* Access the current character. */
|
||||
#define mb_ptr(mbc) ((mbc).ptr)
|
||||
#define mb_len(mbc) ((mbc).bytes)
|
||||
|
||||
/* Comparison of characters. */
|
||||
#define mb_iseq(mbc, sc) ((mbc).wc_valid && (mbc).wc == (sc))
|
||||
#define mb_isnul(mbc) ((mbc).wc_valid && (mbc).wc == 0)
|
||||
#define mb_cmp(mbc1, mbc2) \
|
||||
((mbc1).wc_valid \
|
||||
? ((mbc2).wc_valid \
|
||||
? (int) (mbc1).wc - (int) (mbc2).wc \
|
||||
: -1) \
|
||||
: ((mbc2).wc_valid \
|
||||
? 1 \
|
||||
: (mbc1).bytes == (mbc2).bytes \
|
||||
? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
|
||||
: (mbc1).bytes < (mbc2).bytes \
|
||||
? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
|
||||
: (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
|
||||
#define mb_casecmp(mbc1, mbc2) \
|
||||
((mbc1).wc_valid \
|
||||
? ((mbc2).wc_valid \
|
||||
? (int) towlower ((mbc1).wc) - (int) towlower ((mbc2).wc) \
|
||||
: -1) \
|
||||
: ((mbc2).wc_valid \
|
||||
? 1 \
|
||||
: (mbc1).bytes == (mbc2).bytes \
|
||||
? memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) \
|
||||
: (mbc1).bytes < (mbc2).bytes \
|
||||
? (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) > 0 ? 1 : -1) \
|
||||
: (memcmp ((mbc1).ptr, (mbc2).ptr, (mbc2).bytes) >= 0 ? 1 : -1)))
|
||||
#define mb_equal(mbc1, mbc2) \
|
||||
((mbc1).wc_valid && (mbc2).wc_valid \
|
||||
? (mbc1).wc == (mbc2).wc \
|
||||
: (mbc1).bytes == (mbc2).bytes \
|
||||
&& memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
|
||||
#define mb_caseequal(mbc1, mbc2) \
|
||||
((mbc1).wc_valid && (mbc2).wc_valid \
|
||||
? towlower ((mbc1).wc) == towlower ((mbc2).wc) \
|
||||
: (mbc1).bytes == (mbc2).bytes \
|
||||
&& memcmp ((mbc1).ptr, (mbc2).ptr, (mbc1).bytes) == 0)
|
||||
|
||||
/* <ctype.h>, <wctype.h> classification. */
|
||||
#define mb_isascii(mbc) \
|
||||
((mbc).wc_valid && (mbc).wc >= 0 && (mbc).wc <= 127)
|
||||
#define mb_isalnum(mbc) ((mbc).wc_valid && iswalnum ((mbc).wc))
|
||||
#define mb_isalpha(mbc) ((mbc).wc_valid && iswalpha ((mbc).wc))
|
||||
#define mb_isblank(mbc) ((mbc).wc_valid && iswblank ((mbc).wc))
|
||||
#define mb_iscntrl(mbc) ((mbc).wc_valid && iswcntrl ((mbc).wc))
|
||||
#define mb_isdigit(mbc) ((mbc).wc_valid && iswdigit ((mbc).wc))
|
||||
#define mb_isgraph(mbc) ((mbc).wc_valid && iswgraph ((mbc).wc))
|
||||
#define mb_islower(mbc) ((mbc).wc_valid && iswlower ((mbc).wc))
|
||||
#define mb_isprint(mbc) ((mbc).wc_valid && iswprint ((mbc).wc))
|
||||
#define mb_ispunct(mbc) ((mbc).wc_valid && iswpunct ((mbc).wc))
|
||||
#define mb_isspace(mbc) ((mbc).wc_valid && iswspace ((mbc).wc))
|
||||
#define mb_isupper(mbc) ((mbc).wc_valid && iswupper ((mbc).wc))
|
||||
#define mb_isxdigit(mbc) ((mbc).wc_valid && iswxdigit ((mbc).wc))
|
||||
|
||||
/* Extra <wchar.h> function. */
|
||||
|
||||
/* Unprintable characters appear as a small box of width 1. */
|
||||
#define MB_UNPRINTABLE_WIDTH 1
|
||||
|
||||
static inline int
|
||||
mb_width_aux (wint_t wc)
|
||||
{
|
||||
int w = wcwidth (wc);
|
||||
/* For unprintable characters, arbitrarily return 0 for control characters
|
||||
and MB_UNPRINTABLE_WIDTH otherwise. */
|
||||
return (w >= 0 ? w : iswcntrl (wc) ? 0 : MB_UNPRINTABLE_WIDTH);
|
||||
}
|
||||
|
||||
#define mb_width(mbc) \
|
||||
((mbc).wc_valid ? mb_width_aux ((mbc).wc) : MB_UNPRINTABLE_WIDTH)
|
||||
|
||||
/* Output. */
|
||||
#define mb_putc(mbc, stream) fwrite ((mbc).ptr, 1, (mbc).bytes, (stream))
|
||||
|
||||
/* Assignment. */
|
||||
#define mb_setascii(mbc, sc) \
|
||||
((mbc)->ptr = (mbc)->buf, (mbc)->bytes = 1, (mbc)->wc_valid = 1, \
|
||||
(mbc)->wc = (mbc)->buf[0] = (sc))
|
||||
|
||||
/* Copying a character. */
|
||||
static inline void
|
||||
mb_copy (mbchar_t *new, const mbchar_t *old)
|
||||
{
|
||||
if (old->ptr == &old->buf[0])
|
||||
{
|
||||
memcpy (&new->buf[0], &old->buf[0], old->bytes);
|
||||
new->ptr = &new->buf[0];
|
||||
}
|
||||
else
|
||||
new->ptr = old->ptr;
|
||||
new->bytes = old->bytes;
|
||||
if ((new->wc_valid = old->wc_valid))
|
||||
new->wc = old->wc;
|
||||
}
|
||||
|
||||
|
||||
/* is_basic(c) tests whether the single-byte character c is in the
|
||||
ISO C "basic character set".
|
||||
This is a convenience function, and is in this file only to share code
|
||||
between mbiter_multi.h and mbfile_multi.h. */
|
||||
#if (' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
||||
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
|
||||
&& (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
|
||||
&& ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
|
||||
&& ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
|
||||
&& ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
|
||||
&& ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
|
||||
&& ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
|
||||
&& ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
|
||||
&& ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
|
||||
&& ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
|
||||
&& ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
|
||||
&& ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
|
||||
&& ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
|
||||
&& ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
|
||||
&& ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
|
||||
&& ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
|
||||
&& ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
|
||||
&& ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
|
||||
&& ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
|
||||
&& ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
|
||||
&& ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
|
||||
&& ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)
|
||||
/* The character set is ISO-646, not EBCDIC. */
|
||||
# define IS_BASIC_ASCII 1
|
||||
|
||||
extern unsigned int is_basic_table[];
|
||||
|
||||
static inline bool
|
||||
is_basic (char c)
|
||||
{
|
||||
return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31))
|
||||
& 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline bool
|
||||
is_basic (char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '\t': case '\v': case '\f':
|
||||
case ' ': case '!': case '"': case '#': case '%':
|
||||
case '&': case '\'': case '(': case ')': case '*':
|
||||
case '+': case ',': case '-': case '.': case '/':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
case ':': case ';': case '<': case '=': case '>':
|
||||
case '?':
|
||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||
case 'F': case 'G': case 'H': case 'I': case 'J':
|
||||
case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P': case 'Q': case 'R': case 'S': case 'T':
|
||||
case 'U': case 'V': case 'W': case 'X': case 'Y':
|
||||
case 'Z':
|
||||
case '[': case '\\': case ']': case '^': case '_':
|
||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||
case 'k': case 'l': case 'm': case 'n': case 'o':
|
||||
case 'p': case 'q': case 'r': case 's': case 't':
|
||||
case 'u': case 'v': case 'w': case 'x': case 'y':
|
||||
case 'z': case '{': case '|': case '}': case '~':
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _MBCHAR_H */
|
203
lib/mbuiter.h
Normal file
203
lib/mbuiter.h
Normal file
@ -0,0 +1,203 @@
|
||||
/* Iterating through multibyte strings: macros for multi-byte encodings.
|
||||
Copyright (C) 2001, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software Foundation,
|
||||
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* Written by Bruno Haible <bruno@clisp.org>. */
|
||||
|
||||
/* The macros in this file implement forward iteration through a
|
||||
multi-byte string, without knowing its length a-priori.
|
||||
|
||||
With these macros, an iteration loop that looks like
|
||||
|
||||
char *iter;
|
||||
for (iter = buf; *iter != '\0'; iter++)
|
||||
{
|
||||
do_something (*iter);
|
||||
}
|
||||
|
||||
becomes
|
||||
|
||||
mbui_iterator_t iter;
|
||||
for (mbui_init (iter, buf); mbui_avail (iter); mbui_advance (iter))
|
||||
{
|
||||
do_something (mbui_cur_ptr (iter), mb_len (mbui_cur (iter)));
|
||||
}
|
||||
|
||||
The benefit of these macros over plain use of mbrtowc is:
|
||||
- Handling of invalid multibyte sequences is possible without
|
||||
making the code more complicated, while still preserving the
|
||||
invalid multibyte sequences.
|
||||
|
||||
Compared to mbiter.h, the macros here don't need to know the string's
|
||||
length a-priori. The downside is that at each step, the look-ahead
|
||||
that guards against overrunning the terminating '\0' is more expensive.
|
||||
The mbui_* macros are therefore suitable when there is a high probability
|
||||
that only the first few multibyte characters need to be inspected.
|
||||
Whereas the mbi_* macros are better if usually the iteration runs
|
||||
through the entire string.
|
||||
|
||||
mbui_iterator_t
|
||||
is a type usable for variable declarations.
|
||||
|
||||
mbui_init (iter, startptr)
|
||||
initializes the iterator, starting at startptr.
|
||||
|
||||
mbui_avail (iter)
|
||||
returns true if there are more multibyte chracters available before
|
||||
the end of string is reached. In this case, mbui_cur (iter) is
|
||||
initialized to the next multibyte chracter.
|
||||
|
||||
mbui_advance (iter)
|
||||
advances the iterator by one multibyte character.
|
||||
|
||||
mbui_cur (iter)
|
||||
returns the current multibyte character, of type mbchar_t. All the
|
||||
macros defined in mbchar.h can be used on it.
|
||||
|
||||
mbui_cur_ptr (iter)
|
||||
return a pointer to the beginning of the current multibyte character.
|
||||
|
||||
mbui_reloc (iter, ptrdiff)
|
||||
relocates iterator when the string is moved by ptrdiff bytes.
|
||||
|
||||
Here are the function prototypes of the macros.
|
||||
|
||||
extern void mbui_init (mbui_iterator_t iter, const char *startptr);
|
||||
extern bool mbui_avail (mbui_iterator_t iter);
|
||||
extern void mbui_advance (mbui_iterator_t iter);
|
||||
extern mbchar_t mbui_cur (mbui_iterator_t iter);
|
||||
extern const char * mbui_cur_ptr (mbui_iterator_t iter);
|
||||
extern void mbui_reloc (mbui_iterator_t iter, ptrdiff_t ptrdiff);
|
||||
*/
|
||||
|
||||
#ifndef _MBUITER_H
|
||||
#define _MBUITER_H 1
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Tru64 with Desktop Toolkit C has a bug: <stdio.h> must be included before
|
||||
<wchar.h>.
|
||||
BSD/OS 4.1 has a bug: <stdio.h> and <time.h> must be included before
|
||||
<wchar.h>. */
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "mbchar.h"
|
||||
#include "strnlen1.h"
|
||||
|
||||
struct mbuiter_multi
|
||||
{
|
||||
bool in_shift; /* true if next byte may not be interpreted as ASCII */
|
||||
mbstate_t state; /* if in_shift: current shift state */
|
||||
bool next_done; /* true if mbui_avail has already filled the following */
|
||||
struct mbchar cur; /* the current character:
|
||||
const char *cur.ptr pointer to current character
|
||||
The following are only valid after mbui_avail.
|
||||
size_t cur.bytes number of bytes of current character
|
||||
bool cur.wc_valid true if wc is a valid wide character
|
||||
wchar_t cur.wc if wc_valid: the current character
|
||||
*/
|
||||
};
|
||||
|
||||
static inline void
|
||||
mbuiter_multi_next (struct mbuiter_multi *iter)
|
||||
{
|
||||
if (iter->next_done)
|
||||
return;
|
||||
if (iter->in_shift)
|
||||
goto with_shift;
|
||||
/* Handle most ASCII characters quickly, without calling mbrtowc(). */
|
||||
if (is_basic (*iter->cur.ptr))
|
||||
{
|
||||
/* These characters are part of the basic character set. ISO C 99
|
||||
guarantees that their wide character code is identical to their
|
||||
char code. */
|
||||
iter->cur.bytes = 1;
|
||||
iter->cur.wc = *iter->cur.ptr;
|
||||
iter->cur.wc_valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert (mbsinit (&iter->state));
|
||||
iter->in_shift = true;
|
||||
with_shift:
|
||||
iter->cur.bytes = mbrtowc (&iter->cur.wc, iter->cur.ptr,
|
||||
strnlen1 (iter->cur.ptr, MB_CUR_MAX),
|
||||
&iter->state);
|
||||
if (iter->cur.bytes == (size_t) -1)
|
||||
{
|
||||
/* An invalid multibyte sequence was encountered. */
|
||||
iter->cur.bytes = 1;
|
||||
iter->cur.wc_valid = false;
|
||||
/* Whether to set iter->in_shift = false and reset iter->state
|
||||
or not is not very important; the string is bogus anyway. */
|
||||
}
|
||||
else if (iter->cur.bytes == (size_t) -2)
|
||||
{
|
||||
/* An incomplete multibyte character at the end. */
|
||||
iter->cur.bytes = strlen (iter->cur.ptr);
|
||||
iter->cur.wc_valid = false;
|
||||
/* Whether to set iter->in_shift = false and reset iter->state
|
||||
or not is not important; the string end is reached anyway. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iter->cur.bytes == 0)
|
||||
{
|
||||
/* A null wide character was encountered. */
|
||||
iter->cur.bytes = 1;
|
||||
assert (*iter->cur.ptr == '\0');
|
||||
assert (iter->cur.wc == 0);
|
||||
}
|
||||
iter->cur.wc_valid = true;
|
||||
|
||||
/* When in the initial state, we can go back treating ASCII
|
||||
characters more quickly. */
|
||||
if (mbsinit (&iter->state))
|
||||
iter->in_shift = false;
|
||||
}
|
||||
}
|
||||
iter->next_done = true;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mbuiter_multi_reloc (struct mbuiter_multi *iter, ptrdiff_t ptrdiff)
|
||||
{
|
||||
iter->cur.ptr += ptrdiff;
|
||||
}
|
||||
|
||||
/* Iteration macros. */
|
||||
typedef struct mbuiter_multi mbui_iterator_t;
|
||||
#define mbui_init(iter, startptr) \
|
||||
((iter).cur.ptr = (startptr), \
|
||||
(iter).in_shift = false, memset (&(iter).state, '\0', sizeof (mbstate_t)), \
|
||||
(iter).next_done = false)
|
||||
#define mbui_avail(iter) \
|
||||
(mbuiter_multi_next (&(iter)), !mb_isnul ((iter).cur))
|
||||
#define mbui_advance(iter) \
|
||||
((iter).cur.ptr += (iter).cur.bytes, (iter).next_done = false)
|
||||
|
||||
/* Access to the current character. */
|
||||
#define mbui_cur(iter) (iter).cur
|
||||
#define mbui_cur_ptr(iter) (iter).cur.ptr
|
||||
|
||||
/* Relocation. */
|
||||
#define mbui_reloc(iter, ptrdiff) mbuiter_multi_reloc (&iter, ptrdiff)
|
||||
|
||||
#endif /* _MBUITER_H */
|
48
lib/strcase.h
Normal file
48
lib/strcase.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* Case-insensitive string comparison functions.
|
||||
Copyright (C) 1995-1996, 2001, 2003, 2005 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. */
|
||||
|
||||
#ifndef _STRCASE_H
|
||||
#define _STRCASE_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* 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! */
|
||||
extern int strcasecmp (const char *s1, const char *s2);
|
||||
|
||||
/* 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.
|
||||
Note: This function can not work correctly in multibyte locales. */
|
||||
extern int strncasecmp (const char *s1, const char *s2, size_t n);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _STRCASE_H */
|
32
lib/strnlen.h
Normal file
32
lib/strnlen.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* Find the length of STRING, but scan at most MAXLEN characters.
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Written by Simon Josefsson.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef STRNLEN_H
|
||||
#define STRNLEN_H
|
||||
|
||||
/* Get strnlen declaration, if available. */
|
||||
#include <string.h>
|
||||
|
||||
#if defined HAVE_DECL_STRNLEN && !HAVE_DECL_STRNLEN
|
||||
/* Find the length (number of bytes) of STRING, but scan at most
|
||||
MAXLEN bytes. If no '\0' terminator is found in that many bytes,
|
||||
return MAXLEN. */
|
||||
extern size_t strnlen(const char *string, size_t maxlen);
|
||||
#endif
|
||||
|
||||
#endif /* STRNLEN_H */
|
39
lib/strnlen1.c
Normal file
39
lib/strnlen1.c
Normal file
@ -0,0 +1,39 @@
|
||||
/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library 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 "strnlen1.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
|
||||
If no '\0' terminator is found in that many characters, return MAXLEN. */
|
||||
/* This is the same as strnlen (string, maxlen - 1) + 1. */
|
||||
size_t
|
||||
strnlen1 (const char *string, size_t maxlen)
|
||||
{
|
||||
const char *end = memchr (string, '\0', maxlen);
|
||||
if (end != NULL)
|
||||
return end - string + 1;
|
||||
else
|
||||
return maxlen;
|
||||
}
|
41
lib/strnlen1.h
Normal file
41
lib/strnlen1.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Library 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library 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 _STRNLEN1_H
|
||||
#define _STRNLEN1_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Find the length of STRING + 1, but scan at most MAXLEN bytes.
|
||||
If no '\0' terminator is found in that many characters, return MAXLEN. */
|
||||
/* This is the same as strnlen (string, maxlen - 1) + 1. */
|
||||
extern size_t strnlen1 (const char *string, size_t maxlen);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _STRNLEN1_H */
|
37
lib/strstr.h
Normal file
37
lib/strstr.h
Normal file
@ -0,0 +1,37 @@
|
||||
/* Searching in a string.
|
||||
Copyright (C) 2001-2003, 2005 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. */
|
||||
|
||||
|
||||
/* Include string.h: on glibc systems, it contains a macro definition of
|
||||
strstr() that would collide with our definition if included afterwards. */
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* No known system has a strstr() function that works correctly in
|
||||
multibyte locales. Therefore we use our version always. */
|
||||
#undef strstr
|
||||
#define strstr rpl_strstr
|
||||
|
||||
/* Find the first occurrence of NEEDLE in HAYSTACK. */
|
||||
extern char *strstr (const char *haystack, const char *needle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
19
m4/getaddrinfo.m4
Normal file
19
m4/getaddrinfo.m4
Normal file
@ -0,0 +1,19 @@
|
||||
# getaddrinfo.m4 serial 3
|
||||
dnl Copyright (C) 2004 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_GETADDRINFO],
|
||||
[
|
||||
AC_SEARCH_LIBS(getaddrinfo, nsl socket)
|
||||
AC_REPLACE_FUNCS(getaddrinfo gai_strerror)
|
||||
gl_PREREQ_GETADDRINFO
|
||||
])
|
||||
|
||||
# Prerequisites of lib/getaddrinfo.h and lib/getaddrinfo.c.
|
||||
AC_DEFUN([gl_PREREQ_GETADDRINFO], [
|
||||
AC_REQUIRE([gl_C_RESTRICT])
|
||||
AC_REQUIRE([gl_SOCKET_FAMILIES])
|
||||
AC_REQUIRE([AC_C_INLINE])
|
||||
])
|
30
m4/getdelim.m4
Normal file
30
m4/getdelim.m4
Normal file
@ -0,0 +1,30 @@
|
||||
# getdelim.m4 serial 1
|
||||
|
||||
dnl Copyright (C) 2005 Free Software dnl Foundation, Inc.
|
||||
dnl
|
||||
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_PREREQ(2.52)
|
||||
|
||||
AC_DEFUN([gl_FUNC_GETDELIM],
|
||||
[
|
||||
AC_LIBSOURCES([getdelim.c, getdelim.h])
|
||||
|
||||
dnl Persuade glibc <stdio.h> to declare getdelim().
|
||||
AC_REQUIRE([AC_GNU_SOURCE])
|
||||
|
||||
AC_REPLACE_FUNCS(getdelim)
|
||||
AC_CHECK_DECLS_ONCE(getdelim)
|
||||
|
||||
if test $ac_cv_func_getdelim = no; then
|
||||
gl_PREREQ_GETDELIM
|
||||
fi
|
||||
])
|
||||
|
||||
# Prerequisites of lib/getdelim.c.
|
||||
AC_DEFUN([gl_PREREQ_GETDELIM],
|
||||
[
|
||||
AC_CHECK_FUNCS([flockfile funlockfile])
|
||||
])
|
14
m4/mbchar.m4
Normal file
14
m4/mbchar.m4
Normal file
@ -0,0 +1,14 @@
|
||||
# mbchar.m4 serial 1
|
||||
dnl Copyright (C) 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.
|
||||
|
||||
dnl autoconf tests required for use of mbchar.m4
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([gl_MBCHAR],
|
||||
[
|
||||
AC_REQUIRE([AC_GNU_SOURCE])
|
||||
:
|
||||
])
|
14
m4/mbiter.m4
Normal file
14
m4/mbiter.m4
Normal file
@ -0,0 +1,14 @@
|
||||
# mbiter.m4 serial 1
|
||||
dnl Copyright (C) 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.
|
||||
|
||||
dnl autoconf tests required for use of mbiter.h
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([gl_MBITER],
|
||||
[
|
||||
AC_REQUIRE([AC_TYPE_MBSTATE_T])
|
||||
:
|
||||
])
|
39
m4/sockpfaf.m4
Normal file
39
m4/sockpfaf.m4
Normal file
@ -0,0 +1,39 @@
|
||||
# sockpfaf.m4 serial 2
|
||||
dnl Copyright (C) 2004 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.
|
||||
|
||||
dnl Test for some common socket protocol families (PF_INET, PF_INET6, ...)
|
||||
dnl and some common address families (AF_INET, AF_INET6, ...).
|
||||
dnl This test assumes that a system supports an address family if and only if
|
||||
dnl it supports the corresponding protocol family.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([gl_SOCKET_FAMILIES],
|
||||
[
|
||||
AC_MSG_CHECKING(for IPv4 sockets)
|
||||
AC_CACHE_VAL(gl_cv_socket_ipv4,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>],
|
||||
[int x = AF_INET; struct in_addr y; struct sockaddr_in z;],
|
||||
gl_cv_socket_ipv4=yes, gl_cv_socket_ipv4=no)])
|
||||
AC_MSG_RESULT($gl_cv_socket_ipv4)
|
||||
if test $gl_cv_socket_ipv4 = yes; then
|
||||
AC_DEFINE(HAVE_IPV4, 1, [Define to 1 if <sys/socket.h> defines AF_INET.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING(for IPv6 sockets)
|
||||
AC_CACHE_VAL(gl_cv_socket_ipv6,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>],
|
||||
[int x = AF_INET6; struct in6_addr y; struct sockaddr_in6 z;],
|
||||
gl_cv_socket_ipv6=yes, gl_cv_socket_ipv6=no)])
|
||||
AC_MSG_RESULT($gl_cv_socket_ipv6)
|
||||
if test $gl_cv_socket_ipv6 = yes; then
|
||||
AC_DEFINE(HAVE_IPV6, 1, [Define to 1 if <sys/socket.h> defines AF_INET6.])
|
||||
fi
|
||||
])
|
Loading…
Reference in New Issue
Block a user