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

📄 vasnprintf.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
	  mpn_t denominator;	  void *tmp_memory;	  tmp_memory = multiply (m, pow5, &numerator);	  if (tmp_memory == NULL)	    {	      free (pow5_ptr);	      free (memory);	      return NULL;	    }	  /* Construct 2^|s|.  */	  {	    mp_limb_t *ptr = pow5_ptr + pow5_len;	    size_t i;	    for (i = 0; i < s_limbs; i++)	      ptr[i] = 0;	    ptr[s_limbs] = (mp_limb_t) 1 << s_bits;	    denominator.limbs = ptr;	    denominator.nlimbs = s_limbs + 1;	  }	  z_memory = divide (numerator, denominator, &z);	  free (tmp_memory);	}      else	{	  /* n < 0, s > 0.	     Multiply m with 2^s, then divide by pow5.  */	  mpn_t numerator;	  mp_limb_t *num_ptr;	  num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)					  * sizeof (mp_limb_t));	  if (num_ptr == NULL)	    {	      free (pow5_ptr);	      free (memory);	      return NULL;	    }	  {	    mp_limb_t *destptr = num_ptr;	    {	      size_t i;	      for (i = 0; i < s_limbs; i++)		*destptr++ = 0;	    }	    if (s_bits > 0)	      {		const mp_limb_t *sourceptr = m.limbs;		mp_twolimb_t accu = 0;		size_t count;		for (count = m.nlimbs; count > 0; count--)		  {		    accu += (mp_twolimb_t) *sourceptr++ << s;		    *destptr++ = (mp_limb_t) accu;		    accu = accu >> GMP_LIMB_BITS;		  }		if (accu > 0)		  *destptr++ = (mp_limb_t) accu;	      }	    else	      {		const mp_limb_t *sourceptr = m.limbs;		size_t count;		for (count = m.nlimbs; count > 0; count--)		  *destptr++ = *sourceptr++;	      }	    numerator.limbs = num_ptr;	    numerator.nlimbs = destptr - num_ptr;	  }	  z_memory = divide (numerator, pow5, &z);	  free (num_ptr);	}    }  free (pow5_ptr);  free (memory);  /* Here y = round (x * 10^n) = z * 10^extra_zeroes.  */  if (z_memory == NULL)    return NULL;  digits = convert_to_decimal (z, extra_zeroes);  free (z_memory);  return digits;}/* Assuming x is finite and > 0:   Return an approximation for n with 10^n <= x < 10^(n+1).   The approximation is usually the right n, but may be off by 1 sometimes.  */static intfloorlog10l (long double x){  int exp;  long double y;  double z;  double l;  /* Split into exponential part and mantissa.  */  y = frexpl (x, &exp);  if (!(y >= 0.0L && y < 1.0L))    abort ();  if (y == 0.0L)    return INT_MIN;  if (y < 0.5L)    {      while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))	{	  y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));	  exp -= GMP_LIMB_BITS;	}      if (y < (1.0L / (1 << 16)))	{	  y *= 1.0L * (1 << 16);	  exp -= 16;	}      if (y < (1.0L / (1 << 8)))	{	  y *= 1.0L * (1 << 8);	  exp -= 8;	}      if (y < (1.0L / (1 << 4)))	{	  y *= 1.0L * (1 << 4);	  exp -= 4;	}      if (y < (1.0L / (1 << 2)))	{	  y *= 1.0L * (1 << 2);	  exp -= 2;	}      if (y < (1.0L / (1 << 1)))	{	  y *= 1.0L * (1 << 1);	  exp -= 1;	}    }  if (!(y >= 0.5L && y < 1.0L))    abort ();  /* Compute an approximation for l = log2(x) = exp + log2(y).  */  l = exp;  z = y;  if (z < 0.70710678118654752444)    {      z *= 1.4142135623730950488;      l -= 0.5;    }  if (z < 0.8408964152537145431)    {      z *= 1.1892071150027210667;      l -= 0.25;    }  if (z < 0.91700404320467123175)    {      z *= 1.0905077326652576592;      l -= 0.125;    }  if (z < 0.9576032806985736469)    {      z *= 1.0442737824274138403;      l -= 0.0625;    }  /* Now 0.95 <= z <= 1.01.  */  z = 1 - z;  /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ...     Four terms are enough to get an approximation with error < 10^-7.  */  l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));  /* Finally multiply with log(2)/log(10), yields an approximation for     log10(x).  */  l *= 0.30102999566398119523;  /* Round down to the next integer.  */  return (int) l + (l < 0 ? -1 : 0);}#endifDCHAR_T *VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,	    const FCHAR_T *format, va_list args){  DIRECTIVES d;  arguments a;  if (PRINTF_PARSE (format, &d, &a) < 0)    {      errno = EINVAL;      return NULL;    }#define CLEANUP() \  free (d.dir);								\  if (a.arg)								\    free (a.arg);  if (PRINTF_FETCHARGS (args, &a) < 0)    {      CLEANUP ();      errno = EINVAL;      return NULL;    }  {    size_t buf_neededlength;    TCHAR_T *buf;    TCHAR_T *buf_malloced;    const FCHAR_T *cp;    size_t i;    DIRECTIVE *dp;    /* Output string accumulator.  */    DCHAR_T *result;    size_t allocated;    size_t length;    /* Allocate a small buffer that will hold a directive passed to       sprintf or snprintf.  */    buf_neededlength =      xsum4 (7, d.max_width_length, d.max_precision_length, 6);#if HAVE_ALLOCA    if (buf_neededlength < 4000 / sizeof (TCHAR_T))      {	buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));	buf_malloced = NULL;      }    else#endif      {	size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));	if (size_overflow_p (buf_memsize))	  goto out_of_memory_1;	buf = (TCHAR_T *) malloc (buf_memsize);	if (buf == NULL)	  goto out_of_memory_1;	buf_malloced = buf;      }    if (resultbuf != NULL)      {	result = resultbuf;	allocated = *lengthp;      }    else      {	result = NULL;	allocated = 0;      }    length = 0;    /* Invariants:       result is either == resultbuf or == NULL or malloc-allocated.       If length > 0, then result != NULL.  */    /* Ensures that allocated >= needed.  Aborts through a jump to       out_of_memory if needed is SIZE_MAX or otherwise too big.  */#define ENSURE_ALLOCATION(needed) \    if ((needed) > allocated)						     \      {									     \	size_t memory_size;						     \	DCHAR_T *memory;						     \									     \	allocated = (allocated > 0 ? xtimes (allocated, 2) : 12);	     \	if ((needed) > allocated)					     \	  allocated = (needed);						     \	memory_size = xtimes (allocated, sizeof (DCHAR_T));		     \	if (size_overflow_p (memory_size))				     \	  goto out_of_memory;						     \	if (result == resultbuf || result == NULL)			     \	  memory = (DCHAR_T *) malloc (memory_size);			     \	else								     \	  memory = (DCHAR_T *) realloc (result, memory_size);		     \	if (memory == NULL)						     \	  goto out_of_memory;						     \	if (result == resultbuf && length > 0)				     \	  DCHAR_CPY (memory, result, length);				     \	result = memory;						     \      }    for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)      {	if (cp != dp->dir_start)	  {	    size_t n = dp->dir_start - cp;	    size_t augmented_length = xsum (length, n);	    ENSURE_ALLOCATION (augmented_length);	    /* This copies a piece of FCHAR_T[] into a DCHAR_T[].  Here we	       need that the format string contains only ASCII characters	       if FCHAR_T and DCHAR_T are not the same type.  */	    if (sizeof (FCHAR_T) == sizeof (DCHAR_T))	      {		DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);		length = augmented_length;	      }	    else	      {		do		  result[length++] = (unsigned char) *cp++;		while (--n > 0);	      }	  }	if (i == d.count)	  break;	/* Execute a single directive.  */	if (dp->conversion == '%')	  {	    size_t augmented_length;	    if (!(dp->arg_index == ARG_NONE))	      abort ();	    augmented_length = xsum (length, 1);	    ENSURE_ALLOCATION (augmented_length);	    result[length] = '%';	    length = augmented_length;	  }	else	  {	    if (!(dp->arg_index != ARG_NONE))	      abort ();	    if (dp->conversion == 'n')	      {		switch (a.arg[dp->arg_index].type)		  {		  case TYPE_COUNT_SCHAR_POINTER:		    *a.arg[dp->arg_index].a.a_count_schar_pointer = length;		    break;		  case TYPE_COUNT_SHORT_POINTER:		    *a.arg[dp->arg_index].a.a_count_short_pointer = length;		    break;		  case TYPE_COUNT_INT_POINTER:		    *a.arg[dp->arg_index].a.a_count_int_pointer = length;		    break;		  case TYPE_COUNT_LONGINT_POINTER:		    *a.arg[dp->arg_index].a.a_count_longint_pointer = length;		    break;#if HAVE_LONG_LONG_INT		  case TYPE_COUNT_LONGLONGINT_POINTER:		    *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;		    break;#endif		  default:		    abort ();		  }	      }#if ENABLE_UNISTDIO	    /* The unistdio extensions.  */	    else if (dp->conversion == 'U')	      {		arg_type type = a.arg[dp->arg_index].type;		int flags = dp->flags;		int has_width;		size_t width;		int has_precision;		size_t precision;		has_width = 0;		width = 0;		if (dp->width_start != dp->width_end)		  {		    if (dp->width_arg_index != ARG_NONE)		      {			int arg;			if (!(a.arg[dp->width_arg_index].type == TYPE_INT))			  abort ();			arg = a.arg[dp->width_arg_index].a.a_int;			if (arg < 0)			  {			    /* "A negative field width is taken as a '-' flag			        followed by a positive field width."  */			    flags |= FLAG_LEFT;			    width = (unsigned int) (-arg);			  }			else			  width = arg;		      }		    else		      {			const FCHAR_T *digitp = dp->width_start;			do			  width = xsum (xtimes (width, 10), *digitp++ - '0');			while (digitp != dp->width_end);		      }		    has_width = 1;		  }		has_precision = 0;		precision = 0;		if (dp->precision_start != dp->precision_end)		  {		    if (dp->precision_arg_index != ARG_NONE)		      {			int arg;			if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))			  abort ();			arg = a.arg[dp->precision_arg_index].a.a_int;			/* "A negative precision is taken as if the precision			    were omitted."  */			if (arg >= 0)			  {			    precision = arg;			    has_precision = 1;			  }		      }		    else		      {			const FCHAR_T *digitp = dp->precision_start + 1;			precision = 0;			while (digitp != dp->precision_end)			  precision = xsum (xtimes (precision, 10), *digitp++ - '0');			has_precision = 1;		      }		  }		switch (type)		  {		  case TYPE_U8_STRING:		    {		      const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;		      const uint8_t *arg_end;		      size_t characters;		      if (has_precision)			{			  /* Use only PRECISION characters, from the left.  */			  arg_end = arg;			  characters = 0;			  for (; precision > 0; precision--)			    {			      int count = u8_strmblen (arg_end);			      if (count == 0)				break;			      if (count < 0)				{				  if (!(result == resultbuf || result == NULL))				    free (result);				  if (buf_malloced != NULL)				    free (buf_malloced);				  CLEANUP ();				  errno = EILSEQ;				  return NULL;				}			      arg_end += count;			      characters++;			    }			}		      else if (has_width)			{			  /* Use the entire string, and count the number of			     characters.  */			  arg_end = arg;			  characters = 0;			  for (;;)			    {			      int count = u8_strmblen (arg_end);			      if (count == 0)				break;			      if (count < 0)				{				  if (!(result == resultbuf || result == NULL))				    free (result);				  if (buf_malloced != NULL)				    free (buf_malloced);				  CLEANUP ();				  errno = EILSEQ;				  return NULL;				}			      arg_end += count;			      characters++;			    }			}		      else			{			  /* Use the entire string.  */			  arg_end = arg + u8_strlen (arg);			  /* The number of characters doesn't matter.  */			  characters = 0;			}		      if (has_width && width > characters			  && !(dp->flags & FLAG_LEFT))			{			  size_t n = width - characters;			  ENSURE_ALLOCATION (xsum (length, n));			  DCHAR_SET (result + length, ' ', n);			  length += n;			}# if DCHAR_IS_UINT8_T		      {			size_t n = arg_end - arg;			ENSURE_ALLOCATION (xsum (length, n));			DCHAR_CPY (result + length, arg, n);			length += n;		      }# else		      { /* Convert.  */			DCHAR_T *converted = result + length;			size_t converted_len = allocated - length;#  if DCHAR_IS_TCHAR			/* Convert from UTF-8 to locale encoding.  */			if (u8_conv_to_encoding (locale_charset (),						 iconveh_question_mark,						 arg, arg_end - arg, NULL,						 &converted, &converted_len)			    < 0)#  else			/* Convert from UTF-8 to UTF-16/UTF-32.  */			converted =			  U8_TO_DCHAR (arg, arg_end - arg,				       converted, &converted_len);

⌨️ 快捷键说明

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