register char *s = NULL; char *q; int s_len;
if (len == 0) return 0;
API_EXPORT(int) ap_vformatter(int (*flush_func)(ap_vformatter_buff *),    ap_vformatter_buff *vbuff, const char *fmt, va_list ap){    register char *sp;    register char *bep;    register int cc = 0;    register int i;    register char *s = NULL;    char *q;    int s_len;    register int min_width = 0;    int precision = 0;    enum {	LEFT, RIGHT    } adjust;    char pad_char;    char prefix_char;    double fp_num;    widest_int i_quad = (widest_int) 0;    u_widest_int ui_quad;    wide_int i_num = (wide_int) 0;    u_wide_int ui_num;    char num_buf[NUM_BUF_SIZE];    char char_buf[2];		/* for printing %% and %<unknown> */    enum var_type_enum {    	IS_QUAD, IS_LONG, IS_SHORT, IS_INT    };    enum var_type_enum var_type = IS_INT;    /*     * Flag variables     */    boolean_e alternate_form;    boolean_e print_sign;    boolean_e print_blank;    boolean_e adjust_precision;    boolean_e adjust_width;    bool_int is_negative;    sp = vbuff->curpos;    bep = vbuff->endpos;    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 (!ap_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 (ap_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 (ap_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 == 'q') {		var_type = IS_QUAD;		fmt++;	    }	    else if (*fmt == 'l') {		var_type = IS_LONG;		fmt++;	    }	    else if (*fmt == 'h') {		var_type = IS_SHORT;		fmt++;	    }	    else {		var_type = IS_INT;	    }	    /*	     * 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 'u':	    	if (var_type == IS_QUAD) {		    i_quad = va_arg(ap, u_widest_int);		    s = conv_10_quad(i_quad, 1, &is_negative,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		else {		    if (var_type == IS_LONG)			i_num = (wide_int) va_arg(ap, u_wide_int);		    else if (var_type == IS_SHORT)			i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int);		    else			i_num = (wide_int) va_arg(ap, unsigned int);		    s = conv_10(i_num, 1, &is_negative,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		FIX_PRECISION(adjust_precision, precision, s, s_len);		break;	    case 'd':	    case 'i':	    	if (var_type == IS_QUAD) {		    i_quad = va_arg(ap, widest_int);		    s = conv_10_quad(i_quad, 0, &is_negative,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		else {		    if (var_type == IS_LONG)			i_num = (wide_int) va_arg(ap, wide_int);		    else if (var_type == IS_SHORT)			i_num = (wide_int) (short) va_arg(ap, int);		    else			i_num = (wide_int) va_arg(ap, int);		    s = conv_10(i_num, 0, &is_negative,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		FIX_PRECISION(adjust_precision, precision, s, s_len);		if (is_negative)		    prefix_char = '-';		else if (print_sign)		    prefix_char = '+';		else if (print_blank)		    prefix_char = ' ';		break;	    case 'o':		if (var_type == IS_QUAD) {		    ui_quad = va_arg(ap, u_widest_int);		    s = conv_p2_quad(ui_quad, 3, *fmt,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		else {		    if (var_type == IS_LONG)			ui_num = (u_wide_int) va_arg(ap, u_wide_int);		    else if (var_type == IS_SHORT)			ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned 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 (var_type == IS_QUAD) {		    ui_quad = va_arg(ap, u_widest_int);		    s = conv_p2_quad(ui_quad, 4, *fmt,			    &num_buf[NUM_BUF_SIZE], &s_len);		}		else {		    if (var_type == IS_LONG)			ui_num = (u_wide_int) va_arg(ap, u_wide_int);		    else if (var_type == IS_SHORT)			ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned 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);		/*		 * * We use &num_buf[ 1 ], so that we have room for the sign		 */#ifdef HAVE_ISNAN		if (isnan(fp_num)) {		    s = "nan";		    s_len = 3;		}		else#endif#ifdef HAVE_ISINF		if (isinf(fp_num)) {		    s = "inf";		    s_len = 3;		}		else#endif		{		    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 = ap_gcvt(va_arg(ap, double), precision, &num_buf[1],		            alternate_form);		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++] = '.';		    s[s_len] = '\0'; /* delimit for following strchr() */		}		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':	    	if (var_type == IS_QUAD)		    *(va_arg(ap, widest_int *)) = cc;		else if (var_type == IS_LONG)		    *(va_arg(ap, long *)) = cc;		else if (var_type == IS_SHORT)		    *(va_arg(ap, short *)) = cc;		else		    *(va_arg(ap, int *)) = cc;		break;		/*		 * This is where we extend the printf format, with a second		 * type specifier		 */	    case 'p':		switch(*++fmt) {		    /*		     * If the pointer size is equal to or smaller than the size		     * of the largest unsigned int, we convert the pointer to a		     * hex number, otherwise we print "%p" to indicate that we		     * don't handle "%p".		     */		case 'p':#ifdef AP_VOID_P_IS_QUAD		    if (sizeof(void *) <= sizeof(u_widest_int)) {		    	ui_quad = (u_widest_int) va_arg(ap, void *);			s = conv_p2_quad(ui_quad, 4, 'x',				&num_buf[NUM_BUF_SIZE], &s_len);		    }#else		    if (sizeof(void *) <= sizeof(u_wide_int)) {		    	ui_num = (u_wide_int) va_arg(ap, void *);			s = conv_p2(ui_num, 4, 'x',				&num_buf[NUM_BUF_SIZE], &s_len);		    }#endif		    else {			s = "%p";			s_len = 2;			prefix_char = NUL;		    }		    pad_char = ' ';		    break;		    /* print a struct sockaddr_in as a.b.c.d:port */		case 'I':		    {			struct sockaddr_in *si;			si = va_arg(ap, struct sockaddr_in *);			if (si != NULL) {			    s = conv_sockaddr_in(si, &num_buf[NUM_BUF_SIZE], &s_len);			    if (adjust_precision && precision < s_len)				s_len = precision;			}			else {			    s = S_NULL;			    s_len = S_NULL_LEN;			}			pad_char = ' ';		    }		    break;		    /* print a struct in_addr as a.b.c.d */		case 'A':		    {			struct in_addr *ia;			ia = va_arg(ap, struct in_addr *);			if (ia != NULL) {			    s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len);			    if (adjust_precision && precision < s_len)				s_len = precision;			}			else {			    s = S_NULL;			    s_len = S_NULL_LEN;			}			pad_char = ' ';		    }		    break;		case NUL:		    /* if %p ends the string, oh well ignore it */		    continue;		default:		    s = "bogus %p";		    s_len = 8;		    prefix_char = NUL;		    break;		}		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 format_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 != S_NULL && s != char_buf) {		*--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++;    }    vbuff->curpos = sp;    return cc;}