int hb_printf_params( const char * format ) { int iParam = 0, iMax = 0; char c; do { c = *format++; if( c == '%' ) { const char * pattern = format; int value, param = 0; c = *format++; if( c != 0 && c != '%' ) { /* parameter position */ if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, ¶m ); if( c != '$' ) format = pattern; c = *format++; } /* flags */ value = 0; while( ! value ) { switch( c ) { case '#': case '0': case '-': case ' ': case '+': #ifdef _SUSV2_COMPAT_ case '\'': /* group with locale thousands' grouping characters */ #endif c = *format++; break; default: value = 1; break; } } /* field width */ if( c == '*' ) { c = *format++; if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) { if( value > iMax ) iMax = value; c = *format++; } /* else error, wrong format */ } else ++iParam; } else if( c >= '0' && c <= '9' ) c = get_decimal( c, &format, &value ); /* precision */ if( c == '.' ) { c = *format++; if( c == '*' ) { c = *format++; if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) { if( value > iMax ) iMax = value; c = *format++; } /* else error, wrong format */ } else ++iParam; } else if( c >= '0' && c <= '9' ) c = get_decimal( c, &format, &value ); } /* length modifier */ switch( c ) { case 'h': c = *format++; if( c == 'h' ) c = *format++; break; case 'l': c = *format++; if( c == 'l' ) c = *format++; break; case 'L': c = *format++; break; case 'j': c = *format++; break; case 'z': c = *format++; break; case 't': c = *format++; break; case 'I': /* MS-Windows extension */ if( format[ 0 ] == '6' && format[ 1 ] == '4' ) { format += 2; c = *format++; break; } else if( format[ 0 ] == '1' && format[ 1 ] == '6' ) { format += 2; c = *format++; break; } else if( format[ 0 ] == '3' && format[ 1 ] == '2' ) { format += 2; c = *format++; } /* no break; */ default: break; } /* conversion specifier */ switch( c ) { #ifndef __NO_DOUBLE__ case 'a': case 'A': case 'e': case 'E': case 'g': case 'G': case 'f': /* double decimal notation */ case 'F': /* double decimal notation */ #endif case 'd': case 'i': /* signed int decimal conversion */ case 'o': /* unsigned int octal conversion */ case 'u': /* unsigned int decimal conversion */ case 'x': /* unsigned int hexadecimal conversion */ case 'X': /* unsigned int hexadecimal conversion */ case 'p': /* void * pointer */ case 'c': /* signed int casted to unsigned char */ case 's': /* const char * */ case 'n': /* store current result size in int * arg */ if( param == 0 ) ++iParam; else if( param > iMax ) iMax = param; break; case '%': /* store % consuming arguments % */ break; default: /* error, wrong format, store pattern */ format = pattern; c = '%'; break; } } } } while( c ); return iParam > iMax ? iParam : iMax; }
double convertD(char u[]) { return get_inteiro(u)+get_decimal(u); //Soma inteiro com decimal.ss }
int hb_vsnprintf( char * buffer, size_t bufsize, const char * format, va_list ap ) { va_list args; size_t size; char c; #ifndef __NO_ARGPOS__ const char * fmt_start = format; v_param argbuf[ _ARGBUF_SIZE ]; v_paramlst params; params.size = _ARGBUF_SIZE; params.maxarg = 0; params.arglst = argbuf; #endif #ifndef __NO_ARGPOS__ do { params.repeat = HB_FALSE; if( params.maxarg > 0 ) { va_copy( args, ap ); va_arg_fill( ¶ms, args ); va_end( args ); } format = fmt_start; #endif va_copy( args, ap ); size = 0; do { c = *format++; if( c == '%' ) { const char * pattern = format; c = *format++; if( c != 0 && c != '%' ) { /* decode pattern */ v_param argval; int param = 0, flags = 0, width = -1, precision = -1, length, value, stop = 0; /* parameter position */ if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) param = value; else format = pattern; c = *format++; } /* flags */ while( ! stop ) { switch( c ) { case '#': flags |= _F_ALTERNATE; c = *format++; break; case '0': flags |= _F_ZEROPADED; c = *format++; break; case '-': flags |= _F_LEFTADJUSTED; c = *format++; break; case ' ': flags |= _F_SPACE; c = *format++; break; case '+': flags |= _F_SIGN; c = *format++; break; #ifdef _SUSV2_COMPAT_ case '\'': /* group with locale thousands' grouping characters */ c = *format++; break; #endif default: stop = 1; break; } } /* field width */ if( c == '*' ) { c = *format++; if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) { width = va_arg_n( args, _x_int, value ); c = *format++; } /* else error, wrong format */ } else width = va_arg_n( args, _x_int, 0 ); } else if( c >= '0' && c <= '9' ) c = get_decimal( c, &format, &width ); /* precision */ if( c == '.' ) { precision = 0; c = *format++; if( c == '*' ) { c = *format++; if( c >= '0' && c <= '9' ) { c = get_decimal( c, &format, &value ); if( c == '$' ) { precision = va_arg_n( args, _x_int, value ); c = *format++; } /* else error, wrong format */ } else precision = va_arg_n( args, _x_int, 0 ); } else if( c >= '0' && c <= '9' ) c = get_decimal( c, &format, &precision ); } /* length modifier */ switch( c ) { case 'h': c = *format++; if( c == 'h' ) { length = _L_CHAR_; c = *format++; } else length = _L_SHORT_; break; case 'l': c = *format++; if( c == 'l' ) { length = _L_LONGLONG_; c = *format++; } else length = _L_LONG_; break; case 'L': length = _L_LONGDOUBLE_; c = *format++; break; case 'j': length = _L_INTMAX_; c = *format++; break; case 'z': length = _L_SIZE_; c = *format++; break; case 't': length = _L_PTRDIFF_; c = *format++; break; case 'I': /* MS-Windows extension */ if( format[ 0 ] == '6' && format[ 1 ] == '4' ) { length = _L_LONGLONG_; format += 2; c = *format++; break; } else if( format[ 0 ] == '1' && format[ 1 ] == '6' ) { length = _L_SHORT_; format += 2; c = *format++; break; } else if( format[ 0 ] == '3' && format[ 1 ] == '2' ) { format += 2; c = *format++; } /* no break; */ default: length = _L_UNDEF_; break; } /* conversion specifier */ switch( c ) { #ifndef __NO_DOUBLE__ case 'a': case 'A': case 'e': case 'E': case 'g': case 'G': /* redirect above conversion to 'f' or 'F' type to keep * valid parameters order */ c = ( c == 'a' || c == 'e' || c == 'g' ) ? 'f' : 'F'; /* no break; */ case 'f': /* double decimal notation */ case 'F': /* double decimal notation */ if( length == _L_LONGDOUBLE_ ) { argval.value.as_x_long_dbl = va_arg_n( args, _x_long_dbl, param ); HB_NUMTYPEL( value, argval.value.as_x_long_dbl ); } else { double d = va_arg_n( args, _x_double, param ); HB_NUMTYPE( value, d ); argval.value.as_x_long_dbl = ( value & ( _HB_NUM_NAN | _HB_NUM_PINF | _HB_NUM_NINF ) ) == 0 ? d : 0; } if( value & _HB_NUM_NAN ) size = put_str( buffer, bufsize, size, c == 'f' ? ( flags & _F_SIGN ? "+nan": "nan" ) : ( flags & _F_SIGN ? "+NAN": "NAN" ) , flags, width, -1 ); else if( value & _HB_NUM_PINF ) size = put_str( buffer, bufsize, size, c == 'f' ? ( flags & _F_SIGN ? "+inf": "inf" ) : ( flags & _F_SIGN ? "+INF": "INF" ), flags, width, -1 ); else if( value & _HB_NUM_NINF ) size = put_str( buffer, bufsize, size, c == 'f' ? "-inf" : "-INF", flags, width, -1 ); else size = put_dbl( buffer, bufsize, size, argval.value.as_x_long_dbl, flags, width, precision ); continue; #endif case 'd': case 'i': /* signed int decimal conversion */ if( length == _L_CHAR_ ) argval.value.as_x_intmax_t = ( unsigned char ) va_arg_n( args, _x_int, param ); else if( length == _L_SHORT_ ) argval.value.as_x_intmax_t = ( unsigned short ) va_arg_n( args, _x_int, param ); else if( length == _L_LONG_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_long, param ); else if( length == _L_LONGLONG_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_longlong, param ); else if( length == _L_INTMAX_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_intmax_t, param ); else if( length == _L_SIZE_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_size_t, param ); else if( length == _L_PTRDIFF_ ) argval.value.as_x_intmax_t = va_arg_n( args, _x_ptrdiff_t, param ); else argval.value.as_x_intmax_t = va_arg_n( args, _x_int, param ); value = argval.value.as_x_intmax_t < 0; argval.value.as_x_uintmax_t = value ? -argval.value.as_x_intmax_t : argval.value.as_x_intmax_t; size = put_dec( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags, width, precision, value ); continue; case 'o': /* unsigned int octal conversion */ case 'u': /* unsigned int decimal conversion */ case 'x': /* unsigned int hexadecimal conversion */ case 'X': /* unsigned int hexadecimal conversion */ if( length == _L_CHAR_ ) argval.value.as_x_uintmax_t = ( unsigned char ) va_arg_n( args, _x_int, param ); else if( length == _L_SHORT_ ) argval.value.as_x_uintmax_t = ( unsigned short ) va_arg_n( args, _x_int, param ); else if( length == _L_LONG_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_ulong, param ); else if( length == _L_LONGLONG_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_ulonglong, param ); else if( length == _L_INTMAX_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_uintmax_t, param ); else if( length == _L_SIZE_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_size_t, param ); else if( length == _L_PTRDIFF_ ) argval.value.as_x_uintmax_t = va_arg_n( args, _x_ptrdiff_t, param ); else argval.value.as_x_uintmax_t = va_arg_n( args, _x_uint, param ); if( c == 'o' ) size = put_octal( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags, width, precision ); else if( c == 'u' ) size = put_dec( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags & ~( _F_SPACE | _F_SIGN ), width, precision, 0 ); else size = put_hex( buffer, bufsize, size, argval.value.as_x_uintmax_t, flags, width, precision, c == 'X' ); continue; case 'p': /* void * pointer */ argval.value.as_x_ptr = va_arg_n( args, _x_ptr, param ); if( argval.value.as_x_ptr ) size = put_hex( buffer, bufsize, size, ( HB_PTRUINT ) argval.value.as_x_ptr, flags | _F_ALTERNATE, width, precision, 0 ); else size = put_str( buffer, bufsize, size, "(nil)", flags, width, -1 ); continue; case 'c': /* signed int casted to unsigned char */ if( ( flags & _F_LEFTADJUSTED ) == 0 ) { while( --width > 0 ) { if( size < bufsize ) buffer[ size ] = ' '; ++size; } } c = ( unsigned char ) va_arg_n( args, _x_int, param ); if( size < bufsize ) buffer[ size ] = c; ++size; while( --width > 0 ) { if( size < bufsize ) buffer[ size ] = ' '; ++size; } continue; case 's': /* const char * */ if( length == _L_LONG_ ) { argval.value.as_x_wstr = va_arg_n( args, _x_wstr, param ); size = put_wstr( buffer, bufsize, size, argval.value.as_x_wstr, flags, width, precision ); } else { argval.value.as_x_str = va_arg_n( args, _x_str, param ); size = put_str( buffer, bufsize, size, argval.value.as_x_str, flags, width, precision ); } continue; case 'n': /* store current result size in int * arg */ /* This is very danger feature in *printf() functions * family very often used by hackers to create buffer * overflows. It can also cause unintentional memory * corruption by programmers typo in pattern so if it's * not strictly necessary it's good to disable it. */ *( va_arg_n( args, _x_intptr, param ) ) = ( int ) size; continue; case '%': /* store % consuming arguments % */ break; default: /* error, wrong format, store pattern */ format = pattern; c = '%'; break; } } } /* ISO C99 defines that when size is 0 and buffer is NULL we should * return number of characters that would have been written in case * the output string has been large enough without trailing 0. * Many implementations always returns number of characters necessary * to hold the string even if the above condition is not true so the * returned value can be used to check if buffer was large enough * and if not to allocate bigger buffer. Let's do the same. */ if( size < bufsize ) buffer[ size ] = c; ++size; } while( c != 0 ); va_end( args ); #ifndef __NO_ARGPOS__ } while( params.repeat ); if( params.arglst != argbuf ) hb_xfree( params.arglst ); #endif /* always set trailing \0 !!! */ if( bufsize ) buffer[ bufsize - 1 ] = 0; return ( int ) ( size - 1 ); }