Blame locale/weight.h

Packit 6c4009
/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
   Written by Ulrich Drepper, <drepper@cygnus.com>.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#ifndef _WEIGHT_H_
Packit 6c4009
#define _WEIGHT_H_	1
Packit 6c4009
Packit 6c4009
#include <libc-diag.h>
Packit 6c4009
Packit 6c4009
/* Find index of weight.  */
Packit 6c4009
static inline int32_t __attribute__ ((always_inline))
Packit 6c4009
findidx (const int32_t *table,
Packit 6c4009
	 const int32_t *indirect,
Packit 6c4009
	 const unsigned char *extra,
Packit 6c4009
	 const unsigned char **cpp, size_t len)
Packit 6c4009
{
Packit 6c4009
  int_fast32_t i = table[*(*cpp)++];
Packit 6c4009
  const unsigned char *cp;
Packit 6c4009
  const unsigned char *usrc;
Packit 6c4009
Packit 6c4009
  if (i >= 0)
Packit 6c4009
    /* This is an index into the weight table.  Cool.  */
Packit 6c4009
    return i;
Packit 6c4009
Packit 6c4009
  /* Oh well, more than one sequence starting with this byte.
Packit 6c4009
     Search for the correct one.  */
Packit 6c4009
  cp = &extra[-i];
Packit 6c4009
  usrc = *cpp;
Packit 6c4009
  --len;
Packit 6c4009
  while (1)
Packit 6c4009
    {
Packit 6c4009
      size_t nhere;
Packit 6c4009
Packit 6c4009
      /* The first thing is the index.  */
Packit 6c4009
      i = *((const int32_t *) cp);
Packit 6c4009
      cp += sizeof (int32_t);
Packit 6c4009
Packit 6c4009
      /* Next is the length of the byte sequence.  These are always
Packit 6c4009
	 short byte sequences so there is no reason to call any
Packit 6c4009
	 function (even if they are inlined).  */
Packit 6c4009
      nhere = *cp++;
Packit 6c4009
Packit 6c4009
      if (i >= 0)
Packit 6c4009
	{
Packit 6c4009
	  /* It is a single character.  If it matches we found our
Packit 6c4009
	     index.  Note that at the end of each list there is an
Packit 6c4009
	     entry of length zero which represents the single byte
Packit 6c4009
	     sequence.  The first (and here only) byte was tested
Packit 6c4009
	     already.  */
Packit 6c4009
	  size_t cnt;
Packit 6c4009
Packit 6c4009
	  /* With GCC 5.3 when compiling with -Os the compiler warns
Packit 6c4009
	     that seq2.back_us, which becomes usrc, might be used
Packit 6c4009
	     uninitialized.  This can't be true because we pass a length
Packit 6c4009
	     of -1 for len at the same time which means that this loop
Packit 6c4009
	     never executes.  */
Packit 6c4009
	  DIAG_PUSH_NEEDS_COMMENT;
Packit 6c4009
	  DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
Packit 6c4009
	  for (cnt = 0; cnt < nhere && cnt < len; ++cnt)
Packit 6c4009
	    if (cp[cnt] != usrc[cnt])
Packit 6c4009
	      break;
Packit 6c4009
	  DIAG_POP_NEEDS_COMMENT;
Packit 6c4009
Packit 6c4009
	  if (cnt == nhere)
Packit 6c4009
	    {
Packit 6c4009
	      /* Found it.  */
Packit 6c4009
	      *cpp += nhere;
Packit 6c4009
	      return i;
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  /* Up to the next entry.  */
Packit 6c4009
	  cp += nhere;
Packit 6c4009
	  if (!LOCFILE_ALIGNED_P (1 + nhere))
Packit 6c4009
	    cp += LOCFILE_ALIGN - (1 + nhere) % LOCFILE_ALIGN;
Packit 6c4009
	}
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  /* This is a range of characters.  First decide whether the
Packit 6c4009
	     current byte sequence lies in the range.  */
Packit 6c4009
	  size_t cnt;
Packit 6c4009
	  size_t offset = 0;
Packit 6c4009
Packit 6c4009
	  for (cnt = 0; cnt < nhere && cnt < len; ++cnt)
Packit 6c4009
	    if (cp[cnt] != usrc[cnt])
Packit 6c4009
	      break;
Packit 6c4009
Packit 6c4009
	  if (cnt != nhere)
Packit 6c4009
	    {
Packit 6c4009
	      if (cnt == len || cp[cnt] > usrc[cnt])
Packit 6c4009
		{
Packit 6c4009
		  /* Cannot be in this range.  */
Packit 6c4009
		  cp += 2 * nhere;
Packit 6c4009
		  if (!LOCFILE_ALIGNED_P (1 + 2 * nhere))
Packit 6c4009
		    cp += (LOCFILE_ALIGN
Packit 6c4009
			   - (1 + 2 * nhere) % LOCFILE_ALIGN);
Packit 6c4009
		  continue;
Packit 6c4009
		}
Packit 6c4009
Packit 6c4009
	      /* Test against the end of the range.  */
Packit 6c4009
	      for (cnt = 0; cnt < nhere; ++cnt)
Packit 6c4009
		if (cp[nhere + cnt] != usrc[cnt])
Packit 6c4009
		  break;
Packit 6c4009
Packit 6c4009
	      if (cnt != nhere && cp[nhere + cnt] < usrc[cnt])
Packit 6c4009
		{
Packit 6c4009
		  /* Cannot be in this range.  */
Packit 6c4009
		  cp += 2 * nhere;
Packit 6c4009
		  if (!LOCFILE_ALIGNED_P (1 + 2 * nhere))
Packit 6c4009
		    cp += (LOCFILE_ALIGN
Packit 6c4009
			   - (1 + 2 * nhere) % LOCFILE_ALIGN);
Packit 6c4009
		  continue;
Packit 6c4009
		}
Packit 6c4009
Packit 6c4009
	      /* This range matches the next characters.  Now find
Packit 6c4009
		 the offset in the indirect table.  */
Packit 6c4009
	      for (cnt = 0; cp[cnt] == usrc[cnt]; ++cnt);
Packit 6c4009
Packit 6c4009
	      do
Packit 6c4009
		{
Packit 6c4009
		  offset <<= 8;
Packit 6c4009
		  /* With GCC 7 when compiling with -Os the compiler
Packit 6c4009
		     warns that seq1.back_us and seq2.back_us, which
Packit 6c4009
		     become usrc, might be used uninitialized.  This
Packit 6c4009
		     is impossible for the same reason as described
Packit 6c4009
		     above.  */
Packit 6c4009
		  DIAG_PUSH_NEEDS_COMMENT;
Packit 6c4009
		  DIAG_IGNORE_Os_NEEDS_COMMENT (7, "-Wmaybe-uninitialized");
Packit 6c4009
		  offset += usrc[cnt] - cp[cnt];
Packit 6c4009
		  DIAG_POP_NEEDS_COMMENT;
Packit 6c4009
		}
Packit 6c4009
	      while (++cnt < nhere);
Packit 6c4009
	    }
Packit 6c4009
Packit 6c4009
	  *cpp += nhere;
Packit 6c4009
	  return indirect[-i + offset];
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* NOTREACHED */
Packit 6c4009
  return 0x43219876;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#endif	/* weight.h */