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

📄 snprintf.c

📁 minicom的源码,linux下常用的串口程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* * Do format conversion. */SCOPE int vsnprintf(char *str, size_t size, const char *fmt, va_list ap){    char *sp;    char *bep;    int cc = 0;    int i;    char *s;    char *q;    int s_len;    int min_width;    int precision;    enum {	LEFT, RIGHT    } adjust;    char pad_char;    char prefix_char;    double fp_num;    wide_int i_num;    u_wide_int ui_num;    char num_buf[NUM_BUF_SIZE];    char char_buf[2];		       /* for printing %% and %<unknown> */    /*     * Flag variables     */    boolean_e is_long;    boolean_e alternate_form;    boolean_e print_sign;    boolean_e print_blank;    boolean_e adjust_precision;    boolean_e adjust_width;    bool_int is_negative;    if (size == 0)	return 0;    sp = str;    bep = str + size - 1;    while (*fmt) {	if (*fmt != '%') {	    INS_CHAR(*fmt, sp, bep, cc);	} else {	    /*	     * Default variable settings	     */	    adjust = RIGHT;	    alternate_form = print_sign = print_blank = NO;	    pad_char = ' ';	    prefix_char = NUL;	    fmt++;	    /*	     * Try to avoid checking for flags, width or precision	     */	    if (isascii(*fmt) && !islower(*fmt)) {		/*		 * Recognize flags: -, #, BLANK, +		 */		for (;; fmt++) {		    if (*fmt == '-')			adjust = LEFT;		    else if (*fmt == '+')			print_sign = YES;		    else if (*fmt == '#')			alternate_form = YES;		    else if (*fmt == ' ')			print_blank = YES;		    else if (*fmt == '0')			pad_char = '0';		    else			break;		}		/*		 * Check if a width was specified		 */		if (isdigit(*fmt)) {		    STR_TO_DEC(fmt, min_width);		    adjust_width = YES;		} else if (*fmt == '*') {		    min_width = va_arg(ap, int);		    fmt++;		    adjust_width = YES;		    if (min_width < 0) {			adjust = LEFT;			min_width = -min_width;		    }		} else		    adjust_width = NO;		/*		 * Check if a precision was specified		 *		 * XXX: an unreasonable amount of precision may be specified		 *      resulting in overflow of num_buf. Currently we		 *      ignore this possibility.		 */		if (*fmt == '.') {		    adjust_precision = YES;		    fmt++;		    if (isdigit(*fmt)) {			STR_TO_DEC(fmt, precision);		    } else if (*fmt == '*') {			precision = va_arg(ap, int);			fmt++;			if (precision < 0)			    precision = 0;		    } else			precision = 0;		} else		    adjust_precision = NO;	    } else		adjust_precision = adjust_width = NO;	    /*	     * Modifier check	     */	    if (*fmt == 'l') {		is_long = YES;		fmt++;	    } else		is_long = NO;	    /*	     * Argument extraction and printing.	     * First we determine the argument type.	     * Then, we convert the argument to a string.	     * On exit from the switch, s points to the string that	     * must be printed, s_len has the length of the string	     * The precision requirements, if any, are reflected in s_len.	     *	     * NOTE: pad_char may be set to '0' because of the 0 flag.	     *                      It is reset to ' ' by non-numeric formats	     */	    switch (*fmt) {	    case 'd':	    case 'i':	    case 'u':		if (is_long)		    i_num = va_arg(ap, wide_int);		else		    i_num = (wide_int) va_arg(ap, int);		s = conv_10(i_num, (*fmt) == 'u', &is_negative,		    &num_buf[NUM_BUF_SIZE], &s_len);		FIX_PRECISION(adjust_precision, precision, s, s_len);		if (*fmt != 'u') {		    if (is_negative)			prefix_char = '-';		    else if (print_sign)			prefix_char = '+';		    else if (print_blank)			prefix_char = ' ';		}		break;	    case 'o':		if (is_long)		    ui_num = va_arg(ap, u_wide_int);		else		    ui_num = (u_wide_int) va_arg(ap, unsigned int);		s = conv_p2(ui_num, 3, *fmt,		    &num_buf[NUM_BUF_SIZE], &s_len);		FIX_PRECISION(adjust_precision, precision, s, s_len);		if (alternate_form && *s != '0') {		    *--s = '0';		    s_len++;		}		break;	    case 'x':	    case 'X':		if (is_long)		    ui_num = (u_wide_int) va_arg(ap, u_wide_int);		else		    ui_num = (u_wide_int) va_arg(ap, unsigned int);		s = conv_p2(ui_num, 4, *fmt,		    &num_buf[NUM_BUF_SIZE], &s_len);		FIX_PRECISION(adjust_precision, precision, s, s_len);		if (alternate_form && i_num != 0) {		    *--s = *fmt;       /* 'x' or 'X' */		    *--s = '0';		    s_len += 2;		}		break;	    case 's':		s = va_arg(ap, char *);		if (s != NULL) {		    s_len = strlen(s);		    if (adjust_precision && precision < s_len)			s_len = precision;		} else {		    s = S_NULL;		    s_len = S_NULL_LEN;		}		pad_char = ' ';		break;	    case 'f':	    case 'e':	    case 'E':		fp_num = va_arg(ap, double);		s = conv_fp(*fmt, fp_num, alternate_form,		    (adjust_precision == NO) ? FLOAT_DIGITS : precision,		    &is_negative, &num_buf[1], &s_len);		if (is_negative)		    prefix_char = '-';		else if (print_sign)		    prefix_char = '+';		else if (print_blank)		    prefix_char = ' ';		break;	    case 'g':	    case 'G':		if (adjust_precision == NO)		    precision = FLOAT_DIGITS;		else if (precision == 0)		    precision = 1;		/*		 * We use &num_buf[ 1 ], so that we have room for the sign		 */		s = gcvt(va_arg(ap, double), precision, &num_buf[1]);		if (*s == '-')		    prefix_char = *s++;		else if (print_sign)		    prefix_char = '+';		else if (print_blank)		    prefix_char = ' ';		s_len = strlen(s);		if (alternate_form && (q = strchr(s, '.')) == NULL)		    s[s_len++] = '.';		if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL)		    *q = 'E';		break;	    case 'c':		char_buf[0] = (char)(va_arg(ap, int));		s = &char_buf[0];		s_len = 1;		pad_char = ' ';		break;	    case '%':		char_buf[0] = '%';		s = &char_buf[0];		s_len = 1;		pad_char = ' ';		break;	    case 'n':		*(va_arg(ap, int *)) = cc;		break;		/*		 * If the pointer size is equal to the size of an unsigned		 * integer we convert the pointer to a hex number, otherwise 		 * we print "%p" to indicate that we don't handle "%p".		 */	    case 'p':		ui_num = (u_wide_int) va_arg(ap, void *);		if (sizeof(void *) <= sizeof(u_wide_int))		        s = conv_p2(ui_num, 4, 'x',			&num_buf[NUM_BUF_SIZE], &s_len);		else {		    s = "%p";		    s_len = 2;		}		pad_char = ' ';		break;	    case NUL:		/*		 * The last character of the format string was %.		 * We ignore it.		 */		continue;		/*		 * The default case is for unrecognized %'s.		 * We print %<char> to help the user identify what		 * option is not understood.		 * This is also useful in case the user wants to pass		 * the output of __sio_converter to another function		 * that understands some other %<char> (like syslog).		 * Note that we can't point s inside fmt because the		 * unknown <char> could be preceded by width etc.		 */	    default:		char_buf[0] = '%';		char_buf[1] = *fmt;		s = char_buf;		s_len = 2;		pad_char = ' ';		break;	    }	    if (prefix_char != NUL) {		*--s = prefix_char;		s_len++;	    }	    if (adjust_width && adjust == RIGHT && min_width > s_len) {		if (pad_char == '0' && prefix_char != NUL) {		    INS_CHAR(*s, sp, bep, cc)			s++;		    s_len--;		    min_width--;		}		PAD(min_width, s_len, pad_char);	    }	    /*	     * Print the string s. 	     */	    for (i = s_len; i != 0; i--) {		INS_CHAR(*s, sp, bep, cc);		s++;	    }	    if (adjust_width && adjust == LEFT && min_width > s_len)		PAD(min_width, s_len, pad_char);	}	fmt++;    }    if (cc < size)	str[cc] = NUL;    else	str[size - 1] = NUL;    return cc;}

⌨️ 快捷键说明

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