code:
/* A POSIX <locale.h>.
   Copyright (C) 2007-2017 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/>.  */

#if __GNUC__ >= 3
@PRAGMA_SYSTEM_HEADER@
#endif
@PRAGMA_COLUMNS@

#ifdef _GL_ALREADY_INCLUDING_LOCALE_H

/* Special invocation conventions to handle Solaris header files
   (through Solaris 10) when combined with gettext's libintl.h.  */

#@INCLUDE_NEXT@ @NEXT_LOCALE_H@

#else
/* Normal invocation convention.  */

#ifndef _@GUARD_PREFIX@_LOCALE_H

#define _GL_ALREADY_INCLUDING_LOCALE_H

/* The include_next requires a split double-inclusion guard.  */
#@INCLUDE_NEXT@ @NEXT_LOCALE_H@

#undef _GL_ALREADY_INCLUDING_LOCALE_H

#ifndef _@GUARD_PREFIX@_LOCALE_H
#define _@GUARD_PREFIX@_LOCALE_H

/* NetBSD 5.0 mis-defines NULL.  */
#include <stddef.h>

/* Mac OS X 10.5 defines the locale_t type in <xlocale.h>.  */
#if @HAVE_XLOCALE_H@
# include <xlocale.h>
#endif

/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */

/* The definition of _GL_ARG_NONNULL is copied here.  */

/* The definition of _GL_WARN_ON_USE is copied here.  */

/* The LC_MESSAGES locale category is specified in POSIX, but not in ISO C.
   On systems that don't define it, use the same value as GNU libintl.  */
#if !defined LC_MESSAGES
# define LC_MESSAGES 1729
#endif

/* Bionic libc's 'struct lconv' is just a dummy.  */
#if @REPLACE_STRUCT_LCONV@
# define lconv rpl_lconv
struct lconv
{
  /* All 'char *' are actually 'const char *'.  */

  /* Members that depend on the LC_NUMERIC category of the locale.  See
     <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_04> */

  /* Symbol used as decimal point.  */
  char *decimal_point;
  /* Symbol used to separate groups of digits to the left of the decimal
     point.  */
  char *thousands_sep;
  /* Definition of the size of groups of digits to the left of the decimal
     point.  */
  char *grouping;

  /* Members that depend on the LC_MONETARY category of the locale.  See
     <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_03> */

  /* Symbol used as decimal point.  */
  char *mon_decimal_point;
  /* Symbol used to separate groups of digits to the left of the decimal
     point.  */
  char *mon_thousands_sep;
  /* Definition of the size of groups of digits to the left of the decimal
     point.  */
  char *mon_grouping;
  /* Sign used to indicate a value >= 0.  */
  char *positive_sign;
  /* Sign used to indicate a value < 0.  */
  char *negative_sign;

  /* For formatting local currency.  */
  /* Currency symbol (3 characters) followed by separator (1 character).  */
  char *currency_symbol;
  /* Number of digits after the decimal point.  */
  char frac_digits;
  /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it
     comes after the number.  */
  char p_cs_precedes;
  /* For values >= 0: Position of the sign.  */
  char p_sign_posn;
  /* For values >= 0: Placement of spaces between currency symbol, sign, and
     number.  */
  char p_sep_by_space;
  /* For values < 0: 1 if the currency symbol precedes the number, 0 if it
     comes after the number.  */
  char n_cs_precedes;
  /* For values < 0: Position of the sign.  */
  char n_sign_posn;
  /* For values < 0: Placement of spaces between currency symbol, sign, and
     number.  */
  char n_sep_by_space;

  /* For formatting international currency.  */
  /* Currency symbol (3 characters) followed by separator (1 character).  */
  char *int_curr_symbol;
  /* Number of digits after the decimal point.  */
  char int_frac_digits;
  /* For values >= 0: 1 if the currency symbol precedes the number, 0 if it
     comes after the number.  */
  char int_p_cs_precedes;
  /* For values >= 0: Position of the sign.  */
  char int_p_sign_posn;
  /* For values >= 0: Placement of spaces between currency symbol, sign, and
     number.  */
  char int_p_sep_by_space;
  /* For values < 0: 1 if the currency symbol precedes the number, 0 if it
     comes after the number.  */
  char int_n_cs_precedes;
  /* For values < 0: Position of the sign.  */
  char int_n_sign_posn;
  /* For values < 0: Placement of spaces between currency symbol, sign, and
     number.  */
  char int_n_sep_by_space;
};
#endif

#if @GNULIB_LOCALECONV@
# if @REPLACE_LOCALECONV@
#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
#   undef localeconv
#   define localeconv rpl_localeconv
#  endif
_GL_FUNCDECL_RPL (localeconv, struct lconv *, (void));
_GL_CXXALIAS_RPL (localeconv, struct lconv *, (void));
# else
_GL_CXXALIAS_SYS (localeconv, struct lconv *, (void));
# endif
_GL_CXXALIASWARN (localeconv);
#elif @REPLACE_STRUCT_LCONV@
# undef localeconv
# define localeconv localeconv_used_without_requesting_gnulib_module_localeconv
#elif defined GNULIB_POSIXCHECK
# undef localeconv
# if HAVE_RAW_DECL_LOCALECONV
_GL_WARN_ON_USE (localeconv,
                 "localeconv returns too few information on some platforms - "
                 "use gnulib module localeconv for portability");
# endif
#endif

#if @GNULIB_SETLOCALE@
# if @REPLACE_SETLOCALE@
#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
#   undef setlocale
#   define setlocale rpl_setlocale
#   define GNULIB_defined_setlocale 1
#  endif
_GL_FUNCDECL_RPL (setlocale, char *, (int category, const char *locale));
_GL_CXXALIAS_RPL (setlocale, char *, (int category, const char *locale));
# else
_GL_CXXALIAS_SYS (setlocale, char *, (int category, const char *locale));
# endif
_GL_CXXALIASWARN (setlocale);
#elif defined GNULIB_POSIXCHECK
# undef setlocale
# if HAVE_RAW_DECL_SETLOCALE
_GL_WARN_ON_USE (setlocale, "setlocale works differently on native Windows - "
                 "use gnulib module setlocale for portability");
# endif
#endif

#if @GNULIB_DUPLOCALE@
# if @REPLACE_DUPLOCALE@
#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
#   undef duplocale
#   define duplocale rpl_duplocale
#  endif
_GL_FUNCDECL_RPL (duplocale, locale_t, (locale_t locale) _GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (duplocale, locale_t, (locale_t locale));
# else
#  if @HAVE_DUPLOCALE@
_GL_CXXALIAS_SYS (duplocale, locale_t, (locale_t locale));
#  endif
# endif
# if @HAVE_DUPLOCALE@
_GL_CXXALIASWARN (duplocale);
# endif
#elif defined GNULIB_POSIXCHECK
# undef duplocale
# if HAVE_RAW_DECL_DUPLOCALE
_GL_WARN_ON_USE (duplocale, "duplocale is buggy on some glibc systems - "
                 "use gnulib module duplocale for portability");
# endif
#endif

#endif /* _@GUARD_PREFIX@_LOCALE_H */
#endif /* ! _GL_ALREADY_INCLUDING_LOCALE_H */
#endif /* _@GUARD_PREFIX@_LOCALE_H */


code:
/* Query locale dependent information for formatting numbers.
   Copyright (C) 2012-2017 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/>.  */

#include <config.h>

/* Specification.  */
#include <locale.h>

#if HAVE_STRUCT_LCONV_DECIMAL_POINT

/* Override for platforms where 'struct lconv' lacks the int_p_*, int_n_*
   members.  */

struct lconv *
localeconv (void)
{
  static struct lconv result;
# undef lconv
# undef localeconv
  struct lconv *sys_result = localeconv ();

  result.decimal_point = sys_result->decimal_point;
  result.thousands_sep = sys_result->thousands_sep;
  result.grouping = sys_result->grouping;
  result.mon_decimal_point = sys_result->mon_decimal_point;
  result.mon_thousands_sep = sys_result->mon_thousands_sep;
  result.mon_grouping = sys_result->mon_grouping;
  result.positive_sign = sys_result->positive_sign;
  result.negative_sign = sys_result->negative_sign;
  result.currency_symbol = sys_result->currency_symbol;
  result.frac_digits = sys_result->frac_digits;
  result.p_cs_precedes = sys_result->p_cs_precedes;
  result.p_sign_posn = sys_result->p_sign_posn;
  result.p_sep_by_space = sys_result->p_sep_by_space;
  result.n_cs_precedes = sys_result->n_cs_precedes;
  result.n_sign_posn = sys_result->n_sign_posn;
  result.n_sep_by_space = sys_result->n_sep_by_space;
  result.int_curr_symbol = sys_result->int_curr_symbol;
  result.int_frac_digits = sys_result->int_frac_digits;
  result.int_p_cs_precedes = sys_result->p_cs_precedes;
  result.int_p_sign_posn = sys_result->p_sign_posn;
  result.int_p_sep_by_space = sys_result->p_sep_by_space;
  result.int_n_cs_precedes = sys_result->n_cs_precedes;
  result.int_n_sign_posn = sys_result->n_sign_posn;
  result.int_n_sep_by_space = sys_result->n_sep_by_space;

  return &result;
}

#else

/* Override for platforms where 'struct lconv' is a dummy.  */

# include <limits.h>

struct lconv *
localeconv (void)
{
  static /*const*/ struct lconv result =
    {
      /* decimal_point */ ".",
      /* thousands_sep */ "",
      /* grouping */ "",
      /* mon_decimal_point */ "",
      /* mon_thousands_sep */ "",
      /* mon_grouping */ "",
      /* positive_sign */ "",
      /* negative_sign */ "",
      /* currency_symbol */ "",
      /* frac_digits */ CHAR_MAX,
      /* p_cs_precedes */ CHAR_MAX,
      /* p_sign_posn */ CHAR_MAX,
      /* p_sep_by_space */ CHAR_MAX,
      /* n_cs_precedes */ CHAR_MAX,
      /* n_sign_posn */ CHAR_MAX,
      /* n_sep_by_space */ CHAR_MAX,
      /* int_curr_symbol */ "",
      /* int_frac_digits */ CHAR_MAX,
      /* int_p_cs_precedes */ CHAR_MAX,
      /* int_p_sign_posn */ CHAR_MAX,
      /* int_p_sep_by_space */ CHAR_MAX,
      /* int_n_cs_precedes */ CHAR_MAX,
      /* int_n_sign_posn */ CHAR_MAX,
      /* int_n_sep_by_space */ CHAR_MAX
    };

  return &result;
}

#endif

repo_name: mthl/texinfo

license: mit


code:
/* malloc() function that is glibc compatible.

   Copyright (C) 1997-1998, 2006-2007, 2009-2017 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, 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 and Bruno Haible */

#define _GL_USE_STDLIB_ALLOC 1
#include <config.h>
/* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h.  */
#ifdef malloc
# define NEED_MALLOC_GNU 1
# undef malloc
/* Whereas the gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU.  */
#elif GNULIB_MALLOC_GNU && !HAVE_MALLOC_GNU
# define NEED_MALLOC_GNU 1
#endif

#include <stdlib.h>

#include <errno.h>

/* Allocate an N-byte block of memory from the heap.
   If N is zero, allocate a 1-byte block.  */

void *
rpl_malloc (size_t n)
{
  void *result;

#if NEED_MALLOC_GNU
  if (n == 0)
    n = 1;
#endif

  result = malloc (n);

#if !HAVE_MALLOC_POSIX
  if (result == NULL)
    errno = ENOMEM;
#endif

  return result;
}


code:
/* Safe automatic memory allocation.
   Copyright (C) 2003, 2006-2007, 2009-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2003.

   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, 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/>.  */

#define _GL_USE_STDLIB_ALLOC 1
#include <config.h>

/* Specification.  */
#include "malloca.h"

#include <stdint.h>

#include "verify.h"

/* The speed critical point in this file is freea() applied to an alloca()
   result: it must be fast, to match the speed of alloca().  The speed of
   mmalloca() and freea() in the other case are not critical, because they
   are only invoked for big memory sizes.  */

#if HAVE_ALLOCA

/* Store the mmalloca() results in a hash table.  This is needed to reliably
   distinguish a mmalloca() result and an alloca() result.

   Although it is possible that the same pointer is returned by alloca() and
   by mmalloca() at different times in the same application, it does not lead
   to a bug in freea(), because:
     - Before a pointer returned by alloca() can point into malloc()ed memory,
       the function must return, and once this has happened the programmer must
       not call freea() on it anyway.
     - Before a pointer returned by mmalloca() can point into the stack, it
       must be freed.  The only function that can free it is freea(), and
       when freea() frees it, it also removes it from the hash table.  */

#define MAGIC_NUMBER 0x1415fb4a
#define MAGIC_SIZE sizeof (int)
/* This is how the header info would look like without any alignment
   considerations.  */
struct preliminary_header { void *next; int magic; };
/* But the header's size must be a multiple of sa_alignment_max.  */
#define HEADER_SIZE \
  (((sizeof (struct preliminary_header) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max)
union header {
  void *next;
  struct {
    char room[HEADER_SIZE - MAGIC_SIZE];
    int word;
  } magic;
};
verify (HEADER_SIZE == sizeof (union header));
/* We make the hash table quite big, so that during lookups the probability
   of empty hash buckets is quite high.  There is no need to make the hash
   table resizable, because when the hash table gets filled so much that the
   lookup becomes slow, it means that the application has memory leaks.  */
#define HASH_TABLE_SIZE 257
static void * mmalloca_results[HASH_TABLE_SIZE];

#endif

void *
mmalloca (size_t n)
{
#if HAVE_ALLOCA
  /* Allocate one more word, that serves as an indicator for malloc()ed
     memory, so that freea() of an alloca() result is fast.  */
  size_t nplus = n + HEADER_SIZE;

  if (nplus >= n)
    {
      void *p = malloc (nplus);

      if (p != NULL)
        {
          size_t slot;
          union header *h = p;

          p = h + 1;

          /* Put a magic number into the indicator word.  */
          h->magic.word = MAGIC_NUMBER;

          /* Enter p into the hash table.  */
          slot = (uintptr_t) p % HASH_TABLE_SIZE;
          h->next = mmalloca_results[slot];
          mmalloca_results[slot] = p;

          return p;
        }
    }
  /* Out of memory.  */
  return NULL;
#else
# if !MALLOC_0_IS_NONNULL
  if (n == 0)
    n = 1;
# endif
  return malloc (n);
#endif
}

#if HAVE_ALLOCA
void
freea (void *p)
{
  /* mmalloca() may have returned NULL.  */
  if (p != NULL)
    {
      /* Attempt to quickly distinguish the mmalloca() result - which has
         a magic indicator word - and the alloca() result - which has an
         uninitialized indicator word.  It is for this test that sa_increment
         additional bytes are allocated in the alloca() case.  */
      if (((int *) p)[-1] == MAGIC_NUMBER)
        {
          /* Looks like a mmalloca() result.  To see whether it really is one,
             perform a lookup in the hash table.  */
          size_t slot = (uintptr_t) p % HASH_TABLE_SIZE;
          void **chain = &mmalloca_results[slot];
          for (; *chain != NULL;)
            {
              union header *h = p;
              if (*chain == p)
                {
                  /* Found it.  Remove it from the hash table and free it.  */
                  union header *p_begin = h - 1;
                  *chain = p_begin->next;
                  free (p_begin);
                  return;
                }
              h = *chain;
              chain = &h[-1].next;
            }
        }
      /* At this point, we know it was not a mmalloca() result.  */
    }
}
#endif


code:
/* Safe automatic memory allocation.
   Copyright (C) 2003-2007, 2009-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2003.

   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, 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/>.  */

#ifndef _MALLOCA_H
#define _MALLOCA_H

#include <alloca.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>

#include "xalloc-oversized.h"

#ifdef __cplusplus
extern "C" {
#endif

/* safe_alloca(N) is equivalent to alloca(N) when it is safe to call
   alloca(N); otherwise it returns NULL.  It either returns N bytes of
   memory allocated on the stack, that lasts until the function returns,
   or NULL.
   Use of safe_alloca should be avoided:
     - inside arguments of function calls - undefined behaviour,
     - in inline functions - the allocation may actually last until the
       calling function returns.
*/
#if HAVE_ALLOCA
/* The OS usually guarantees only one guard page at the bottom of the stack,
   and a page size can be as small as 4096 bytes.  So we cannot safely
   allocate anything larger than 4096 bytes.  Also care for the possibility
   of a few compiler-allocated temporary stack slots.
   This must be a macro, not a function.  */
# define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL)
#else
# define safe_alloca(N) ((void) (N), NULL)
#endif

/* malloca(N) is a safe variant of alloca(N).  It allocates N bytes of
   memory allocated on the stack, that must be freed using freea() before
   the function returns.  Upon failure, it returns NULL.  */
#if HAVE_ALLOCA
# define malloca(N) \
  ((N) < 4032 - sa_increment                                        \
   ? (void *) ((char *) alloca ((N) + sa_increment) + sa_increment) \
   : mmalloca (N))
#else
# define malloca(N) \
  mmalloca (N)
#endif
extern void * mmalloca (size_t n);

/* Free a block of memory allocated through malloca().  */
#if HAVE_ALLOCA
extern void freea (void *p);
#else
# define freea free
#endif

/* nmalloca(N,S) is an overflow-safe variant of malloca (N * S).
   It allocates an array of N objects, each with S bytes of memory,
   on the stack.  S must be positive and N must be nonnegative.
   The array must be freed using freea() before the function returns.  */
#define nmalloca(n, s) (xalloc_oversized (n, s) ? NULL : malloca ((n) * (s)))

#ifdef __cplusplus
}
#endif

/* ------------------- Auxiliary, non-public definitions ------------------- */

/* Determine the alignment of a type at compile time.  */
#if defined __GNUC__ || defined __IBM__ALIGNOF__
# define sa_alignof __alignof__
#elif defined __cplusplus
  template <class type> struct sa_alignof_helper { char __slot1; type __slot2; };
# define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2)
#elif defined __hpux
  /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof
     values.  */
# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
#elif defined _AIX
  /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof
     values.  */
# define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8)
#else
# define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2)
#endif

enum
{
/* The desired alignment of memory allocations is the maximum alignment
   among all elementary types.  */
  sa_alignment_long = sa_alignof (long),
  sa_alignment_double = sa_alignof (double),
#if HAVE_LONG_LONG_INT
  sa_alignment_longlong = sa_alignof (long long),
#endif
  sa_alignment_longdouble = sa_alignof (long double),
  sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1)
#if HAVE_LONG_LONG_INT
                      | (sa_alignment_longlong - 1)
#endif
                      | (sa_alignment_longdouble - 1)
                     ) + 1,
/* The increment that guarantees room for a magic word must be >= sizeof (int)
   and a multiple of sa_alignment_max.  */
  sa_increment = ((sizeof (int) + sa_alignment_max - 1) / sa_alignment_max) * sa_alignment_max
};

#endif /* _MALLOCA_H */


code:
# Suppress a valgrind message about use of uninitialized memory in freea().
# This use is OK because it provides only a speedup.
{
    freea
    Memcheck:Cond
    fun:freea
}


code:
/* Copyright (C) 2001, 2006, 2009-2017 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/>.  */

#include <config.h>

#define MBCHAR_INLINE _GL_EXTERN_INLINE

#include <limits.h>

#include "mbchar.h"

#if IS_BASIC_ASCII

/* Bit table of characters in the ISO C "basic character set".  */
const 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 */


code:
/* Multibyte character data type.
   Copyright (C) 2001, 2005-2007, 2009-2017 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 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>

#ifndef _GL_INLINE_HEADER_BEGIN
 #error "Please include config.h first."
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef MBCHAR_INLINE
# define MBCHAR_INLINE _GL_INLINE
#endif

#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

MBCHAR_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.  */
MBCHAR_INLINE void
mb_copy (mbchar_t *new_mbc, const mbchar_t *old_mbc)
{
  if (old_mbc->ptr == &old_mbc->buf[0])
    {
      memcpy (&new_mbc->buf[0], &old_mbc->buf[0], old_mbc->bytes);
      new_mbc->ptr = &new_mbc->buf[0];
    }
  else
    new_mbc->ptr = old_mbc->ptr;
  new_mbc->bytes = old_mbc->bytes;
  if ((new_mbc->wc_valid = old_mbc->wc_valid))
    new_mbc->wc = old_mbc->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 const unsigned int is_basic_table[];

MBCHAR_INLINE bool
is_basic (char c)
{
  return (is_basic_table [(unsigned char) c >> 5] >> ((unsigned char) c & 31))
         & 1;
}

#else

MBCHAR_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

_GL_INLINE_HEADER_END

#endif /* _MBCHAR_H */


code:
#include <config.h>
#define MBITER_INLINE _GL_EXTERN_INLINE
#include "mbiter.h"


code:
/* Iterating through multibyte strings: macros for multi-byte encodings.
   Copyright (C) 2001, 2005, 2007, 2009-2017 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 Bruno Haible <bruno@clisp.org>.  */

/* The macros in this file implement forward iteration through a
   multi-byte string.

   With these macros, an iteration loop that looks like

      char *iter;
      for (iter = buf; iter < buf + buflen; iter++)
        {
          do_something (*iter);
        }

   becomes

      mbi_iterator_t iter;
      for (mbi_init (iter, buf, buflen); mbi_avail (iter); mbi_advance (iter))
        {
          do_something (mbi_cur_ptr (iter), mb_len (mbi_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.

   mbi_iterator_t
     is a type usable for variable declarations.

   mbi_init (iter, startptr, length)
     initializes the iterator, starting at startptr and crossing length bytes.

   mbi_avail (iter)
     returns true if there are more multibyte characters available before
     the end of string is reached. In this case, mbi_cur (iter) is
     initialized to the next multibyte character.

   mbi_advance (iter)
     advances the iterator by one multibyte character.

   mbi_cur (iter)
     returns the current multibyte character, of type mbchar_t.  All the
     macros defined in mbchar.h can be used on it.

   mbi_cur_ptr (iter)
     return a pointer to the beginning of the current multibyte character.

   mbi_reloc (iter, ptrdiff)
     relocates iterator when the string is moved by ptrdiff bytes.

   mbi_copy (&destiter, &srciter)
     copies srciter to destiter.

   Here are the function prototypes of the macros.

   extern void          mbi_init (mbi_iterator_t iter,
                                  const char *startptr, size_t length);
   extern bool          mbi_avail (mbi_iterator_t iter);
   extern void          mbi_advance (mbi_iterator_t iter);
   extern mbchar_t      mbi_cur (mbi_iterator_t iter);
   extern const char *  mbi_cur_ptr (mbi_iterator_t iter);
   extern void          mbi_reloc (mbi_iterator_t iter, ptrdiff_t ptrdiff);
   extern void          mbi_copy (mbi_iterator_t *new, const mbi_iterator_t *old);
 */

#ifndef _MBITER_H
#define _MBITER_H 1

#include <assert.h>
#include <stdbool.h>
#include <stddef.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 "mbchar.h"

#ifndef _GL_INLINE_HEADER_BEGIN
 #error "Please include config.h first."
#endif
_GL_INLINE_HEADER_BEGIN
#ifndef MBITER_INLINE
# define MBITER_INLINE _GL_INLINE
#endif

struct mbiter_multi
{
  const char *limit;    /* pointer to end of string */
  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 mbi_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 mbi_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
        */
};

MBITER_INLINE void
mbiter_multi_next (struct mbiter_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,
                                 iter->limit - iter->cur.ptr, &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 = iter->limit - 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;
}

MBITER_INLINE void
mbiter_multi_reloc (struct mbiter_multi *iter, ptrdiff_t ptrdiff)
{
  iter->cur.ptr += ptrdiff;
  iter->limit += ptrdiff;
}

MBITER_INLINE void
mbiter_multi_copy (struct mbiter_multi *new_iter, const struct mbiter_multi *old_iter)
{
  new_iter->limit = old_iter->limit;
  if ((new_iter->in_shift = old_iter->in_shift))
    memcpy (&new_iter->state, &old_iter->state, sizeof (mbstate_t));
  else
    memset (&new_iter->state, 0, sizeof (mbstate_t));
  new_iter->next_done = old_iter->next_done;
  mb_copy (&new_iter->cur, &old_iter->cur);
}

/* Iteration macros.  */
typedef struct mbiter_multi mbi_iterator_t;
#define mbi_init(iter, startptr, length) \
  ((iter).cur.ptr = (startptr), (iter).limit = (iter).cur.ptr + (length), \
   (iter).in_shift = false, memset (&(iter).state, '\0', sizeof (mbstate_t)), \
   (iter).next_done = false)
#define mbi_avail(iter) \
  ((iter).cur.ptr < (iter).limit && (mbiter_multi_next (&(iter)), true))
#define mbi_advance(iter) \
  ((iter).cur.ptr += (iter).cur.bytes, (iter).next_done = false)

/* Access to the current character.  */
#define mbi_cur(iter) (iter).cur
#define mbi_cur_ptr(iter) (iter).cur.ptr

/* Relocation.  */
#define mbi_reloc(iter, ptrdiff) mbiter_multi_reloc (&iter, ptrdiff)

/* Copying an iterator.  */
#define mbi_copy mbiter_multi_copy

_GL_INLINE_HEADER_END

#endif /* _MBITER_H */


code:
/* Convert multibyte character to wide character.
   Copyright (C) 1999-2002, 2005-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2008.

   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/>.  */

#include <config.h>

/* Specification.  */
#include <wchar.h>

#if C_LOCALE_MAYBE_EILSEQ
# include "hard-locale.h"
# include <locale.h>
#endif

#if GNULIB_defined_mbstate_t
/* Implement mbrtowc() on top of mbtowc().  */

# include <errno.h>
# include <stdlib.h>

# include "localcharset.h"
# include "streq.h"
# include "verify.h"

verify (sizeof (mbstate_t) >= 4);

static char internal_state[4];

size_t
mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
{
  char *pstate = (char *)ps;

  if (s == NULL)
    {
      pwc = NULL;
      s = "";
      n = 1;
    }

  if (n == 0)
    return (size_t)(-2);

  /* Here n > 0.  */

  if (pstate == NULL)
    pstate = internal_state;

  {
    size_t nstate = pstate[0];
    char buf[4];
    const char *p;
    size_t m;

    switch (nstate)
      {
      case 0:
        p = s;
        m = n;
        break;
      case 3:
        buf[2] = pstate[3];
        /*FALLTHROUGH*/
      case 2:
        buf[1] = pstate[2];
        /*FALLTHROUGH*/
      case 1:
        buf[0] = pstate[1];
        p = buf;
        m = nstate;
        buf[m++] = s[0];
        if (n >= 2 && m < 4)
          {
            buf[m++] = s[1];
            if (n >= 3 && m < 4)
              buf[m++] = s[2];
          }
        break;
      default:
        errno = EINVAL;
        return (size_t)(-1);
      }

    /* Here m > 0.  */

# if __GLIBC__ || defined __UCLIBC__
    /* Work around bug <http://sourceware.org/bugzilla/show_bug.cgi?id=9674> */
    mbtowc (NULL, NULL, 0);
# endif
    {
      int res = mbtowc (pwc, p, m);

      if (res >= 0)
        {
          if (pwc != NULL && ((*pwc == 0) != (res == 0)))
            abort ();
          if (nstate >= (res > 0 ? res : 1))
            abort ();
          res -= nstate;
          pstate[0] = 0;
          return res;
        }

      /* mbtowc does not distinguish between invalid and incomplete multibyte
         sequences.  But mbrtowc needs to make this distinction.
         There are two possible approaches:
           - Use iconv() and its return value.
           - Use built-in knowledge about the possible encodings.
         Given the low quality of implementation of iconv() on the systems that
         lack mbrtowc(), we use the second approach.
         The possible encodings are:
           - 8-bit encodings,
           - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS,
           - UTF-8.
         Use specialized code for each.  */
      if (m >= 4 || m >= MB_CUR_MAX)
        goto invalid;
      /* Here MB_CUR_MAX > 1 and 0 < m < 4.  */
      {
        const char *encoding = locale_charset ();

        if (STREQ_OPT (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0))
          {
            /* Cf. unistr/u8-mblen.c.  */
            unsigned char c = (unsigned char) p[0];

            if (c >= 0xc2)
              {
                if (c < 0xe0)
                  {
                    if (m == 1)
                      goto incomplete;
                  }
                else if (c < 0xf0)
                  {
                    if (m == 1)
                      goto incomplete;
                    if (m == 2)
                      {
                        unsigned char c2 = (unsigned char) p[1];

                        if ((c2 ^ 0x80) < 0x40
                            && (c >= 0xe1 || c2 >= 0xa0)
                            && (c != 0xed || c2 < 0xa0))
                          goto incomplete;
                      }
                  }
                else if (c <= 0xf4)
                  {
                    if (m == 1)
                      goto incomplete;
                    else /* m == 2 || m == 3 */
                      {
                        unsigned char c2 = (unsigned char) p[1];

                        if ((c2 ^ 0x80) < 0x40
                            && (c >= 0xf1 || c2 >= 0x90)
                            && (c < 0xf4 || (c == 0xf4 && c2 < 0x90)))
                          {
                            if (m == 2)
                              goto incomplete;
                            else /* m == 3 */
                              {
                                unsigned char c3 = (unsigned char) p[2];

                                if ((c3 ^ 0x80) < 0x40)
                                  goto incomplete;
                              }
                          }
                      }
                  }
              }
            goto invalid;
          }

        /* As a reference for this code, you can use the GNU libiconv
           implementation.  Look for uses of the RET_TOOFEW macro.  */

        if (STREQ_OPT (encoding,
                       "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0))
          {
            if (m == 1)
              {
                unsigned char c = (unsigned char) p[0];

                if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f)
                  goto incomplete;
              }
            if (m == 2)
              {
                unsigned char c = (unsigned char) p[0];

                if (c == 0x8f)
                  {
                    unsigned char c2 = (unsigned char) p[1];

                    if (c2 >= 0xa1 && c2 < 0xff)
                      goto incomplete;
                  }
              }
            goto invalid;
          }
        if (STREQ_OPT (encoding,
                       "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0)
            || STREQ_OPT (encoding,
                          "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0)
            || STREQ_OPT (encoding,
                          "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0))
          {
            if (m == 1)
              {
                unsigned char c = (unsigned char) p[0];

                if (c >= 0xa1 && c < 0xff)
                  goto incomplete;
              }
            goto invalid;
          }
        if (STREQ_OPT (encoding,
                       "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0))
          {
            if (m == 1)
              {
                unsigned char c = (unsigned char) p[0];

                if ((c >= 0xa1 && c < 0xff) || c == 0x8e)
                  goto incomplete;
              }
            else /* m == 2 || m == 3 */
              {
                unsigned char c = (unsigned char) p[0];

                if (c == 0x8e)
                  goto incomplete;
              }
            goto invalid;
          }
        if (STREQ_OPT (encoding,
                       "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0))
          {
            if (m == 1)
              {
                unsigned char c = (unsigned char) p[0];

                if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe))
                  goto incomplete;
              }
            else /* m == 2 || m == 3 */
              {
                unsigned char c = (unsigned char) p[0];

                if (c >= 0x90 && c <= 0xe3)
                  {
                    unsigned char c2 = (unsigned char) p[1];

                    if (c2 >= 0x30 && c2 <= 0x39)
                      {
                        if (m == 2)
                          goto incomplete;
                        else /* m == 3 */
                          {
                            unsigned char c3 = (unsigned char) p[2];

                            if (c3 >= 0x81 && c3 <= 0xfe)
                              goto incomplete;
                          }
                      }
                  }
              }
            goto invalid;
          }
        if (STREQ_OPT (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0))
          {
            if (m == 1)
              {
                unsigned char c = (unsigned char) p[0];

                if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea)
                    || (c >= 0xf0 && c <= 0xf9))
                  goto incomplete;
              }
            goto invalid;
          }

        /* An unknown multibyte encoding.  */
        goto incomplete;
      }

     incomplete:
      {
        size_t k = nstate;
        /* Here 0 <= k < m < 4.  */
        pstate[++k] = s[0];
        if (k < m)
          {
            pstate[++k] = s[1];
            if (k < m)
              pstate[++k] = s[2];
          }
        if (k != m)
          abort ();
      }
      pstate[0] = m;
      return (size_t)(-2);

     invalid:
      errno = EILSEQ;
      /* The conversion state is undefined, says POSIX.  */
      return (size_t)(-1);
    }
  }
}

#else
/* Override the system's mbrtowc() function.  */

# undef mbrtowc

size_t
rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)
{
  size_t ret;
  wchar_t wc;

# if MBRTOWC_NULL_ARG2_BUG || MBRTOWC_RETVAL_BUG || MBRTOWC_EMPTY_INPUT_BUG
  if (s == NULL)
    {
      pwc = NULL;
      s = "";
      n = 1;
    }
# endif

# if MBRTOWC_EMPTY_INPUT_BUG
  if (n == 0)
    return (size_t) -2;
# endif

  if (! pwc)
    pwc = &wc;

# if MBRTOWC_RETVAL_BUG
  {
    static mbstate_t internal_state;

    /* Override mbrtowc's internal state.  We cannot call mbsinit() on the
       hidden internal state, but we can call it on our variable.  */
    if (ps == NULL)
      ps = &internal_state;

    if (!mbsinit (ps))
      {
        /* Parse the rest of the multibyte character byte for byte.  */
        size_t count = 0;
        for (; n > 0; s++, n--)
          {
            ret = mbrtowc (&wc, s, 1, ps);

            if (ret == (size_t)(-1))
              return (size_t)(-1);
            count++;
            if (ret != (size_t)(-2))
              {
                /* The multibyte character has been completed.  */
                *pwc = wc;
                return (wc == 0 ? 0 : count);
              }
          }
        return (size_t)(-2);
      }
  }
# endif

  ret = mbrtowc (pwc, s, n, ps);

# if MBRTOWC_NUL_RETVAL_BUG
  if (ret < (size_t) -2 && !*pwc)
    return 0;
# endif

# if C_LOCALE_MAYBE_EILSEQ
  if ((size_t) -2 <= ret && n != 0 && ! hard_locale (LC_CTYPE))
    {
      unsigned char uc = *s;
      *pwc = uc;
      return 1;
    }
# endif

  return ret;
}

#endif


code:
/* Case-insensitive string comparison function.
   Copyright (C) 1998-1999, 2005-2017 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
   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/>.  */

#include <config.h>

/* Specification.  */
#include <string.h>

#include <ctype.h>
#include <limits.h>

#include "mbuiter.h"

#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))

/* Compare the character 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
mbscasecmp (const char *s1, const char *s2)
{
  if (s1 == s2)
    return 0;

  /* 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 (MB_CUR_MAX > 1)
    {
      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 (cmp != 0)
            return cmp;

          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;
    }
  else
    {
      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);

          if (c1 == '\0')
            break;

          ++p1;
          ++p2;
        }
      while (c1 == c2);

      if (UCHAR_MAX <= INT_MAX)
        return c1 - c2;
      else
        /* On machines where 'char' and 'int' are types of the same size, the
           difference of two 'unsigned char' values - including the sign bit -
           doesn't fit in an 'int'.  */
        return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
    }
}


code:
/* Searching a string for a character.
   Copyright (C) 2007-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2007.

   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/>.  */

#include <config.h>

/* Specification.  */
#include <string.h>

#include "mbuiter.h"

/* Locate the first single-byte character C in the character string STRING,
   and return a pointer to it.  Return NULL if C is not found in STRING.  */
char *
mbschr (const char *string, int c)
{
  if (MB_CUR_MAX > 1
      /* Optimization: We know that ASCII characters < 0x30 don't occur as
         part of multibyte characters longer than 1 byte.  Hence, if c < 0x30,
         the faster unibyte loop can be used.  */
      && (unsigned char) c >= 0x30)
    {
      mbui_iterator_t iter;

      for (mbui_init (iter, string);; mbui_advance (iter))
        {
          if (!mbui_avail (iter))
            goto notfound;
          if (mb_len (mbui_cur (iter)) == 1
              && (unsigned char) * mbui_cur_ptr (iter) == (unsigned char) c)
            break;
        }
      return (char *) mbui_cur_ptr (iter);
     notfound:
      return NULL;
    }
  else
    return strchr (string, c);
}


code:
/* Test for initial conversion state.
   Copyright (C) 2008-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2008.

   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/>.  */

#include <config.h>

/* Specification.  */
#include <wchar.h>

#include "verify.h"

#if GNULIB_defined_mbstate_t

/* Platforms that lack mbsinit() also lack mbrlen(), mbrtowc(), mbsrtowcs()
   and wcrtomb(), wcsrtombs().
   We assume that
     - sizeof (mbstate_t) >= 4,
     - only stateless encodings are supported (such as UTF-8 and EUC-JP, but
       not ISO-2022 variants),
     - for each encoding, the number of bytes for a wide character is <= 4.
       (This maximum is attained for UTF-8, GB18030, EUC-TW.)
   We define the meaning of mbstate_t as follows:
     - In mb -> wc direction, mbstate_t's first byte contains the number of
       buffered bytes (in the range 0..3), followed by up to 3 buffered bytes.
       See mbrtowc.c.
     - In wc -> mb direction, mbstate_t contains no information. In other
       words, it is always in the initial state.  */

verify (sizeof (mbstate_t) >= 4);

int
mbsinit (const mbstate_t *ps)
{
  const char *pstate = (const char *)ps;

  return pstate == NULL || pstate[0] == 0;
}

#else

int
mbsinit (const mbstate_t *ps)
{
# if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
  /* Native Windows.  */
#  ifdef __MINGW32__
  /* On mingw, 'mbstate_t' is defined as 'int'.  */
  return ps == NULL || *ps == 0;
#  else
  /* MSVC defines 'mbstate_t' as an 8-byte struct; the first 4-bytes matter.  */
  return ps == NULL || *(const unsigned int *)ps == 0;
#  endif
# else
  /* Minix, HP-UX 11.00, Solaris 2.6, Interix, ...  */
  /* Maybe this definition works, maybe not...  */
  return ps == NULL || *(const char *)ps == 0;
# endif
}

#endif


code:
/* Counting the multibyte characters in a string.
   Copyright (C) 2007-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2007.

   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/>.  */

#include <config.h>

/* Specification.  */
#include <string.h>

#include <stdlib.h>

#include "mbuiter.h"

/* Return the number of multibyte characters in the character string STRING.  */
size_t
mbslen (const char *string)
{
  if (MB_CUR_MAX > 1)
    {
      size_t count;
      mbui_iterator_t iter;

      count = 0;
      for (mbui_init (iter, string); mbui_avail (iter); mbui_advance (iter))
        count++;

      return count;
    }
  else
    return strlen (string);
}


code:
/* Case-insensitive string comparison function.
   Copyright (C) 1998-1999, 2005-2017 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
   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/>.  */

#include <config.h>

/* Specification.  */
#include <string.h>

#include <ctype.h>
#include <limits.h>

#include "mbuiter.h"

#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch))

/* Compare the initial segment of the character string S1 consisting of at most
   N characters with the initial segment of the character string S2 consisting
   of at most N characters, ignoring case, returning less than, equal to or
   greater than zero if the initial segment of S1 is lexicographically less
   than, equal to or greater than the initial segment of S2.
   Note: This function may, in multibyte locales, return 0 for initial segments
   of different lengths!  */
int
mbsncasecmp (const char *s1, const char *s2, size_t n)
{
  if (s1 == s2 || n == 0)
    return 0;

  /* 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 (MB_CUR_MAX > 1)
    {
      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 (cmp != 0)
            return cmp;

          if (--n == 0)
            return 0;

          mbui_advance (iter1);
          mbui_advance (iter2);
        }
      if (mbui_avail (iter1))
        /* s2 terminated before s1 and n.  */
        return 1;
      if (mbui_avail (iter2))
        /* s1 terminated before s2 and n.  */
        return -1;
      return 0;
    }
  else
    {
      const unsigned char *p1 = (const unsigned char *) s1;
      const unsigned char *p2 = (const unsigned char *) s2;
      unsigned char c1, c2;

      for (; ; p1++, p2++)
        {
          c1 = TOLOWER (*p1);
          c2 = TOLOWER (*p2);

          if (--n == 0 || c1 == '\0' || c1 != c2)
            break;
        }

      if (UCHAR_MAX <= INT_MAX)
        return c1 - c2;
      else
        /* On machines where 'char' and 'int' are types of the same size, the
           difference of two 'unsigned char' values - including the sign bit -
           doesn't fit in an 'int'.  */
        return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0);
    }
}


code:
/* Searching in a string.  -*- coding: utf-8 -*-
   Copyright (C) 2005-2017 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 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/>.  */

#include <config.h>

/* Specification.  */
#include <string.h>

#include <stdbool.h>
#include <stddef.h>  /* for NULL, in case a nonstandard string.h lacks it */

#include "malloca.h"
#include "mbuiter.h"

/* Knuth-Morris-Pratt algorithm.  */
#define UNIT unsigned char
#define CANON_ELEMENT(c) c
#include "str-kmp.h"

/* Knuth-Morris-Pratt algorithm.
   See http://en.wikipedia.org/wiki/Knuth-Morris-Pratt_algorithm
   Return a boolean indicating success:
   Return true and set *RESULTP if the search was completed.
   Return false if it was aborted because not enough memory was available.  */
static bool
knuth_morris_pratt_multibyte (const char *haystack, const char *needle,
                              const char **resultp)
{
  size_t m = mbslen (needle);
  mbchar_t *needle_mbchars;
  size_t *table;

  /* Allocate room for needle_mbchars and the table.  */
  void *memory = nmalloca (m, sizeof (mbchar_t) + sizeof (size_t));
  void *table_memory;
  if (memory == NULL)
    return false;
  needle_mbchars = memory;
  table_memory = needle_mbchars + m;
  table = table_memory;

  /* Fill needle_mbchars.  */
  {
    mbui_iterator_t iter;
    size_t j;

    j = 0;
    for (mbui_init (iter, needle); mbui_avail (iter); mbui_advance (iter), j++)
      mb_copy (&needle_mbchars[j], &mbui_cur (iter));
  }

  /* Fill the table.
     For 0 < i < m:
       0 < table[i] <= i is defined such that
       forall 0 < x < table[i]: needle[x..i-1] != needle[0..i-1-x],
       and table[i] is as large as possible with this property.
     This implies:
     1) For 0 < i < m:
          If table[i] < i,
          needle[table[i]..i-1] = needle[0..i-1-table[i]].
     2) For 0 < i < m:
          rhaystack[0..i-1] == needle[0..i-1]
          and exists h, i <= h < m: rhaystack[h] != needle[h]
          implies
          forall 0 <= x < table[i]: rhaystack[x..x+m-1] != needle[0..m-1].
     table[0] remains uninitialized.  */
  {
    size_t i, j;

    /* i = 1: Nothing to verify for x = 0.  */
    table[1] = 1;
    j = 0;

    for (i = 2; i < m; i++)
      {
        /* Here: j = i-1 - table[i-1].
           The inequality needle[x..i-1] != needle[0..i-1-x] is known to hold
           for x < table[i-1], by induction.
           Furthermore, if j>0: needle[i-1-j..i-2] = needle[0..j-1].  */
        mbchar_t *b = &needle_mbchars[i - 1];

        for (;;)
          {
            /* Invariants: The inequality needle[x..i-1] != needle[0..i-1-x]
               is known to hold for x < i-1-j.
               Furthermore, if j>0: needle[i-1-j..i-2] = needle[0..j-1].  */
            if (mb_equal (*b, needle_mbchars[j]))
              {
                /* Set table[i] := i-1-j.  */
                table[i] = i - ++j;
                break;
              }
            /* The inequality needle[x..i-1] != needle[0..i-1-x] also holds
               for x = i-1-j, because
                 needle[i-1] != needle[j] = needle[i-1-x].  */
            if (j == 0)
              {
                /* The inequality holds for all possible x.  */
                table[i] = i;
                break;
              }
            /* The inequality needle[x..i-1] != needle[0..i-1-x] also holds
               for i-1-j < x < i-1-j+table[j], because for these x:
                 needle[x..i-2]
                 = needle[x-(i-1-j)..j-1]
                 != needle[0..j-1-(x-(i-1-j))]  (by definition of table[j])
                    = needle[0..i-2-x],
               hence needle[x..i-1] != needle[0..i-1-x].
               Furthermore
                 needle[i-1-j+table[j]..i-2]
                 = needle[table[j]..j-1]
                 = needle[0..j-1-table[j]]  (by definition of table[j]).  */
            j = j - table[j];
          }
        /* Here: j = i - table[i].  */
      }
  }

  /* Search, using the table to accelerate the processing.  */
  {
    size_t j;
    mbui_iterator_t rhaystack;
    mbui_iterator_t phaystack;

    *resultp = NULL;
    j = 0;
    mbui_init (rhaystack, haystack);
    mbui_init (phaystack, haystack);
    /* Invariant: phaystack = rhaystack + j.  */
    while (mbui_avail (phaystack))
      if (mb_equal (needle_mbchars[j], mbui_cur (phaystack)))
        {
          j++;
          mbui_advance (phaystack);
          if (j == m)
            {
              /* The entire needle has been found.  */
              *resultp = mbui_cur_ptr (rhaystack);
              break;
            }
        }
      else if (j > 0)
        {
          /* Found a match of needle[0..j-1], mismatch at needle[j].  */
          size_t count = table[j];
          j -= count;
          for (; count > 0; count--)
            {
              if (!mbui_avail (rhaystack))
                abort ();
              mbui_advance (rhaystack);
            }
        }
      else
        {
          /* Found a mismatch at needle[0] already.  */
          if (!mbui_avail (rhaystack))
            abort ();
          mbui_advance (rhaystack);
          mbui_advance (phaystack);
        }
  }

  freea (memory);
  return true;
}

/* Find the first occurrence of the character string NEEDLE in the character
   string HAYSTACK.  Return NULL if NEEDLE is not found in HAYSTACK.  */
char *
mbsstr (const char *haystack, const char *needle)
{
  /* 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 (MB_CUR_MAX > 1)
    {
      mbui_iterator_t iter_needle;

      mbui_init (iter_needle, needle);
      if (mbui_avail (iter_needle))
        {
          /* Minimizing the worst-case complexity:
             Let n = mbslen(haystack), m = mbslen(needle).
             The naïve algorithm is O(n*m) worst-case.
             The Knuth-Morris-Pratt algorithm is O(n) worst-case but it needs a
             memory allocation.
             To achieve linear complexity and yet amortize the cost of the
             memory allocation, we activate the Knuth-Morris-Pratt algorithm
             only once the naïve algorithm has already run for some time; more
             precisely, when
               - the outer loop count is >= 10,
               - the average number of comparisons per outer loop is >= 5,
               - the total number of comparisons is >= m.
             But we try it only once.  If the memory allocation attempt failed,
             we don't retry it.  */
          bool try_kmp = true;
          size_t outer_loop_count = 0;
          size_t comparison_count = 0;
          size_t last_ccount = 0;                  /* last comparison count */
          mbui_iterator_t iter_needle_last_ccount; /* = needle + last_ccount */

          mbui_iterator_t iter_haystack;

          mbui_init (iter_needle_last_ccount, needle);
          mbui_init (iter_haystack, haystack);
          for (;; mbui_advance (iter_haystack))
            {
              if (!mbui_avail (iter_haystack))
                /* No match.  */
                return NULL;

              /* See whether it's advisable to use an asymptotically faster
                 algorithm.  */
              if (try_kmp
                  && outer_loop_count >= 10
                  && comparison_count >= 5 * outer_loop_count)
                {
                  /* See if needle + comparison_count now reaches the end of
                     needle.  */
                  size_t count = comparison_count - last_ccount;
                  for (;
                       count > 0 && mbui_avail (iter_needle_last_ccount);
                       count--)
                    mbui_advance (iter_needle_last_ccount);
                  last_ccount = comparison_count;
                  if (!mbui_avail (iter_needle_last_ccount))
                    {
                      /* Try the Knuth-Morris-Pratt algorithm.  */
                      const char *result;
                      bool success =
                        knuth_morris_pratt_multibyte (haystack, needle,
                                                      &result);
                      if (success)
                        return (char *) result;
                      try_kmp = false;
                    }
                }

              outer_loop_count++;
              comparison_count++;
              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;
                      comparison_count++;
                      if (!mb_equal (mbui_cur (rhaystack), mbui_cur (rneedle)))
                        /* Nothing in this round.  */
                        break;
                    }
                }
            }
        }
      else
        return (char *) haystack;
    }
  else
    {
      if (*needle != '\0')
        {
          /* Minimizing the worst-case complexity:
             Let n = strlen(haystack), m = strlen(needle).
             The naïve algorithm is O(n*m) worst-case.
             The Knuth-Morris-Pratt algorithm is O(n) worst-case but it needs a
             memory allocation.
             To achieve linear complexity and yet amortize the cost of the
             memory allocation, we activate the Knuth-Morris-Pratt algorithm
             only once the naïve algorithm has already run for some time; more
             precisely, when
               - the outer loop count is >= 10,
               - the average number of comparisons per outer loop is >= 5,
               - the total number of comparisons is >= m.
             But we try it only once.  If the memory allocation attempt failed,
             we don't retry it.  */
          bool try_kmp = true;
          size_t outer_loop_count = 0;
          size_t comparison_count = 0;
          size_t last_ccount = 0;                  /* last comparison count */
          const char *needle_last_ccount = needle; /* = needle + last_ccount */

          /* Speed up the following searches of needle by caching its first
             character.  */
          char b = *needle++;

          for (;; haystack++)
            {
              if (*haystack == '\0')
                /* No match.  */
                return NULL;

              /* See whether it's advisable to use an asymptotically faster
                 algorithm.  */
              if (try_kmp
                  && outer_loop_count >= 10
                  && comparison_count >= 5 * outer_loop_count)
                {
                  /* See if needle + comparison_count now reaches the end of
                     needle.  */
                  if (needle_last_ccount != NULL)
                    {
                      needle_last_ccount +=
                        strnlen (needle_last_ccount,
                                 comparison_count - last_ccount);
                      if (*needle_last_ccount == '\0')
                        needle_last_ccount = NULL;
                      last_ccount = comparison_count;
                    }
                  if (needle_last_ccount == NULL)
                    {
                      /* Try the Knuth-Morris-Pratt algorithm.  */
                      const unsigned char *result;
                      bool success =
                        knuth_morris_pratt ((const unsigned char *) haystack,
                                            (const unsigned char *) (needle - 1),
                                            strlen (needle - 1),
                                            &result);
                      if (success)
                        return (char *) result;
                      try_kmp = false;
                    }
                }

              outer_loop_count++;
              comparison_count++;
              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;
                      comparison_count++;
                      if (*rhaystack != *rneedle)
                        /* Nothing in this round.  */
                        break;
                    }
                }
            }
        }
      else
        return (char *) haystack;
    }
}


code:
/* Determine the number of screen columns needed for a string.
   Copyright (C) 2000-2017 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 Bruno Haible <haible@clisp.cons.org>.  */

#include <config.h>

/* Specification.  */
#include "mbswidth.h"

/* Get MB_CUR_MAX.  */
#include <stdlib.h>

#include <string.h>

/* Get isprint().  */
#include <ctype.h>

/* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth().  */
#include <wchar.h>

/* Get iswcntrl().  */
#include <wctype.h>

/* Get INT_MAX.  */
#include <limits.h>

/* Returns the number of columns needed to represent the multibyte
   character string pointed to by STRING.  If a non-printable character
   occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned.
   With flags = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE, this is
   the multibyte analogue of the wcswidth function.  */
int
mbswidth (const char *string, int flags)
{
  return mbsnwidth (string, strlen (string), flags);
}

/* Returns the number of columns needed to represent the multibyte
   character string pointed to by STRING of length NBYTES.  If a
   non-printable character occurs, and MBSW_REJECT_UNPRINTABLE is
   specified, -1 is returned.  */
int
mbsnwidth (const char *string, size_t nbytes, int flags)
{
  const char *p = string;
  const char *plimit = p + nbytes;
  int width;

  width = 0;
  if (MB_CUR_MAX > 1)
    {
      while (p < plimit)
        switch (*p)
          {
            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 '~':
              /* These characters are printable ASCII characters.  */
              p++;
              width++;
              break;
            default:
              /* If we have a multibyte sequence, scan it up to its end.  */
              {
                mbstate_t mbstate;
                memset (&mbstate, 0, sizeof mbstate);
                do
                  {
                    wchar_t wc;
                    size_t bytes;
                    int w;

                    bytes = mbrtowc (&wc, p, plimit - p, &mbstate);

                    if (bytes == (size_t) -1)
                      /* An invalid multibyte sequence was encountered.  */
                      {
                        if (!(flags & MBSW_REJECT_INVALID))
                          {
                            p++;
                            width++;
                            break;
                          }
                        else
                          return -1;
                      }

                    if (bytes == (size_t) -2)
                      /* An incomplete multibyte character at the end.  */
                      {
                        if (!(flags & MBSW_REJECT_INVALID))
                          {
                            p = plimit;
                            width++;
                            break;
                          }
                        else
                          return -1;
                      }

                    if (bytes == 0)
                      /* A null wide character was encountered.  */
                      bytes = 1;

                    w = wcwidth (wc);
                    if (w >= 0)
                      /* A printable multibyte character.  */
                      {
                        if (w > INT_MAX - width)
                          goto overflow;
                        width += w;
                      }
                    else
                      /* An unprintable multibyte character.  */
                      if (!(flags & MBSW_REJECT_UNPRINTABLE))
                        {
                          if (!iswcntrl (wc))
                            {
                              if (width == INT_MAX)
                                goto overflow;
                              width++;
                            }
                        }
                      else
                        return -1;

                    p += bytes;
                  }
                while (! mbsinit (&mbstate));
              }
              break;
          }
      return width;
    }

  while (p < plimit)
    {
      unsigned char c = (unsigned char) *p++;

      if (isprint (c))
        {
          if (width == INT_MAX)
            goto overflow;
          width++;
        }
      else if (!(flags & MBSW_REJECT_UNPRINTABLE))
        {
          if (!iscntrl (c))
            {
              if (width == INT_MAX)
                goto overflow;
              width++;
            }
        }
      else
        return -1;
    }
  return width;

 overflow:
  return INT_MAX;
}


code:
/* Determine the number of screen columns needed for a string.
   Copyright (C) 2000-2004, 2007, 2009-2017 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/>.  */

#include <stddef.h>

/* Avoid a clash of our mbswidth() with a function of the same name defined
   in UnixWare 7.1.1 <wchar.h>.  We need this #include before the #define
   below.
   However, we don't want to #include <wchar.h> on all platforms because
   - 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>.  */
#if HAVE_DECL_MBSWIDTH_IN_WCHAR_H
# include <wchar.h>
#endif

#ifdef __cplusplus
extern "C" {
#endif

/* Optional flags to influence mbswidth/mbsnwidth behavior.  */

/* If this bit is set, return -1 upon finding an invalid or incomplete
   character.  Otherwise, assume invalid characters have width 1.  */
#define MBSW_REJECT_INVALID 1

/* If this bit is set, return -1 upon finding a non-printable character.
   Otherwise, assume unprintable characters have width 0 if they are
   control characters and 1 otherwise.  */
#define MBSW_REJECT_UNPRINTABLE 2

/* Returns the number of screen columns needed for STRING.  */
#define mbswidth gnu_mbswidth  /* avoid clash with UnixWare 7.1.1 function */
extern int mbswidth (const char *string, int flags);

/* Returns the number of screen columns needed for the NBYTES bytes
   starting at BUF.  */
extern int mbsnwidth (const char *buf, size_t nbytes, int flags);

#ifdef __cplusplus
}
#endif


code:
/* Convert multibyte character to wide character.
   Copyright (C) 2011-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2011.

   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/>.  */

/* We don't need a static internal state, because the encoding is not state
   dependent, and when mbrtowc returns (size_t)(-2). we throw the result
   away. */

int
mbtowc (wchar_t *pwc, const char *s, size_t n)
{
  if (s == NULL)
    return 0;
  else
    {
      mbstate_t state;
      wchar_t wc;
      size_t result;

      memset (&state, 0, sizeof (mbstate_t));
      result = mbrtowc (&wc, s, n, &state);
      if (result == (size_t)-1 || result == (size_t)-2)
        {
          errno = EILSEQ;
          return -1;
        }
      if (pwc != NULL)
        *pwc = wc;
      return (wc == 0 ? 0 : result);
    }
}


code:
/* Convert multibyte character to wide character.
   Copyright (C) 2011-2017 Free Software Foundation, Inc.
   Written by Bruno Haible <bruno@clisp.org>, 2011.

   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/>.  */

#include <config.h>

#include <stdlib.h>

#include <errno.h>
#include <string.h>
#include <wchar.h>

#include "mbtowc-impl.h"


code:
#include <config.h>
#define MBUITER_INLINE _GL_EXTERN_INLINE
#include "mbuiter.h"