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

📄 bsd-snprintf.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh.  This sort of thing is always nasty do deal with.  Note that * the version here does not include floating point... * * snprintf() is used instead of sprintf() as it does limit checks * for string length.  This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. * * More Recently: *  Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 *  This was ugly.  It is still ugly.  I opted out of floating point *  numbers, but the formatter understands just about everything *  from the normal C string format, at least as far as I can tell from *  the Solaris 2.5 printf(3S) man page. * *  Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 *    Ok, added some minimal floating point support, which means this *    probably requires libm on most operating systems.  Don't yet *    support the exponent (e,E) and sigfig (g,G).  Also, fmtint() *    was pretty badly broken, it just wasn't being exercised in ways *    which showed it, so that's been fixed.  Also, formated the code *    to mutt conventions, and removed dead code left over from the *    original.  Also, there is now a builtin-test, just compile with: *           gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm *    and run snprintf for results. *  *  Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i *    The PGP code was using unsigned hexadecimal formats.  *    Unfortunately, unsigned formats simply didn't work. * *  Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 *    The original code assumed that both snprintf() and vsnprintf() were *    missing.  Some systems only have snprintf() but not vsnprintf(), so *    the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * *  Ben Lindstrom <mouring@eviladmin.org> 09/27/00 for OpenSSH *    Welcome to the world of %lld and %qd support.  With other *    long long support.  This is needed for sftp-server to work *    right. * *  Ben Lindstrom <mouring@eviladmin.org> 02/12/01 for OpenSSH *    Removed all hint of VARARGS stuff and banished it to the void, *    and did a bit of KNF style work to make things a bit more *    acceptable.  Consider stealing from mutt or enlightenment. **************************************************************/#include "includes.h"RCSID("$Id: bsd-snprintf.c,v 1.5 2001/02/25 23:20:41 mouring Exp $");#if defined(BROKEN_SNPRINTF)		/* For those with broken snprintf() */# undef HAVE_SNPRINTF# undef HAVE_VSNPRINTF#endif#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF)static void dopr(char *buffer, size_t maxlen, const char *format, va_list args);static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags,        int min, int max);static void fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base,        int min, int max, int flags);static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, long double fvalue,       int min, int max, int flags);static voiddopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);/* * dopr(): poor man's version of doprintf *//* format read states */#define DP_S_DEFAULT 0#define DP_S_FLAGS   1#define DP_S_MIN     2#define DP_S_DOT     3#define DP_S_MAX     4#define DP_S_MOD     5#define DP_S_CONV    6#define DP_S_DONE    7/* format flags - Bits */#define DP_F_MINUS 	(1 << 0)#define DP_F_PLUS  	(1 << 1)#define DP_F_SPACE 	(1 << 2)#define DP_F_NUM   	(1 << 3)#define DP_F_ZERO  	(1 << 4)#define DP_F_UP    	(1 << 5)#define DP_F_UNSIGNED 	(1 << 6)/* Conversion Flags */#define DP_C_SHORT     1#define DP_C_LONG      2#define DP_C_LDOUBLE   3#define DP_C_LONG_LONG 4#define char_to_int(p) (p - '0')#define abs_val(p) (p < 0 ? -p : p)static void dopr(char *buffer, size_t maxlen, const char *format, va_list args){	char *strvalue;	char ch;	long value;	long double fvalue;	int min = 0;	int max = -1;	int state = DP_S_DEFAULT;	int flags = 0;	int cflags = 0;	size_t currlen = 0;  	ch = *format++;	while (state != DP_S_DONE) {		if ((ch == '\0') || (currlen >= maxlen)) 			state = DP_S_DONE;		switch(state) {			case DP_S_DEFAULT:				if (ch == '%') 					state = DP_S_FLAGS;				else 					dopr_outch(buffer, &currlen, maxlen, ch);				ch = *format++;				break;			case DP_S_FLAGS:				switch (ch) {					case '-':						flags |= DP_F_MINUS;						ch = *format++;						break;					case '+':						flags |= DP_F_PLUS;						ch = *format++;						break;					case ' ':						flags |= DP_F_SPACE;						ch = *format++;						break;					case '#':						flags |= DP_F_NUM;						ch = *format++;						break;					case '0':						flags |= DP_F_ZERO;						ch = *format++;						break;					default:						state = DP_S_MIN;						break;				}				break;			case DP_S_MIN:				if (isdigit((unsigned char)ch)) {					min = 10*min + char_to_int (ch);					ch = *format++;				} else if (ch == '*') {					min = va_arg (args, int);					ch = *format++;					state = DP_S_DOT;				} else 					state = DP_S_DOT;				break;			case DP_S_DOT:				if (ch == '.') {					state = DP_S_MAX;					ch = *format++;				} else 					state = DP_S_MOD;				break;			case DP_S_MAX:				if (isdigit((unsigned char)ch)) {					if (max < 0)						max = 0;					max = 10*max + char_to_int(ch);					ch = *format++;				} else if (ch == '*') {					max = va_arg (args, int);					ch = *format++;					state = DP_S_MOD;				} else 					state = DP_S_MOD;				break;			case DP_S_MOD:				switch (ch) {					case 'h':						cflags = DP_C_SHORT;						ch = *format++;						break;					case 'l':						cflags = DP_C_LONG;						ch = *format++;						if (ch == 'l') {							cflags = DP_C_LONG_LONG;							ch = *format++;						}						break;					case 'q':						cflags = DP_C_LONG_LONG;						ch = *format++;						break;					case 'L':						cflags = DP_C_LDOUBLE;						ch = *format++;						break;					default:						break;				}				state = DP_S_CONV;				break;			case DP_S_CONV:				switch (ch) {					case 'd':					case 'i':						if (cflags == DP_C_SHORT) 							value = va_arg(args, int);						else if (cflags == DP_C_LONG)							value = va_arg(args, long int);						else if (cflags == DP_C_LONG_LONG)							value = va_arg (args, long long);						else							value = va_arg (args, int);						fmtint(buffer, &currlen, maxlen, value, 10, min, max, flags);						break;					case 'o':						flags |= DP_F_UNSIGNED;						if (cflags == DP_C_SHORT)							value = va_arg(args, unsigned int);						else if (cflags == DP_C_LONG)							value = va_arg(args, unsigned long int);						else if (cflags == DP_C_LONG_LONG)							value = va_arg(args, unsigned long long);						else							value = va_arg(args, unsigned int);						fmtint(buffer, &currlen, maxlen, value, 8, min, max, flags);						break;					case 'u':						flags |= DP_F_UNSIGNED;						if (cflags == DP_C_SHORT)							value = va_arg(args, unsigned int);						else if (cflags == DP_C_LONG)							value = va_arg(args, unsigned long int);						else if (cflags == DP_C_LONG_LONG)							value = va_arg(args, unsigned long long);						else							value = va_arg(args, unsigned int);						fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);						break;					case 'X':						flags |= DP_F_UP;					case 'x':						flags |= DP_F_UNSIGNED;						if (cflags == DP_C_SHORT)							value = va_arg(args, unsigned int);						else if (cflags == DP_C_LONG)							value = va_arg(args, unsigned long int);						else if (cflags == DP_C_LONG_LONG)							value = va_arg(args, unsigned long long);						else							value = va_arg(args, unsigned int);						fmtint(buffer, &currlen, maxlen, value, 16, min, max, flags);						break;					case 'f':						if (cflags == DP_C_LDOUBLE)							fvalue = va_arg(args, long double);						else							fvalue = va_arg(args, double);						/* um, floating point? */						fmtfp(buffer, &currlen, maxlen, fvalue, min, max, flags);						break;					case 'E':						flags |= DP_F_UP;					case 'e':						if (cflags == DP_C_LDOUBLE)							fvalue = va_arg(args, long double);						else							fvalue = va_arg(args, double);						break;					case 'G':						flags |= DP_F_UP;					case 'g':						if (cflags == DP_C_LDOUBLE)							fvalue = va_arg(args, long double);						else							fvalue = va_arg(args, double);						break;					case 'c':						dopr_outch(buffer, &currlen, maxlen, va_arg(args, int));						break;					case 's':						strvalue = va_arg(args, char *);						if (max < 0) 							max = maxlen; /* ie, no max */						fmtstr(buffer, &currlen, maxlen, strvalue, flags, min, max);						break;					case 'p':						strvalue = va_arg(args, void *);						fmtint(buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);						break;					case 'n':						if (cflags == DP_C_SHORT) {							short int *num;							num = va_arg(args, short int *);							*num = currlen;						} else if (cflags == DP_C_LONG) {							long int *num;							num = va_arg(args, long int *);							*num = currlen;						} else if (cflags == DP_C_LONG_LONG) {							long long *num;							num = va_arg(args, long long *);							*num = currlen;						} else {							int *num;							num = va_arg(args, int *);							*num = currlen;						}						break;					case '%':						dopr_outch(buffer, &currlen, maxlen, ch);						break;					case 'w': /* not supported yet, treat as next char */						ch = *format++;						break;					default: /* Unknown, skip */					break;				}				ch = *format++;				state = DP_S_DEFAULT;				flags = cflags = min = 0;				max = -1;				break;			case DP_S_DONE:				break;			default: /* hmm? */				break; /* some picky compilers need this */		}	}	if (currlen < maxlen - 1) 		buffer[currlen] = '\0';	else 		buffer[maxlen - 1] = '\0';}static voidfmtstr(char *buffer, size_t *currlen, size_t maxlen,       char *value, int flags, int min, int max){	int padlen, strln;     /* amount to pad */	int cnt = 0;  	if (value == 0) 		value = "<NULL>";	for (strln = 0; value[strln]; ++strln); /* strlen */	padlen = min - strln;	if (padlen < 0) 

⌨️ 快捷键说明

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