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

📄 snprintf.c

📁 android-w.song.android.widget
💻 C
📖 第 1 页 / 共 4 页
字号:
/* snprintf - formatted output to strings, with bounds checking and allocation *//* build a test version with   gcc -g -DDRIVER -I../.. -I../../include -o test-snprintf snprintf.c fmtu*long.o*/ /*   Unix snprintf implementation.   derived from inetutils/libinetutils/snprintf.c Version 1.1   Copyright (C) 2001,2006,2010 Free Software Foundation, Inc.   This file is part of GNU Bash, the Bourne Again SHell.   Bash 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.   Bash 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 Bash.  If not, see <http://www.gnu.org/licenses/>.      Revision History:   1.1:      *  added changes from Miles Bader      *  corrected a bug with %f      *  added support for %#g      *  added more comments :-)   1.0:      *  supporting must ANSI syntaxic_sugars   0.0:      *  support %s %c %d THANKS(for the patches and ideas):     Miles Bader     Cyrille Rustom     Jacek Slabocewiz     Mike Parker(mouse)*//* * Currently doesn't handle (and bash/readline doesn't use): *	* *M$ width, precision specifications *	* %N$ numbered argument conversions *	* inf, nan floating values imperfect (if isinf(), isnan() not in libc) *	* support for `F' is imperfect with ldfallback(), since underlying *	  printf may not handle it -- should ideally have another autoconf test */#define FLOATING_POINT#ifdef HAVE_CONFIG_H#  include <config.h>#endif/* GCC 4.2 on Snow Leopard doesn't like the snprintf prototype */#if defined(DEBUG) && !defined (MACOSX)#  undef HAVE_SNPRINTF#  undef HAVE_ASPRINTF#  define HAVE_SNPRINTF 0#  define HAVE_ASPRINTF 0#endif#if defined(DRIVER) && !defined(HAVE_CONFIG_H)#define HAVE_LONG_LONG#define HAVE_LONG_DOUBLE#ifdef __linux__#define HAVE_PRINTF_A_FORMAT#endif#define HAVE_ISINF_IN_LIBC#define HAVE_ISNAN_IN_LIBC#define PREFER_STDARG#define HAVE_STRINGIZE#define HAVE_LIMITS_H#define HAVE_STDDEF_H#define HAVE_LOCALE_H#define intmax_t long#endif#if !HAVE_SNPRINTF || !HAVE_ASPRINTF#include <bashtypes.h>#if defined(PREFER_STDARG)#  include <stdarg.h>#else#  include <varargs.h>#endif#ifdef HAVE_LIMITS_H#  include <limits.h>#endif#include <bashansi.h>#ifdef HAVE_STDDEF_H#  include <stddef.h>#endif#include <chartypes.h>#ifdef HAVE_STDINT_H#  include <stdint.h>#endif#ifdef FLOATING_POINT#  include <float.h>	/* for manifest constants */#  include <stdio.h>	/* for sprintf */#endif#include <typemax.h>#ifdef HAVE_LOCALE_H#  include <locale.h>#endif#include "stdc.h"#include <shmbutil.h>#ifndef DRIVER#  include "shell.h"#else#  define FL_PREFIX     0x01    /* add 0x, 0X, or 0 prefix as appropriate */#  define FL_ADDBASE    0x02    /* add base# prefix to converted value */#  define FL_HEXUPPER   0x04    /* use uppercase when converting to hex */#  define FL_UNSIGNED   0x08    /* don't add any sign */extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));#endif#ifndef FREE#  define FREE(x)	if (x) free (x)#endif/* Bound on length of the string representing an integer value of type T.   Subtract one for the sign bit if T is signed;   302 / 1000 is log10 (2) rounded up;   add one for integer division truncation;   add one more for a minus sign if t is signed.  */#define INT_STRLEN_BOUND(t) \  ((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \     + 1 + TYPE_SIGNED (t))/* conversion flags */#define PF_ALTFORM	0x00001		/* # */#define PF_HEXPREFIX	0x00002		/* 0[Xx] */#define PF_LADJUST	0x00004		/* - */#define PF_ZEROPAD	0x00008		/* 0 */#define PF_PLUS		0x00010		/* + */#define PF_SPACE	0x00020		/* ' ' */#define PF_THOUSANDS	0x00040		/* ' */#define PF_DOT		0x00080		/* `.precision' */#define PF_STAR_P	0x00100		/* `*' after precision */#define PF_STAR_W	0x00200		/* `*' before or without precision *//* length modifiers */#define PF_SIGNEDCHAR	0x00400		/* hh */#define PF_SHORTINT	0x00800		/* h */#define PF_LONGINT	0x01000		/* l */#define PF_LONGLONG	0x02000		/* ll */#define PF_LONGDBL	0x04000		/* L */#define PF_INTMAX_T	0x08000		/* j */#define PF_SIZE_T	0x10000		/* z */#define PF_PTRDIFF_T	0x20000		/* t */#define PF_ALLOCBUF	0x40000		/* for asprintf, vasprintf */#define PFM_SN		0x01		/* snprintf, vsnprintf */#define PFM_AS		0x02		/* asprintf, vasprintf */#define ASBUFSIZE	128#define x_digs	"0123456789abcdef"#define X_digs	"0123456789ABCDEF"static char intbuf[INT_STRLEN_BOUND(unsigned long) + 1];static int decpoint;static int thoussep;static char *grouping;/*  * For the FLOATING POINT FORMAT : *  the challenge was finding a way to *  manipulate the Real numbers without having *  to resort to mathematical function(it *  would require to link with -lm) and not *  going down to the bit pattern(not portable) * *  so a number, a real is:      real = integral + fraction      integral = ... + a(2)*10^2 + a(1)*10^1 + a(0)*10^0      fraction = b(1)*10^-1 + b(2)*10^-2 + ...      where:       0 <= a(i) => 9        0 <= b(i) => 9      from then it was simple math *//* * size of the buffer for the integral part * and the fraction part  */#define MAX_INT  99 + 1 /* 1 for the null */#define MAX_FRACT 307 + 1/*  * These functions use static buffers to store the results, * and so are not reentrant */#define itoa(n) fmtulong(n, 10, intbuf, sizeof(intbuf), 0);#define dtoa(n, p, f) numtoa(n, 10, p, f)#define SWAP_INT(a,b) {int t; t = (a); (a) = (b); (b) = t;}#define GETARG(type)	(va_arg(args, type))/* Macros that do proper sign extension and handle length modifiers.  Used   for the integer conversion specifiers. */#define GETSIGNED(p) \  (((p)->flags & PF_LONGINT) \	? GETARG (long) \  	: (((p)->flags & PF_SHORTINT) ? (long)(short)GETARG (int) \				      : (long)GETARG (int)))#define GETUNSIGNED(p) \  (((p)->flags & PF_LONGINT) \	? GETARG (unsigned long) \	: (((p)->flags & PF_SHORTINT) ? (unsigned long)(unsigned short)GETARG (int) \				      : (unsigned long)GETARG (unsigned int)))#ifdef HAVE_LONG_DOUBLE#define GETLDOUBLE(p) GETARG (long double)#endif#define GETDOUBLE(p) GETARG (double)#define SET_SIZE_FLAGS(p, type) \  if (sizeof (type) > sizeof (int)) \    (p)->flags |= PF_LONGINT; \  if (sizeof (type) > sizeof (long)) \    (p)->flags |= PF_LONGLONG;/* this struct holds everything we need */struct DATA{  int length;  char *base;		/* needed for [v]asprintf */  char *holder;  int counter;  const char *pf;/* FLAGS */  int flags;  int justify;  int width, precision;  char pad;};/* the floating point stuff */#ifdef FLOATING_POINTstatic double pow_10 __P((int));static int log_10 __P((double));static double integral __P((double, double *));static char *numtoa __P((double, int, int, char **));#endifstatic void init_data __P((struct DATA *, char *, size_t, const char *, int));static void init_conv_flag __P((struct DATA *));/* for the format */#ifdef FLOATING_POINTstatic void floating __P((struct DATA *, double));static void exponent __P((struct DATA *, double));#endifstatic void number __P((struct DATA *, unsigned long, int));#ifdef HAVE_LONG_LONGstatic void lnumber __P((struct DATA *, unsigned long long, int));#endifstatic void pointer __P((struct DATA *, unsigned long));static void strings __P((struct DATA *, char *));#ifdef FLOATING_POINT#  define FALLBACK_FMTSIZE	32#  define FALLBACK_BASE		4096#  define LFALLBACK_BASE	5120#  ifdef HAVE_LONG_DOUBLEstatic void ldfallback __P((struct DATA *, const char *, const char *, long double));#  endifstatic void dfallback __P((struct DATA *, const char *, const char *, double));#endifstatic char *groupnum __P((char *));#ifndef HAVE_ISINF_IN_LIBCstatic int isinf __P((double));#endif#ifndef HAVE_ISNAN_IN_LIBCstatic int isnan __P((double));#endif#ifdef DRIVERstatic void memory_error_and_abort ();static void *xmalloc __P((size_t));static void *xrealloc __P((void *, size_t));static void xfree __P((void *));#else#  include <xmalloc.h>#endif/* those are defines specific to snprintf to hopefully * make the code clearer :-) */#define RIGHT 1#define LEFT  0#define NOT_FOUND -1#define FOUND 1#define MAX_FIELD 15/* round off to the precision */#define ROUND(d, p) \	    (d < 0.) ? \	     d - pow_10(-(p)->precision) * 0.5 : \	     d + pow_10(-(p)->precision) * 0.5/* set default precision */#define DEF_PREC(p) \	    if ((p)->precision == NOT_FOUND) \	      (p)->precision = 6/* put a char.  increment the number of chars written even if we've exceeded   the vsnprintf/snprintf buffer size (for the return value) */#define PUT_CHAR(c, p) \	do \	  { \	    if (((p)->flags & PF_ALLOCBUF) && ((p)->counter >= (p)->length - 1)) \	      { \		(p)->length += ASBUFSIZE; \		(p)->base = (char *)xrealloc((p)->base, (p)->length); \		(p)->holder = (p)->base + (p)->counter; /* in case reallocated */ \	      } \	    if ((p)->counter < (p)->length) \	      *(p)->holder++ = (c); \	    (p)->counter++; \	  } \	while (0)/* Output a string.  P->WIDTH has already been adjusted for padding. */#define PUT_STRING(string, len, p) \	do \	  { \	    PAD_RIGHT (p); \	    while ((len)-- > 0) \	      { \		PUT_CHAR (*(string), (p)); \		(string)++; \	      } \	    PAD_LEFT (p); \	  } \	while (0)#define PUT_PLUS(d, p, zero) \	    if ((d) > zero && (p)->justify == RIGHT) \	      PUT_CHAR('+', p)#define PUT_SPACE(d, p, zero) \	    if (((p)->flags & PF_SPACE) && (d) > zero) \	      PUT_CHAR(' ', p)/* pad right */ #define PAD_RIGHT(p) \	    if ((p)->width > 0 && (p)->justify != LEFT) \	      for (; (p)->width > 0; (p)->width--) \		 PUT_CHAR((p)->pad, p)/* pad left */#define PAD_LEFT(p) \	    if ((p)->width > 0 && (p)->justify == LEFT) \	      for (; (p)->width > 0; (p)->width--) \		 PUT_CHAR((p)->pad, p)/* pad with zeros from decimal precision */#define PAD_ZERO(p) \	if ((p)->precision > 0) \	  for (; (p)->precision > 0; (p)->precision--) \	    PUT_CHAR('0', p)/* if width and prec. in the args */#define STAR_ARGS(p) \	do { \	    if ((p)->flags & PF_STAR_W) \	      { \		(p)->width = GETARG (int); \		if ((p)->width < 0) \		  { \		    (p)->flags |= PF_LADJUST; \		    (p)->justify = LEFT; \		    (p)->width = -(p)->width; \		  } \	      } \	    if ((p)->flags & PF_STAR_P) \	      { \		(p)->precision = GETARG (int); \		if ((p)->precision < 0) \		  { \		    (p)->flags &= ~PF_STAR_P; \		    (p)->precision = NOT_FOUND; \		  } \	      } \	} while (0)#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)#  define GETLOCALEDATA(d, t, g) \      do \	{ \	  struct lconv *lv; \	  if ((d) == 0) { \	  (d) = '.'; (t) = -1; (g) = 0; /* defaults */ \	  lv = localeconv(); \	  if (lv) \	    { \	      if (lv->decimal_point && lv->decimal_point[0]) \	        (d) = lv->decimal_point[0]; \	      if (lv->thousands_sep && lv->thousands_sep[0]) \	        (t) = lv->thousands_sep[0]; \	      (g) = lv->grouping ? lv->grouping : ""; \	      if (*(g) == '\0' || *(g) == CHAR_MAX || (t) == -1) (g) = 0; \	    } \	  } \	} \      while (0);#else#  define GETLOCALEDATA(d, t, g) \      ( (d) = '.', (t) = ',', g = "\003" )#endif#ifdef FLOATING_POINT/* * Find the nth power of 10 */static doublepow_10(n)     int n;{   double P;  /* handle common cases with fast switch statement. */  switch (n)    {    case -3:	return .001;    case -2:	return .01;    case -1:	return .1;    case 0:	return 1.;    case 1:	return 10.;    case 2:	return 100.;    case 3:	return 1000.;    }  if (n < 0)    {      P = .0001;      for (n += 4; n < 0; n++)	P /= 10.;    }  else    {      P = 10000.;      for (n -= 4; n > 0; n--)	P *= 10.;    }  return P;}/* * Find the integral part of the log in base 10  * Note: this not a real log10()	 I just need and approximation(integerpart) of x in:	  10^x ~= r * log_10(200) = 2; * log_10(250) = 2; * * NOTE: do not call this with r == 0 -- an infinite loop results. */static intlog_10(r)     double r;{   int i = 0;  double result = 1.;  if (r < 0.)    r = -r;  if (r < 1.)    {      while (result >= r)	{	  result /= 10.;	  i++;	}      return (-i);    }  else    {      while (result <= r)	{	  result *= 10.;	  i++;	}      return (i - 1);    }}/* * This function return the fraction part of a double * and set in ip the integral part. * In many ways it resemble the modf() found on most Un*x */static doubleintegral(real, ip)     double real;     double *ip;{   int j;  double i, s, p;  double real_integral = 0.;  /* take care of the obvious */  /* equal to zero ? */  if (real == 0.)    {      *ip = 0.;

⌨️ 快捷键说明

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