diff --git a/newlib/ChangeLog b/newlib/ChangeLog index af1b8d6f7..4243fb767 100644 --- a/newlib/ChangeLog +++ b/newlib/ChangeLog @@ -1,3 +1,15 @@ +2002-05-13 Jeff Johnston + + * libc/machine/powerpc/vfprintf.c(__VFPRINTF_R)[__ALTIVEC__]: Restore + the original format specifier when looping for vectors to compensate + for any changes made in vector %g format processing. + Also add syntax checking for various invalid scenarios + involving vector format extensions. + * libc/machine/powerpc/vfscanf.c(__VFSCANF_R)[__ALTIVEC__]: Fix + return code setting for vector formats. Also treat vector + separator mismatch as a match error instead of an input error. + Perform some syntax checking for vector formats. + 2002-05-10 Mark Bradshaw * libc/include/string.h (!__STRICT_ANSI__): Add strlcat and strlcpy. diff --git a/newlib/libc/machine/powerpc/vfprintf.c b/newlib/libc/machine/powerpc/vfprintf.c index aed3d704f..1e2fe529b 100644 --- a/newlib/libc/machine/powerpc/vfprintf.c +++ b/newlib/libc/machine/powerpc/vfprintf.c @@ -196,7 +196,7 @@ typedef union int i[16 / sizeof(int)]; long l[4]; short s[8]; - signed char c[16]; + signed char c[16]; } vec_16_byte_union; #endif /* __ALTIVEC__ */ @@ -337,6 +337,8 @@ _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap), int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ char old_sign; /* saved value of sign when looping for vectors */ + int old_ch; /* saved value of ch when looping for vectors */ + char *format_anchor; /* start of format to process */ wchar_t wc; #ifdef FLOATING_POINT char *decimal_point = localeconv()->decimal_point; @@ -535,7 +537,9 @@ _DEFUN (_VFPRINTF_R, (data, fp, fmt0, ap), vec_sep = ' '; #endif /* __ALTIVEC__ */ + format_anchor = fmt; rflag: ch = *fmt++; + old_ch = ch; reswitch: switch (ch) { case ' ': /* @@ -571,6 +575,11 @@ reswitch: switch (ch) { case ';': case ':': case '_': + if (vec_sep != ' ') + { + fmt = format_anchor; + continue; + } vec_sep = ch; goto rflag; #endif /* __ALTIVEC__ */ @@ -611,6 +620,11 @@ reswitch: switch (ch) { goto rflag; #endif case 'h': + if (flags & LONGINT) + { + fmt = format_anchor; + continue; + } flags |= SHORTINT; #ifdef __ALTIVEC__ if (flags & VECTOR) @@ -618,6 +632,11 @@ reswitch: switch (ch) { #endif goto rflag; case 'l': + if (flags & SHORTINT) + { + fmt = format_anchor; + continue; + } if (*fmt == 'l') { fmt++; flags |= QUADINT; @@ -632,13 +651,24 @@ reswitch: switch (ch) { goto rflag; #ifdef __ALTIVEC__ case 'v': + if (flags & VECTOR) + { + fmt = format_anchor; + continue; + } flags |= VECTOR; vec_print_count = (flags & SHORTINT) ? 8 : ((flags & LONGINT) ? 4 : 16); goto rflag; #endif case 'q': - flags &= ~VECTOR; +#ifdef __ALTIVEC__ + if (flags & VECTOR) + { + fmt = format_anchor; + continue; + } +#endif /* __ALTIVEC__ */ flags |= QUADINT; goto rflag; case 'c': @@ -646,6 +676,11 @@ reswitch: switch (ch) { if (flags & VECTOR) { int k; + if (flags & (SHORTINT | LONGINT)) + { + fmt = format_anchor; + continue; + } vec_16_byte_union tmp; tmp.v = va_arg(ap, vector int); cp = buf; @@ -673,6 +708,13 @@ reswitch: switch (ch) { /*FALLTHROUGH*/ case 'd': case 'i': +#ifdef __ALTIVEC__ + if (!(flags & VECTOR) && vec_sep != ' ') + { + fmt = format_anchor; + continue; + } +#endif /* __ALTIVEC__ */ _uquad = SARG(); #ifndef _NO_LONGLONG if ((quad_t)_uquad < 0) @@ -705,11 +747,15 @@ reswitch: switch (ch) { #ifdef __ALTIVEC__ } else if (flags & VECTOR) { if (vec_print_count >= 4) - { - vec_print_count = 4; + { + vec_print_count = 4; vec_tmp.v = va_arg(ap, vector int); - } + } _fpvalue = (double)vec_tmp.f[4 - vec_print_count]; + } else if (vec_sep != ' ') { + fmt = format_anchor; + continue; + #endif /* __ALTIVEC__ */ } else { _fpvalue = va_arg(ap, double); @@ -740,10 +786,10 @@ reswitch: switch (ch) { #ifdef __ALTIVEC__ } else if (flags & VECTOR) { if (vec_print_count >= 4) - { - vec_print_count = 4; + { + vec_print_count = 4; vec_tmp.v = va_arg(ap, vector int); - } + } _fpvalue = (_LONG_DOUBLE)k.f[4 - vec_print_count]; #endif /* __ALTIVEC__ */ } else { @@ -776,7 +822,10 @@ reswitch: switch (ch) { if (ch == 'g' || ch == 'G') { if (expt <= -4 || expt > prec) - ch = (ch == 'g') ? 'e' : 'E'; + { + old_ch = ch; + ch = (ch == 'g') ? 'e' : 'E'; + } else ch = 'g'; } @@ -826,6 +875,13 @@ reswitch: switch (ch) { flags |= LONGINT; /*FALLTHROUGH*/ case 'o': +#ifdef __ALTIVEC__ + if (!(flags & VECTOR) && vec_sep != ' ') + { + fmt = format_anchor; + continue; + } +#endif /* __ALTIVEC__ */ _uquad = UARG(); base = OCT; goto nosign; @@ -841,7 +897,12 @@ reswitch: switch (ch) { #ifdef __ALTIVEC__ if (flags & VECTOR) _uquad = UARG(); - else + else if (vec_sep != ' ') + { + fmt = format_anchor; + continue; + } + else #endif /* __ALTIVEC__ */ _uquad = (u_long)(unsigned _POINTER_INT)va_arg(ap, void *); base = HEX; @@ -850,7 +911,13 @@ reswitch: switch (ch) { ch = 'x'; goto nosign; case 's': - flags &= ~VECTOR; +#ifdef __ALTIVEC__ + if (flags & VECTOR) + { + fmt = format_anchor; + continue; + } +#endif /* __ALTIVEC__ */ if ((cp = va_arg(ap, char *)) == NULL) cp = "(null)"; if (prec >= 0) { @@ -875,6 +942,13 @@ reswitch: switch (ch) { flags |= LONGINT; /*FALLTHROUGH*/ case 'u': +#ifdef __ALTIVEC__ + if (!(flags & VECTOR) && vec_sep != ' ') + { + fmt = format_anchor; + continue; + } +#endif /* __ALTIVEC__ */ _uquad = UARG(); base = DEC; goto nosign; @@ -883,6 +957,13 @@ reswitch: switch (ch) { goto hex; case 'x': xdigs = "0123456789abcdef"; +#ifdef __ALTIVEC__ + if (!(flags & VECTOR) && vec_sep != ' ') + { + fmt = format_anchor; + continue; + } +#endif /* __ALTIVEC__ */ hex: _uquad = UARG(); base = HEX; /* leading 0x/X only if non-zero */ @@ -1078,6 +1159,7 @@ number: if ((dprec = prec) >= 0) } FLUSH(); sign = old_sign; + ch = old_ch; goto reswitch; } #endif /* __ALTIVEC__ */ diff --git a/newlib/libc/machine/powerpc/vfscanf.c b/newlib/libc/machine/powerpc/vfscanf.c index c0bd0e526..919147c3a 100644 --- a/newlib/libc/machine/powerpc/vfscanf.c +++ b/newlib/libc/machine/powerpc/vfscanf.c @@ -363,6 +363,8 @@ __svfscanf_r (rptr, fp, fmt0, ap) vec_sep = c; goto again; case 'l': + if (flags & SHORT) + continue; /* invalid format, don't process any further */ if (flags & LONG) { flags &= ~LONG; @@ -382,6 +384,8 @@ __svfscanf_r (rptr, fp, fmt0, ap) goto again; case 'h': flags |= SHORT; + if (flags & LONG) + continue; /* invalid format, don't process any further */ if (flags & VECTOR) vec_read_count = 8; goto again; @@ -482,6 +486,9 @@ __svfscanf_r (rptr, fp, fmt0, ap) type = CT_CHAR; if (flags & VECTOR) { + /* not allowed to have h or l with c specifier */ + if (flags & (LONG | SHORT)) + continue; /* invalid format don't process any further */ width = 0; vec_read_count = 16; } @@ -580,7 +587,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) { if (vec_sep == ' ' && last_space_char != ' ' || vec_sep != ' ' && *fp->_p != vec_sep) - goto input_failure; + goto match_failure; if (vec_sep != ' ') { nread++; @@ -958,7 +965,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) ip = va_arg (ap, int *); *ip++ = res; } - else + else { if (!looped) ch_dest = vec_buf.c; @@ -1172,6 +1179,7 @@ __svfscanf_r (rptr, fp, fmt0, ap) unsigned long *vp = va_arg (ap, unsigned long *); for (i = 0; i < 4; ++i) *vp++ = vec_buf.l[i]; + nassigned++; } } input_failure: