diff --git a/library/changes b/library/changes index 5fbf8a1..a906500 100644 --- a/library/changes +++ b/library/changes @@ -50,6 +50,10 @@ - Added fabsf() for C99. +- The scanf() family now supports the %hh, %j, %t and %z modifiers and the + %a/%A conversions for C99. The %j is treated like %ll; %t and %z are treated + like %l. Also, the "inf"/"infinity"/"nan"/"nan()" keywords are processed. + c.lib 1.191 (9.4.2005) diff --git a/library/math_fpclassify.c b/library/math_fpclassify.c index 2b1b06e..bdd1c28 100644 --- a/library/math_fpclassify.c +++ b/library/math_fpclassify.c @@ -1,5 +1,5 @@ /* - * $Id: math_fpclassify.c,v 1.1 2005-05-08 08:51:29 obarthel Exp $ + * $Id: math_fpclassify.c,v 1.2 2005-05-08 11:27:26 obarthel Exp $ * * :ts=4 * @@ -54,16 +54,44 @@ __fpclassify_float(float number) x.value = number; + D(("number = 0x%08lx",x.raw[0])); + if((x.raw[0] & 0x7f800000) == 0x7f800000 && (x.raw[0] & 0x007fffff) != 0) - result = FP_NAN; /* Exponent = 255 and fraction != 0.0 -> not a number */ + { + SHOWMSG("not a number"); + + /* Exponent = 255 and fraction != 0.0 -> not a number */ + result = FP_NAN; + } else if ((x.raw[0] & 0x7fffffff) == 0x7f800000) - result = FP_INFINITE; /* Exponent = 255 and fraction = 0.0 -> infinity */ + { + SHOWMSG("infinity"); + + /* Exponent = 255 and fraction = 0.0 -> infinity */ + result = FP_INFINITE; + } else if (x.raw[0] == 0) /* ZZZ test against epsilon? */ - result = FP_ZERO; /* Both exponent and fraction are zero -> zero */ + { + SHOWMSG("zero"); + + /* Both exponent and fraction are zero -> zero */ + result = FP_ZERO; + } else if ((x.raw[0] & 0x7f800000) == 0) - result = FP_SUBNORMAL; /* Exponent = 0 -> subnormal */ + { + SHOWMSG("subnormal"); + + /* Exponent = 0 -> subnormal (IEEE 754) */ + result = FP_SUBNORMAL; + } else + { + SHOWMSG("normal"); + result = FP_NORMAL; + } + + SHOWVALUE(result); return(result); } @@ -78,16 +106,44 @@ __fpclassify_double(double number) x.value = number; + D(("number = 0x%08lx%08lx",x.raw[0],x.raw[1])); + if(((x.raw[0] & 0x7ff00000) == 0x7ff00000) && ((x.raw[0] & 0x000fffff) != 0 || (x.raw[1] != 0))) - result = FP_NAN; /* Exponent = 2047 and fraction != 0.0 -> not a number */ + { + SHOWMSG("not a number"); + + /* Exponent = 2047 and fraction != 0.0 -> not a number */ + result = FP_NAN; + } else if (((x.raw[0] & 0x7fffffff) == 0x7ff00000) && (x.raw[1] == 0)) - result = FP_INFINITE; /* Exponent = 2047 and fraction = 0.0 -> infinity */ + { + SHOWMSG("infinity"); + + /* Exponent = 2047 and fraction = 0.0 -> infinity */ + result = FP_INFINITE; + } else if (x.raw[0] == 0 && x.raw[1] == 0) /* ZZZ test against epsilon? */ - result = FP_ZERO; /* Both exponent and fraction are zero -> zero */ + { + SHOWMSG("zero"); + + /* Both exponent and fraction are zero -> zero */ + result = FP_ZERO; + } else if ((x.raw[0] & 0x7fff0000) == 0) - result = FP_SUBNORMAL; /* Exponent = 0 -> subnormal */ + { + SHOWMSG("subnormal"); + + /* Exponent = 0 -> subnormal (IEEE 754) */ + result = FP_SUBNORMAL; + } else + { + SHOWMSG("normal"); + result = FP_NORMAL; + } + + SHOWVALUE(result); return(result); } diff --git a/library/stdio_vfprintf.c b/library/stdio_vfprintf.c index 8e27041..917b9fe 100644 --- a/library/stdio_vfprintf.c +++ b/library/stdio_vfprintf.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_vfprintf.c,v 1.15 2005-05-08 08:51:29 obarthel Exp $ + * $Id: stdio_vfprintf.c,v 1.16 2005-05-08 11:27:26 obarthel Exp $ * * :ts=4 * @@ -37,8 +37,6 @@ /****************************************************************************/ -/*#define DEBUG*/ - #ifndef _STDIO_HEADERS_H #include "stdio_headers.h" #endif /* _STDIO_HEADERS_H */ @@ -76,6 +74,8 @@ get_num_leading_digits(__long_double_t v,int radix) { int num_digits; + SHOWVALUE(radix); + if(v < radix) { num_digits = 1; @@ -124,7 +124,7 @@ vfprintf(FILE * stream,const char * format, va_list arg) parameter_size_long_long, parameter_size_long_double, parameter_size_intmax_t, - parameter_size_default, + parameter_size_default }; struct iob * iob = (struct iob *)stream; @@ -892,6 +892,8 @@ vfprintf(FILE * stream,const char * format, va_list arg) exponent). */ num_leading_digits = get_num_leading_digits(v,radix); + SHOWVALUE(num_leading_digits); + v /= pow(radix,(double)num_leading_digits); for(i = 0 ; (max_digits != 0) && (i < num_leading_digits) && (output_buffer < buffer_stop) ; i++) diff --git a/library/stdio_vfscanf.c b/library/stdio_vfscanf.c index eba363f..3a43a3f 100644 --- a/library/stdio_vfscanf.c +++ b/library/stdio_vfscanf.c @@ -1,5 +1,5 @@ /* - * $Id: stdio_vfscanf.c,v 1.12 2005-04-03 10:22:47 obarthel Exp $ + * $Id: stdio_vfscanf.c,v 1.13 2005-05-08 11:27:26 obarthel Exp $ * * :ts=4 * @@ -64,16 +64,20 @@ int vfscanf(FILE *stream, const char *format, va_list arg) { - enum format_size_t + enum parameter_size_t { - format_size_default, - format_size_long, - format_size_long_long, - format_size_short, - format_size_long_double + parameter_size_byte, + parameter_size_long, + parameter_size_short, + parameter_size_size_t, + parameter_size_ptrdiff_t, + parameter_size_long_long, + parameter_size_long_double, + parameter_size_intmax_t, + parameter_size_default }; - enum format_size_t format_size; + enum parameter_size_t parameter_size; int total_num_chars_read = 0; int num_chars_processed; BOOL assignment_suppressed; @@ -254,19 +258,34 @@ vfscanf(FILE *stream, const char *format, va_list arg) if(c == 'h') { /* Parameter is a short integer. */ - format_size = format_size_short; + parameter_size = parameter_size_short; + format++; + } + else if (c == 'j') + { + parameter_size = parameter_size_intmax_t; format++; } else if (c == 'l') { /* Parameter is a long integer or a double precision floating point value. */ - format_size = format_size_long; + parameter_size = parameter_size_long; format++; } else if (c == 'L') { /* Parameter is a long double floating point value. */ - format_size = format_size_long_double; + parameter_size = parameter_size_long_double; + format++; + } + else if (c == 't') + { + parameter_size = parameter_size_ptrdiff_t; + format++; + } + else if (c == 'z') + { + parameter_size = parameter_size_size_t; format++; } else if (c == '\0') @@ -277,7 +296,7 @@ vfscanf(FILE *stream, const char *format, va_list arg) else { /* Parameter is a long integer or a single precision floating point value. */ - format_size = format_size_default; + parameter_size = parameter_size_default; } /* Now for the conversion type. */ @@ -288,10 +307,9 @@ vfscanf(FILE *stream, const char *format, va_list arg) #if defined(USE_64_BIT_INTS) && defined(__GNUC__) { /* Check for long long parameters. */ - if(c == 'l') + if(parameter_size == parameter_size_long && c == 'l') { - if(format_size == format_size_long) - format_size = format_size_long_long; + parameter_size == parameter_size_long_long; format++; @@ -303,6 +321,19 @@ vfscanf(FILE *stream, const char *format, va_list arg) } #endif /* __GNUC__ */ + /* Check for byte parameters. */ + if(parameter_size == parameter_size_short && c == 'h') + { + parameter_size = parameter_size_byte; + + format++; + + /* The conversion type follows. */ + c = (*format); + if(c == '\0') + break; + } + switch(c) { /* It's a pointer. */ @@ -313,6 +344,8 @@ vfscanf(FILE *stream, const char *format, va_list arg) break; /* It's a floating point number. */ + case 'a': + case 'A': case 'e': case 'E': case 'f': @@ -475,13 +508,13 @@ vfscanf(FILE *stream, const char *format, va_list arg) } #endif /* CHECK_FOR_NULL_POINTERS */ - if(format_size == format_size_default) + if(parameter_size == parameter_size_default) { SHOWMSG("short format (float)"); next_parameter = va_arg(arg,float *); } - else if (format_size == format_size_long) + else if (parameter_size == parameter_size_long) { SHOWMSG("long format (double)"); @@ -506,11 +539,11 @@ vfscanf(FILE *stream, const char *format, va_list arg) } #endif /* CHECK_FOR_NULL_POINTERS */ - if(format_size == format_size_default) + if(parameter_size == parameter_size_default) { *((float *)next_parameter) = 0; } - else if (format_size == format_size_long) + else if (parameter_size == parameter_size_long) { *((double *)next_parameter) = 0; } @@ -560,239 +593,386 @@ vfscanf(FILE *stream, const char *format, va_list arg) } } + /* Now it gets complicated. We need to pick up a keyword + such as "inf", "infinity" or "nan" if it's present. + This is tricky because we won't be able to push all + the characters back we read during scanning. */ if(maximum_field_width != 0) { - while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) + const char infinity[] = "infinity"; + const char nan[] = "nan"; + char chars_read_so_far[80]; + size_t num_chars_read_so_far = 0; + size_t infinity_match = 0; + size_t nan_match = 0; + + while(maximum_field_width != 0 && num_chars_read_so_far < sizeof(chars_read_so_far) && (c = __getc(stream)) != EOF) { - /* Is this a digit? */ - if('0' <= c && c <= '9') + D(("c = '%lc'",c)); + + if(tolower(c) == infinity[infinity_match]) { - D(("got another digit '%lc'",c)); + SHOWVALUE(infinity_match); - new_sum = (10 * sum) + (c - '0'); - if(new_sum < sum) /* overflow? */ + nan_match = 0; + + chars_read_so_far[num_chars_read_so_far++] = c; + if(maximum_field_width > 0) + maximum_field_width--; + + /* Did we match the complete word? */ + infinity_match++; + if(infinity_match == sizeof(infinity)-1) { - /* Put this back. */ - if(ungetc(c,stream) == EOF) - { - SHOWMSG("couldn't push this character back"); - goto out; - } - + SHOWMSG("we have a match for infinity"); break; } - - sum = new_sum; } - else + else if (infinity_match == 3) /* Did we match the "inf" of "infinity"? */ { - D(("'%lc' is not a digit",c)); + SHOWVALUE(infinity_match); + + nan_match = 0; - /* It's not a digit; reread this later. */ if(ungetc(c,stream) == EOF) { SHOWMSG("couldn't push this character back"); goto out; } + SHOWMSG("we have a match for inf"); break; } - - total_num_chars_read++; - num_chars_processed++; - - if(maximum_field_width > 0) - maximum_field_width--; - } - - if(c == EOF && num_chars_processed == 0 && num_conversions == 0) - goto out; - } - - if(maximum_field_width != 0) - { - SHOWMSG("looking for decimal point"); - - c = __getc(stream); - if(c != EOF) - { - __locale_lock(); - - /* Did we find the decimal point? We accept both the - * locale configured decimal point and the plain old - * dot. - */ - if(__locale_table[LC_NUMERIC] != NULL) + else if (tolower(c) == nan[nan_match]) { - unsigned char * point; + SHOWVALUE(nan_match); - point = (unsigned char *)__locale_table[LC_NUMERIC]->loc_DecimalPoint; - - if(c == (*point) || c == '.') - { - SHOWMSG("found a decimal point"); - - decimal_point_matches = TRUE; - } - else - { - D(("'%lc' is not a decimal point",c)); - } - } - else - { - if(c == '.') - { - SHOWMSG("found a decimal point"); - - decimal_point_matches = TRUE; - } - else - { - D(("'%lc' is not a decimal point",c)); - } - } - - __locale_unlock(); - - if(decimal_point_matches) - { - total_num_chars_read++; + infinity_match = 0; + chars_read_so_far[num_chars_read_so_far++] = c; if(maximum_field_width > 0) maximum_field_width--; - } - else if (c == 'e' || c == 'E') - { - SHOWMSG("found an exponent specifier"); - total_num_chars_read++; - - have_exponent = TRUE; - - if(maximum_field_width > 0) - maximum_field_width--; - } - else - { - if(ungetc(c,stream) == EOF) + /* Did we match the complete word? */ + nan_match++; + if(nan_match == sizeof(nan)-1) { - SHOWMSG("couldn't push this character back"); - goto out; - } - } - } + SHOWMSG("we have a match for nan"); - if(decimal_point_matches) - { - double multiplier = 0.1; - - SHOWMSG("found a decimal point"); - - /* Process all digits following the decimal point. */ - while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) - { - if('0' <= c && c <= '9') - { - if(multiplier != 0.0) + /* Check for the () to follow the nan. */ + if(maximum_field_width != 0 && num_chars_read_so_far < sizeof(chars_read_so_far) && (c = __getc(stream)) != EOF) { - new_sum = sum + (c - '0') * multiplier; - if(new_sum < sum) /* overflow? */ + /* Is this the opening parenthesis of the "nan()" keyword? */ + if(c == '(') { - SHOWMSG("got an overflow"); + SHOWMSG("there's something following the nan"); - /* Put this back. */ + nan_match++; + + if(maximum_field_width > 0) + maximum_field_width--; + + /* Look for the closing parenthesis. */ + while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) + { + nan_match++; + + if(maximum_field_width > 0) + maximum_field_width--; + + if(c == ')') + break; + } + } + else + { if(ungetc(c,stream) == EOF) { SHOWMSG("couldn't push this character back"); goto out; } - - break; } - - sum = new_sum; - - multiplier = multiplier / 10.0; - } - - total_num_chars_read++; - - if(maximum_field_width > 0) - maximum_field_width--; - } - else if (c == 'e' || c == 'E') - { - SHOWMSG("found an exponent specifier"); - - total_num_chars_read++; - - if(maximum_field_width > 0) - maximum_field_width--; - - have_exponent = TRUE; - break; - } - else - { - if(ungetc(c,stream) == EOF) - { - SHOWMSG("couldn't push this character back"); - goto out; } break; } } + else + { + SHOWMSG("we didn't find a match for infinity/nan"); + + nan_match = infinity_match = 0; + + if(ungetc(c,stream) == EOF) + { + SHOWMSG("couldn't push this character back"); + goto out; + } + + maximum_field_width += num_chars_read_so_far; + + /* Let's try our best here... */ + while(num_chars_read_so_far > 0) + ungetc(chars_read_so_far[--num_chars_read_so_far],stream); + + break; + } } - if(have_exponent) + SHOWVALUE(infinity_match); + + if(infinity_match >= 3) { - BOOL exponent_is_negative = FALSE; - int new_exponent; - int exponent = 0; + union ieee_double x; - SHOWMSG("processing exponent"); + SHOWMSG("infinity"); - if(maximum_field_width != 0) + /* Exponent = 2047 and fraction = 0.0 */ + x.raw[0] = 0x7ff00000; + x.raw[1] = 0x00000000; + + sum = x.value; + + total_num_chars_read = num_chars_processed = infinity_match; + } + else if (nan_match >= 3) + { + union ieee_double x; + + SHOWMSG("not a number"); + + /* Exponent = 2047 and fraction != 0.0 */ + x.raw[0] = 0x7ff00000; + x.raw[1] = 0x00000001; + + sum = x.value; + + total_num_chars_read = num_chars_processed = nan_match; + } + } + + /* If we didn't find a keyword above, look for digits. */ + if(num_chars_processed == 0) + { + int radix = 10; + + /* Check if there's a hex prefix introducing this number. */ + if(maximum_field_width != 0 && (c = __getc(stream)) != EOF) + { + if(c == '0') { - c = __getc(stream); - if(c != EOF) + /* Use the leading zero as is. */ + total_num_chars_read++; + num_chars_processed++; + + if(maximum_field_width > 0) + maximum_field_width--; + + if(maximum_field_width != 0 && (c = __getc(stream)) != EOF) { - /* Skip the sign. */ - if(c == '-') + if(tolower(c) == 'x') { - exponent_is_negative = TRUE; + SHOWMSG("found the 0x prefix; setting radix to 16"); + + /* The floating point number will be encoded + in hexadecimal/binary notation. */ + radix = 16; total_num_chars_read++; - - if(maximum_field_width > 0) - maximum_field_width--; - } - else if (c == '+') - { - total_num_chars_read++; + num_chars_processed++; if(maximum_field_width > 0) maximum_field_width--; } else { - /* It's not a sign; reread this later. */ + /* Put this back. */ if(ungetc(c,stream) == EOF) { SHOWMSG("couldn't push this character back"); goto out; } } + } + } + else + { + /* Put this back. */ + if(ungetc(c,stream) == EOF) + { + SHOWMSG("couldn't push this character back"); + goto out; + } + } + } - while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) + if(maximum_field_width != 0) + { + int digit; + + while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) + { + /* Is this a digit? */ + if('0' <= c && c <= '9') + digit = c - '0'; + else if ('a' <= c && c <= 'f') + digit = c - 'a' + 10; + else if ('A' <= c && c <= 'F') + digit = c - 'A' + 10; + else + digit = radix; + + if(digit < radix) + { + D(("got another digit '%lc'",c)); + + new_sum = (radix * sum) + digit; + if(new_sum < sum) /* overflow? */ { - if('0' <= c && c <= '9') + /* Put this back. */ + if(ungetc(c,stream) == EOF) { - new_exponent = (10 * exponent) + (c - '0'); - if(new_exponent < exponent) /* overflow? */ + SHOWMSG("couldn't push this character back"); + goto out; + } + + break; + } + + sum = new_sum; + } + else + { + D(("'%lc' is not a digit",c)); + + /* It's not a digit; reread this later. */ + if(ungetc(c,stream) == EOF) + { + SHOWMSG("couldn't push this character back"); + goto out; + } + + break; + } + + total_num_chars_read++; + num_chars_processed++; + + if(maximum_field_width > 0) + maximum_field_width--; + } + + if(c == EOF && num_chars_processed == 0 && num_conversions == 0) + goto out; + } + + if(maximum_field_width != 0) + { + SHOWMSG("looking for decimal point"); + + c = __getc(stream); + if(c != EOF) + { + __locale_lock(); + + /* Did we find the decimal point? We accept both the + * locale configured decimal point and the plain old + * dot. + */ + if(__locale_table[LC_NUMERIC] != NULL) + { + unsigned char * point; + + point = (unsigned char *)__locale_table[LC_NUMERIC]->loc_DecimalPoint; + + if(c == (*point) || c == '.') + { + SHOWMSG("found a decimal point"); + + decimal_point_matches = TRUE; + } + else + { + D(("'%lc' is not a decimal point",c)); + } + } + else + { + if(c == '.') + { + SHOWMSG("found a decimal point"); + + decimal_point_matches = TRUE; + } + else + { + D(("'%lc' is not a decimal point",c)); + } + } + + __locale_unlock(); + + if(decimal_point_matches) + { + total_num_chars_read++; + + if(maximum_field_width > 0) + maximum_field_width--; + } + else if ((radix == 10 && (c == 'e' || c == 'E')) || + (radix == 16 && (c == 'p' || c == 'P'))) + { + SHOWMSG("found an exponent specifier"); + + total_num_chars_read++; + + have_exponent = TRUE; + + if(maximum_field_width > 0) + maximum_field_width--; + } + else + { + if(ungetc(c,stream) == EOF) + { + SHOWMSG("couldn't push this character back"); + goto out; + } + } + } + + if(decimal_point_matches) + { + double multiplier = 1.0 / radix; + int digit; + + SHOWMSG("found a decimal point"); + + /* Process all digits following the decimal point. */ + while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) + { + /* Is this a digit? */ + if('0' <= c && c <= '9') + digit = c - '0'; + else if ('a' <= c && c <= 'f') + digit = c - 'a' + 10; + else if ('A' <= c && c <= 'F') + digit = c - 'A' + 10; + else + digit = radix; + + if(digit < radix) + { + D(("got another digit '%lc'",c)); + + if(multiplier != 0.0) + { + new_sum = sum + digit * multiplier; + if(new_sum < sum) /* overflow? */ { + SHOWMSG("got an overflow"); + + /* Put this back. */ if(ungetc(c,stream) == EOF) { SHOWMSG("couldn't push this character back"); @@ -802,8 +982,76 @@ vfscanf(FILE *stream, const char *format, va_list arg) break; } - exponent = new_exponent; + sum = new_sum; + multiplier = multiplier / radix; + } + + total_num_chars_read++; + + if(maximum_field_width > 0) + maximum_field_width--; + } + else if ((radix == 10 && (c == 'e' || c == 'E')) || + (radix == 16 && (c == 'p' || c == 'P'))) + { + SHOWMSG("found an exponent specifier"); + + total_num_chars_read++; + + if(maximum_field_width > 0) + maximum_field_width--; + + have_exponent = TRUE; + break; + } + else + { + if(ungetc(c,stream) == EOF) + { + SHOWMSG("couldn't push this character back"); + goto out; + } + + break; + } + } + } + + if(have_exponent) + { + BOOL exponent_is_negative = FALSE; + int new_exponent; + int exponent = 0; + int exponent_radix; + + SHOWMSG("processing exponent"); + + /* The exponent may be a binary number. */ + if(radix == 16) + exponent_radix = 2; + else + exponent_radix = 10; + + if(maximum_field_width != 0) + { + c = __getc(stream); + if(c != EOF) + { + int digit; + + /* Skip the sign. */ + if(c == '-') + { + exponent_is_negative = TRUE; + + total_num_chars_read++; + + if(maximum_field_width > 0) + maximum_field_width--; + } + else if (c == '+') + { total_num_chars_read++; if(maximum_field_width > 0) @@ -811,38 +1059,79 @@ vfscanf(FILE *stream, const char *format, va_list arg) } else { + /* It's not a sign; reread this later. */ if(ungetc(c,stream) == EOF) { SHOWMSG("couldn't push this character back"); goto out; } - - break; } - } - /* If the exponent is valid, scale the number - * accordingly. - */ - if(exponent != 0) - { - if(exponent_is_negative) + while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) { - double divisor; - - /* A negative exponent means division. */ - divisor = pow(10.0,(double)exponent); - if(divisor != 0.0) - sum = sum / divisor; - } - else - { - /* A positive exponent means multiplication. */ - new_sum = sum * pow(10.0,(double)exponent); - if(new_sum >= sum) - sum = new_sum; + if('0' <= c && c <= '9') + digit = c - '0'; else - sum = __get_huge_val(); + digit = exponent_radix; + + if(digit < exponent_radix) + { + D(("got another digit '%lc'",c)); + + new_exponent = (exponent_radix * exponent) + digit; + if(new_exponent < exponent) /* overflow? */ + { + if(ungetc(c,stream) == EOF) + { + SHOWMSG("couldn't push this character back"); + goto out; + } + + break; + } + + exponent = new_exponent; + + total_num_chars_read++; + + if(maximum_field_width > 0) + maximum_field_width--; + } + else + { + if(ungetc(c,stream) == EOF) + { + SHOWMSG("couldn't push this character back"); + goto out; + } + + break; + } + } + + /* If the exponent is valid, scale the number + * accordingly. + */ + if(exponent != 0) + { + if(exponent_is_negative) + { + double divisor; + + /* A negative exponent means division. */ + divisor = pow(radix,(double)exponent); + if(divisor != 0.0) + sum = sum / divisor; + } + else + { + /* A positive exponent means multiplication. */ + new_sum = sum * pow(radix,(double)exponent); + if(new_sum >= sum) + sum = new_sum; + else + sum = __get_huge_val(); + } } } } @@ -859,11 +1148,11 @@ vfscanf(FILE *stream, const char *format, va_list arg) if(is_negative) sum = (-sum); - if(format_size == format_size_default) + if(parameter_size == parameter_size_default) { *((float *)next_parameter) = sum; } - else if (format_size == format_size_long) + else if (parameter_size == parameter_size_long) { *((double *)next_parameter) = sum; } @@ -896,13 +1185,13 @@ vfscanf(FILE *stream, const char *format, va_list arg) } #endif /* CHECK_FOR_NULL_POINTERS */ - if(format_size == format_size_default) + if(parameter_size == parameter_size_default) { SHOWMSG("short format (float)"); next_parameter = va_arg(arg,float *); } - else if (format_size == format_size_long) + else if (parameter_size == parameter_size_long) { SHOWMSG("long format (double)"); @@ -944,7 +1233,7 @@ vfscanf(FILE *stream, const char *format, va_list arg) int sum = 0; #endif /* __GNUC__ */ BOOL is_negative = FALSE; - int base; + int radix; void * next_parameter = NULL; /* We boldly try to initialize the parameter to a well- @@ -963,15 +1252,19 @@ vfscanf(FILE *stream, const char *format, va_list arg) } #endif /* CHECK_FOR_NULL_POINTERS */ - if(format_size == format_size_short) + if(parameter_size == parameter_size_short) { next_parameter = va_arg(arg,short *); } + else if (parameter_size == parameter_size_byte) + { + next_parameter = va_arg(arg,char *); + } else { #if defined(USE_64_BIT_INTS) && defined(__GNUC__) { - if(format_size == format_size_long_long) + if(parameter_size == parameter_size_long_long || parameter_size == parameter_size_intmax_t) next_parameter = va_arg(arg,long long *); else next_parameter = va_arg(arg,int *); @@ -995,15 +1288,19 @@ vfscanf(FILE *stream, const char *format, va_list arg) } #endif /* CHECK_FOR_NULL_POINTERS */ - if(format_size == format_size_short) + if(parameter_size == parameter_size_short) { *((short *)next_parameter) = 0; } + else if (parameter_size == parameter_size_byte) + { + *((char *)next_parameter) = 0; + } else { #if defined(USE_64_BIT_INTS) && defined(__GNUC__) { - if(format_size == format_size_long_long) + if(parameter_size == parameter_size_long_long || parameter_size == parameter_size_intmax_t) *((long long *)next_parameter) = 0; else *((int *)next_parameter) = 0; @@ -1021,11 +1318,11 @@ vfscanf(FILE *stream, const char *format, va_list arg) incoming data rather than commit ourselves to a peculiar data format now. */ if(conversion_type == 'd' || conversion_type == 'u') - base = 10; + radix = 10; else if (conversion_type == 'o') - base = 8; + radix = 8; else - base = 0; + radix = 0; if(maximum_field_width != 0) { @@ -1058,7 +1355,7 @@ vfscanf(FILE *stream, const char *format, va_list arg) if(maximum_field_width > 0) maximum_field_width--; - if(base == 0 && maximum_field_width != 0) + if(radix == 0 && maximum_field_width != 0) { /* This could be an octal number, the * '0x' prefix or just a zero. @@ -1071,7 +1368,7 @@ vfscanf(FILE *stream, const char *format, va_list arg) if ((c == 'x' || c == 'X') && (conversion_type == 'x' || conversion_type == 'i')) { /* It's the hex prefix. */ - base = 16; + radix = 16; /* The preceding '0' was part of the hex prefix. So we don't really know @@ -1091,7 +1388,7 @@ vfscanf(FILE *stream, const char *format, va_list arg) num_chars_processed--; /* It's an octal number. */ - base = 8; + radix = 8; /* Process the rest later. */ if(ungetc(c,stream) == EOF) @@ -1114,90 +1411,80 @@ vfscanf(FILE *stream, const char *format, va_list arg) } /* Pick a base if none has been chosen yet. */ - if(base == 0) + if(radix == 0) { if(conversion_type == 'x') - base = 16; + radix = 16; else - base = 10; + radix = 10; } if(maximum_field_width != 0) { + int digit; + while(maximum_field_width != 0 && (c = __getc(stream)) != EOF) { /* Is this a digit or hexadecimal value? */ - if(isxdigit(c)) - { - int digit; - - /* Perform the necessary conversion. */ - if('0' <= c && c <= '9') - digit = c - '0'; - else if ('a' <= c && c <= 'f') - digit = c - 'a' + 10; - else - digit = c - 'A' + 10; - - /* Is this a valid digit? */ - if(digit > base) - { - if(ungetc(c,stream) == EOF) - goto out; - - break; - } - - next_sum = (base * sum) + digit; - - #if defined(USE_64_BIT_INTS) && defined(__GNUC__) - { - if(format_size == format_size_long_long && (unsigned long long)next_sum < (unsigned long long)sum) /* overflow? */ - { - /* Put this back. */ - if(ungetc(c,stream) == EOF) - goto out; - - break; - } - else if ((unsigned int)next_sum < (unsigned int)sum) /* overflow? */ - { - /* Put this back. */ - if(ungetc(c,stream) == EOF) - goto out; - - break; - } - } - #else - { - if((unsigned int)next_sum < (unsigned int)sum) /* overflow? */ - { - /* Put this back. */ - if(ungetc(c,stream) == EOF) - goto out; - - break; - } - } - #endif /* __GNUC__ */ - - total_num_chars_read++; - num_chars_processed++; - - sum = next_sum; - - if(maximum_field_width > 0) - maximum_field_width--; - } + if('0' <= c && c <= '9') + digit = c - '0'; + else if ('a' <= c && c <= 'f') + digit = c - 'a' + 10; + else if ('A' <= c && c <= 'F') + digit = c - 'A' + 10; else + digit = radix; + + /* Is this a valid digit? */ + if(digit >= radix) { - /* It's something else; reread this later. */ if(ungetc(c,stream) == EOF) goto out; break; } + + next_sum = (radix * sum) + digit; + + #if defined(USE_64_BIT_INTS) && defined(__GNUC__) + { + if((parameter_size == parameter_size_long_long || parameter_size == parameter_size_intmax_t) && (unsigned long long)next_sum < (unsigned long long)sum) /* overflow? */ + { + /* Put this back. */ + if(ungetc(c,stream) == EOF) + goto out; + + break; + } + else if ((unsigned int)next_sum < (unsigned int)sum) /* overflow? */ + { + /* Put this back. */ + if(ungetc(c,stream) == EOF) + goto out; + + break; + } + } + #else + { + if((unsigned int)next_sum < (unsigned int)sum) /* overflow? */ + { + /* Put this back. */ + if(ungetc(c,stream) == EOF) + goto out; + + break; + } + } + #endif /* __GNUC__ */ + + total_num_chars_read++; + num_chars_processed++; + + sum = next_sum; + + if(maximum_field_width > 0) + maximum_field_width--; } if(c == EOF && num_chars_processed == 0 && num_conversions == 0) @@ -1211,15 +1498,19 @@ vfscanf(FILE *stream, const char *format, va_list arg) if(is_negative) sum = (-sum); - if(format_size == format_size_short) + if(parameter_size == parameter_size_short) { *((short *)next_parameter) = sum; } + else if (parameter_size == parameter_size_byte) + { + *((char *)next_parameter) = sum; + } else { #if defined(USE_64_BIT_INTS) && defined(__GNUC__) { - if(format_size == format_size_long_long) + if(parameter_size == parameter_size_long_long || parameter_size == parameter_size_intmax_t) *((long long *)next_parameter) = sum; else *((int *)next_parameter) = sum; @@ -1332,7 +1623,7 @@ vfscanf(FILE *stream, const char *format, va_list arg) } #endif /* CHECK_FOR_NULL_POINTERS */ - if(format_size == format_size_short) + if(parameter_size == parameter_size_short) { short * short_ptr; @@ -1352,11 +1643,31 @@ vfscanf(FILE *stream, const char *format, va_list arg) (*short_ptr) = total_num_chars_read; } + else if (parameter_size == parameter_size_byte) + { + char * byte_ptr; + + byte_ptr = va_arg(arg,char *); + + assert( byte_ptr != NULL ); + + #if defined(CHECK_FOR_NULL_POINTERS) + { + if(byte_ptr == NULL) + { + __set_errno(EFAULT); + goto out; + } + } + #endif /* CHECK_FOR_NULL_POINTERS */ + + (*byte_ptr) = total_num_chars_read; + } else { #if defined(USE_64_BIT_INTS) && defined(__GNUC__) { - if(format_size == format_size_long_long) + if(parameter_size == parameter_size_long_long || parameter_size == parameter_size_intmax_t) { long long * int_ptr; diff --git a/library/stdlib_strtod.c b/library/stdlib_strtod.c index 2c5b4ce..5a35d45 100644 --- a/library/stdlib_strtod.c +++ b/library/stdlib_strtod.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtod.c,v 1.5 2005-05-08 08:51:29 obarthel Exp $ + * $Id: stdlib_strtod.c,v 1.6 2005-05-08 11:27:26 obarthel Exp $ * * :ts=4 * @@ -123,17 +123,23 @@ strtod(const char *str, char ** ptr) /* We begin by checking for the "inf" and "nan" strings. */ if(strcasecmp(str,"inf") == SAME || strcasecmp(str,"infinity") == SAME) { - union ieee_double * x = (union ieee_double *)∑ + union ieee_double x; + + SHOWMSG("infinity"); str += strlen(str); /* Exponent = 2047 and fraction = 0.0 */ - x->raw[0] = 0x7ff00000; - x->raw[1] = 0x00000000; + x.raw[0] = 0x7ff00000; + x.raw[1] = 0x00000000; + + sum = x.value; } else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0')) { - union ieee_double * x = (union ieee_double *)∑ + union ieee_double x; + + SHOWMSG("not a number"); str += 3; @@ -148,8 +154,10 @@ strtod(const char *str, char ** ptr) } /* Exponent = 2047 and fraction != 0.0 */ - x->raw[0] = 0x7ff00000; - x->raw[1] = 0x00000001; + x.raw[0] = 0x7ff00000; + x.raw[1] = 0x00000001; + + sum = x.value; } else { @@ -272,12 +280,15 @@ strtod(const char *str, char ** ptr) int exponent_is_negative; int new_exponent; int exponent = 0; + int exponent_radix; /* If we are processing a hexadecimal encoded floating point number, switch to a binary exponent. */ if(radix == 16) - radix = 2; + exponent_radix = 2; + else + exponent_radix = 10; /* Skip the indicator. */ str++; @@ -302,16 +313,16 @@ strtod(const char *str, char ** ptr) if('0' <= c && c <= '9') c -= '0'; else - c = radix; + c = exponent_radix; - if(c >= radix) + if(c >= exponent_radix) break; str++; if(error == 0) { - new_exponent = (radix * exponent) + c; + new_exponent = (exponent_radix * exponent) + c; if(new_exponent < exponent) /* overflow? */ error = ERANGE; else diff --git a/library/stdlib_strtof.c b/library/stdlib_strtof.c index 68457de..03c9a2c 100644 --- a/library/stdlib_strtof.c +++ b/library/stdlib_strtof.c @@ -1,5 +1,5 @@ /* - * $Id: stdlib_strtof.c,v 1.3 2005-05-08 08:51:29 obarthel Exp $ + * $Id: stdlib_strtof.c,v 1.4 2005-05-08 11:27:26 obarthel Exp $ * * :ts=4 * @@ -123,16 +123,22 @@ strtof(const char *str, char ** ptr) /* We begin by checking for the "inf" and "nan" strings. */ if(strcasecmp(str,"inf") == SAME || strcasecmp(str,"infinity") == SAME) { - union ieee_single * x = (union ieee_single *)∑ + union ieee_single x; + + SHOWMSG("infinity"); str += strlen(str); /* Exponent = 255 and fraction = 0.0 */ - x->raw[0] = 0x7f800000; + x.raw[0] = 0x7f800000; + + sum = x.value; } else if (strncasecmp(str,"nan",3) == SAME && (str[3] == '(' || str[3] == '\0')) { - union ieee_single * x = (union ieee_single *)∑ + union ieee_single x; + + SHOWMSG("not a number"); str += 3; @@ -147,7 +153,9 @@ strtof(const char *str, char ** ptr) } /* Exponent = 255 and fraction != 0.0 */ - x->raw[0] = 0x7f800001; + x.raw[0] = 0x7f800001; + + sum = x.value; } else { @@ -270,12 +278,15 @@ strtof(const char *str, char ** ptr) int exponent_is_negative; int new_exponent; int exponent = 0; + int exponent_radix; /* If we are processing a hexadecimal encoded floating point number, switch to a binary exponent. */ if(radix == 16) - radix = 2; + exponent_radix = 2; + else + exponent_radix = 10; /* Skip the indicator. */ str++; @@ -300,16 +311,16 @@ strtof(const char *str, char ** ptr) if('0' <= c && c <= '9') c -= '0'; else - c = radix; + c = exponent_radix; - if(c >= radix) + if(c >= exponent_radix) break; str++; if(error == 0) { - new_exponent = (radix * exponent) + c; + new_exponent = (exponent_radix * exponent) + c; if(new_exponent < exponent) /* overflow? */ error = ERANGE; else diff --git a/library/time_strftime.c b/library/time_strftime.c index 270ceda..d9f9919 100644 --- a/library/time_strftime.c +++ b/library/time_strftime.c @@ -1,5 +1,5 @@ /* - * $Id: time_strftime.c,v 1.12 2005-05-07 14:03:08 obarthel Exp $ + * $Id: time_strftime.c,v 1.13 2005-05-08 11:27:26 obarthel Exp $ * * :ts=4 * @@ -113,7 +113,9 @@ julian_day(int day,int month,int year) y = year + 4800 - a; m = month + 12 * a - 3; - result = day + (153 * m + 2) / 5 + 365 * y + (y/4) - (y/100) + (y/400) - 32045; + result = day + (153 * m + 2) / 5 + 365 * y + (y / 4) - (y / 100) + (y / 400) - 32045; + + return(result); } STATIC int