⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vasnprintf.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- buffer-read-only: t -*- vi: set ro: *//* DO NOT EDIT! GENERATED AUTOMATICALLY! *//* vsprintf with automatic memory allocation.   Copyright (C) 1999, 2002-2008 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, write to the Free Software Foundation,   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  *//* This file can be parametrized with the following macros:     VASNPRINTF         The name of the function being defined.     FCHAR_T            The element type of the format string.     DCHAR_T            The element type of the destination (result) string.     FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters                        in the format string are ASCII. MUST be set if                        FCHAR_T and DCHAR_T are not the same type.     DIRECTIVE          Structure denoting a format directive.                        Depends on FCHAR_T.     DIRECTIVES         Structure denoting the set of format directives of a                        format string.  Depends on FCHAR_T.     PRINTF_PARSE       Function that parses a format string.                        Depends on FCHAR_T.     DCHAR_CPY          memcpy like function for DCHAR_T[] arrays.     DCHAR_SET          memset like function for DCHAR_T[] arrays.     DCHAR_MBSNLEN      mbsnlen like function for DCHAR_T[] arrays.     SNPRINTF           The system's snprintf (or similar) function.                        This may be either snprintf or swprintf.     TCHAR_T            The element type of the argument and result string                        of the said SNPRINTF function.  This may be either                        char or wchar_t.  The code exploits that                        sizeof (TCHAR_T) | sizeof (DCHAR_T) and                        alignof (TCHAR_T) <= alignof (DCHAR_T).     DCHAR_IS_TCHAR     Set to 1 if DCHAR_T and TCHAR_T are the same type.     DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].     DCHAR_IS_UINT8_T   Set to 1 if DCHAR_T is uint8_t.     DCHAR_IS_UINT16_T  Set to 1 if DCHAR_T is uint16_t.     DCHAR_IS_UINT32_T  Set to 1 if DCHAR_T is uint32_t.  *//* Tell glibc's <stdio.h> to provide a prototype for snprintf().   This must come before <config.h> because <config.h> may include   <features.h>, and once <features.h> has been included, it's too late.  */#ifndef _GNU_SOURCE# define _GNU_SOURCE    1#endif#ifndef VASNPRINTF# include <config.h>#endif#ifndef IN_LIBINTL# include <alloca.h>#endif/* Specification.  */#ifndef VASNPRINTF# if WIDE_CHAR_VERSION#  include "vasnwprintf.h"# else#  include "vasnprintf.h"# endif#endif#include <locale.h>	/* localeconv() */#include <stdio.h>	/* snprintf(), sprintf() */#include <stdlib.h>	/* abort(), malloc(), realloc(), free() */#include <string.h>	/* memcpy(), strlen() */#include <errno.h>	/* errno */#include <limits.h>	/* CHAR_BIT */#include <float.h>	/* DBL_MAX_EXP, LDBL_MAX_EXP */#if HAVE_NL_LANGINFO# include <langinfo.h>#endif#ifndef VASNPRINTF# if WIDE_CHAR_VERSION#  include "wprintf-parse.h"# else#  include "printf-parse.h"# endif#endif/* Checked size_t computations.  */#include "xsize.h"#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL# include <math.h># include "float+.h"#endif#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL# include <math.h># include "isnand.h"#endif#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL# include <math.h># include "isnanl-nolibm.h"# include "fpucw.h"#endif#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL# include <math.h># include "isnand.h"# include "printf-frexp.h"#endif#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL# include <math.h># include "isnanl-nolibm.h"# include "printf-frexpl.h"# include "fpucw.h"#endif#if HAVE_WCHAR_T# if HAVE_WCSLEN#  define local_wcslen wcslen# else   /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid      a dependency towards this library, here is a local substitute.      Define this substitute only once, even if this file is included      twice in the same compilation unit.  */#  ifndef local_wcslen_defined#   define local_wcslen_defined 1static size_tlocal_wcslen (const wchar_t *s){  const wchar_t *ptr;  for (ptr = s; *ptr != (wchar_t) 0; ptr++)    ;  return ptr - s;}#  endif# endif#endif/* Default parameters.  */#ifndef VASNPRINTF# if WIDE_CHAR_VERSION#  define VASNPRINTF vasnwprintf#  define FCHAR_T wchar_t#  define DCHAR_T wchar_t#  define TCHAR_T wchar_t#  define DCHAR_IS_TCHAR 1#  define DIRECTIVE wchar_t_directive#  define DIRECTIVES wchar_t_directives#  define PRINTF_PARSE wprintf_parse#  define DCHAR_CPY wmemcpy# else#  define VASNPRINTF vasnprintf#  define FCHAR_T char#  define DCHAR_T char#  define TCHAR_T char#  define DCHAR_IS_TCHAR 1#  define DIRECTIVE char_directive#  define DIRECTIVES char_directives#  define PRINTF_PARSE printf_parse#  define DCHAR_CPY memcpy# endif#endif#if WIDE_CHAR_VERSION  /* TCHAR_T is wchar_t.  */# define USE_SNPRINTF 1# if HAVE_DECL__SNWPRINTF   /* On Windows, the function swprintf() has a different signature than      on Unix; we use the _snwprintf() function instead.  */#  define SNPRINTF _snwprintf# else   /* Unix.  */#  define SNPRINTF swprintf# endif#else  /* TCHAR_T is char.  */# /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.     But don't use it on BeOS, since BeOS snprintf produces no output if the     size argument is >= 0x3000000.  */# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__#  define USE_SNPRINTF 1# else#  define USE_SNPRINTF 0# endif# if HAVE_DECL__SNPRINTF   /* Windows.  */#  define SNPRINTF _snprintf# else   /* Unix.  */#  define SNPRINTF snprintf   /* Here we need to call the native snprintf, not rpl_snprintf.  */#  undef snprintf# endif#endif/* Here we need to call the native sprintf, not rpl_sprintf.  */#undef sprintf#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL/* Determine the decimal-point character according to the current locale.  */# ifndef decimal_point_char_defined#  define decimal_point_char_defined 1static chardecimal_point_char (){  const char *point;  /* Determine it in a multithread-safe way.  We know nl_langinfo is     multithread-safe on glibc systems, but is not required to be multithread-     safe by POSIX.  sprintf(), however, is multithread-safe.  localeconv()     is rarely multithread-safe.  */#  if HAVE_NL_LANGINFO && __GLIBC__  point = nl_langinfo (RADIXCHAR);#  elif 1  char pointbuf[5];  sprintf (pointbuf, "%#.0f", 1.0);  point = &pointbuf[1];#  else  point = localeconv () -> decimal_point;#  endif  /* The decimal point is always a single byte: either '.' or ','.  */  return (point[0] != '\0' ? point[0] : '.');}# endif#endif#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL/* Equivalent to !isfinite(x) || x == 0, but does not require libm.  */static intis_infinite_or_zero (double x){  return isnand (x) || x + x == x;}#endif#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL/* Equivalent to !isfinite(x), but does not require libm.  */static intis_infinitel (long double x){  return isnanl (x) || (x + x == x && x != 0.0L);}#endif#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL/* Converting 'long double' to decimal without rare rounding bugs requires   real bignums.  We use the naming conventions of GNU gmp, but vastly simpler   (and slower) algorithms.  */typedef unsigned int mp_limb_t;# define GMP_LIMB_BITS 32typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1];typedef unsigned long long mp_twolimb_t;# define GMP_TWOLIMB_BITS 64typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1];/* Representation of a bignum >= 0.  */typedef struct{  size_t nlimbs;  mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc().  */} mpn_t;/* Compute the product of two bignums >= 0.   Return the allocated memory in case of success, NULL in case of memory   allocation failure.  */static void *multiply (mpn_t src1, mpn_t src2, mpn_t *dest){  const mp_limb_t *p1;  const mp_limb_t *p2;  size_t len1;  size_t len2;  if (src1.nlimbs <= src2.nlimbs)    {      len1 = src1.nlimbs;      p1 = src1.limbs;      len2 = src2.nlimbs;      p2 = src2.limbs;    }  else    {      len1 = src2.nlimbs;      p1 = src2.limbs;      len2 = src1.nlimbs;      p2 = src1.limbs;    }  /* Now 0 <= len1 <= len2.  */  if (len1 == 0)    {      /* src1 or src2 is zero.  */      dest->nlimbs = 0;      dest->limbs = (mp_limb_t *) malloc (1);    }  else    {      /* Here 1 <= len1 <= len2.  */      size_t dlen;      mp_limb_t *dp;      size_t k, i, j;      dlen = len1 + len2;      dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));      if (dp == NULL)	return NULL;      for (k = len2; k > 0; )	dp[--k] = 0;      for (i = 0; i < len1; i++)	{	  mp_limb_t digit1 = p1[i];	  mp_twolimb_t carry = 0;	  for (j = 0; j < len2; j++)	    {	      mp_limb_t digit2 = p2[j];	      carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;	      carry += dp[i + j];	      dp[i + j] = (mp_limb_t) carry;	      carry = carry >> GMP_LIMB_BITS;	    }	  dp[i + len2] = (mp_limb_t) carry;	}      /* Normalise.  */      while (dlen > 0 && dp[dlen - 1] == 0)	dlen--;      dest->nlimbs = dlen;      dest->limbs = dp;    }  return dest->limbs;}/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.   a is written as  a = q * b + r  with 0 <= r < b.  q is the quotient, r   the remainder.   Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,   q is incremented.   Return the allocated memory in case of success, NULL in case of memory   allocation failure.  */static void *divide (mpn_t a, mpn_t b, mpn_t *q){  /* Algorithm:     First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]     with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).     If m<n, then q:=0 and r:=a.     If m>=n=1, perform a single-precision division:       r:=0, j:=m,       while j>0 do         {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =               = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}         j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].       Normalise [q[m-1],...,q[0]], yields q.     If m>=n>1, perform a multiple-precision division:       We have a/b < beta^(m-n+1).       s:=intDsize-1-(hightest bit in b[n-1]), 0<=s<intDsize.       Shift a and b left by s bits, copying them. r:=a.       r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.       For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}         Compute q* :           q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).           In case of overflow (q* >= beta) set q* := beta-1.           Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]           and c3 := b[n-2] * q*.           {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow            occurred.  Furthermore 0 <= c3 < beta^2.            If there was overflow and            r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,            the next test can be skipped.}           While c3 > c2, {Here 0 <= c2 < c3 < beta^2}             Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].           If q* > 0:             Put r := r - b * q* * beta^j. In detail:               [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].               hence: u:=0, for i:=0 to n-1 do                              u := u + q* * b[i],                              r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),                              u:=u div beta (+ 1, if carry in subtraction)                      r[n+j]:=r[n+j]-u.               {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1                               < q* + 1 <= beta,                the carry u does not overflow.}             If a negative carry occurs, put q* := q* - 1               and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].         Set q[j] := q*.       Normalise [q[m-n],..,q[0]]; this yields the quotient q.       Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the       rest r.       The room for q[j] can be allocated at the memory location of r[n+j].     Finally, round-to-even:       Shift r left by 1 bit.       If r > b or if r = b and q[0] is odd, q := q+1.   */  const mp_limb_t *a_ptr = a.limbs;  size_t a_len = a.nlimbs;  const mp_limb_t *b_ptr = b.limbs;  size_t b_len = b.nlimbs;  mp_limb_t *roomptr;  mp_limb_t *tmp_roomptr = NULL;  mp_limb_t *q_ptr;  size_t q_len;  mp_limb_t *r_ptr;  size_t r_len;  /* Allocate room for a_len+2 digits.     (Need a_len+1 digits for the real division and 1 more digit for the     final rounding of q.)  */  roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));  if (roomptr == NULL)    return NULL;  /* Normalise a.  */  while (a_len > 0 && a_ptr[a_len - 1] == 0)    a_len--;  /* Normalise b.  */  for (;;)    {      if (b_len == 0)	/* Division by zero.  */	abort ();      if (b_ptr[b_len - 1] == 0)	b_len--;      else	break;    }  /* Here m = a_len >= 0 and n = b_len > 0.  */  if (a_len < b_len)    {      /* m<n: trivial case.  q=0, r := copy of a.  */      r_ptr = roomptr;      r_len = a_len;      memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));      q_ptr = roomptr + a_len;      q_len = 0;    }  else if (b_len == 1)    {      /* n=1: single precision division.	 beta^(m-1) <= a < beta^m  ==>  beta^(m-2) <= a/b < beta^m  */      r_ptr = roomptr;      q_ptr = roomptr + 1;      {	mp_limb_t den = b_ptr[0];	mp_limb_t remainder = 0;	const mp_limb_t *sourceptr = a_ptr + a_len;	mp_limb_t *destptr = q_ptr + a_len;	size_t count;	for (count = a_len; count > 0; count--)	  {	    mp_twolimb_t num =	      ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;	    *--destptr = num / den;	    remainder = num % den;	  }	/* Normalise and store r.  */	if (remainder > 0)	  {	    r_ptr[0] = remainder;	    r_len = 1;	  }	else	  r_len = 0;	/* Normalise q.  */	q_len = a_len;	if (q_ptr[q_len - 1] == 0)	  q_len--;      }    }  else    {      /* n>1: multiple precision division.	 beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n  ==>	 beta^(m-n-1) <= a/b < beta^(m-n+1).  */      /* Determine s.  */      size_t s;      {	mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */	s = 31;	if (msd >= 0x10000)	  {	    msd = msd >> 16;	    s -= 16;	  }	if (msd >= 0x100)	  {	    msd = msd >> 8;	    s -= 8;	  }	if (msd >= 0x10)	  {	    msd = msd >> 4;	    s -= 4;	  }	if (msd >= 0x4)	  {	    msd = msd >> 2;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -