From patchwork Fri Jun 2 12:00:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 20694 Received: (qmail 91602 invoked by alias); 2 Jun 2017 12:00:57 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 91010 invoked by uid 89); 2 Jun 2017 12:00:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=FORMAT, Unlock, UD:q, Slow X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6F3FD142A79 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 6F3FD142A79 Date: Fri, 02 Jun 2017 14:00:11 +0200 To: libc-alpha@sourceware.org Subject: [PATCH] vfscanf: Implement struct char_buffer with a dynamic array User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20170602120011.693C5400EA94D@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) 2017-06-02 Florian Weimer * stdio-common/vfscanf.c (struct char_buffer): Define using . (_IO_vfscanf_internal): Adjust to dynarray-based struct char_buffer. diff --git a/stdio-common/vfscanf.c b/stdio-common/vfscanf.c index 1adf27e..093d17c 100644 --- a/stdio-common/vfscanf.c +++ b/stdio-common/vfscanf.c @@ -30,7 +30,6 @@ #include #include #include -#include #ifdef __GNUC__ # define HAVE_LONGLONG @@ -187,6 +186,7 @@ _IO_funlockfile (S); \ __libc_cleanup_region_end (0) + struct ptrs_to_free { size_t count; @@ -194,77 +194,14 @@ struct ptrs_to_free char **ptrs[32]; }; -struct char_buffer { - CHAR_T *current; - CHAR_T *end; - struct scratch_buffer scratch; -}; - -/* Returns a pointer to the first CHAR_T object in the buffer. Only - valid if char_buffer_add (BUFFER, CH) has been called and - char_buffer_error (BUFFER) is false. */ -static inline CHAR_T * -char_buffer_start (const struct char_buffer *buffer) -{ - return (CHAR_T *) buffer->scratch.data; -} - -/* Returns the number of CHAR_T objects in the buffer. Only valid if - char_buffer_error (BUFFER) is false. */ -static inline size_t -char_buffer_size (const struct char_buffer *buffer) -{ - return buffer->current - char_buffer_start (buffer); -} - -/* Reinitializes BUFFER->current and BUFFER->end to cover the entire - scratch buffer. */ -static inline void -char_buffer_rewind (struct char_buffer *buffer) -{ - buffer->current = char_buffer_start (buffer); - buffer->end = buffer->current + buffer->scratch.length / sizeof (CHAR_T); -} - -/* Returns true if a previous call to char_buffer_add (BUFFER, CH) - failed. */ -static inline bool -char_buffer_error (const struct char_buffer *buffer) -{ - return __glibc_unlikely (buffer->current == NULL); -} - -/* Slow path for char_buffer_add. */ -static void -char_buffer_add_slow (struct char_buffer *buffer, CHAR_T ch) -{ - if (char_buffer_error (buffer)) - return; - size_t offset = buffer->end - (CHAR_T *) buffer->scratch.data; - if (!scratch_buffer_grow_preserve (&buffer->scratch)) - { - buffer->current = NULL; - buffer->end = NULL; - return; - } - char_buffer_rewind (buffer); - buffer->current += offset; - *buffer->current++ = ch; -} - -/* Adds CH to BUFFER. This function does not report any errors, check - for them with char_buffer_error. */ -static inline void -char_buffer_add (struct char_buffer *buffer, CHAR_T ch) - __attribute__ ((always_inline)); -static inline void -char_buffer_add (struct char_buffer *buffer, CHAR_T ch) -{ - if (__glibc_unlikely (buffer->current == buffer->end)) - char_buffer_add_slow (buffer, ch); - else - *buffer->current++ = ch; -} +#define DYNARRAY_STRUCT char_buffer +#define DYNARRAY_ELEMENT CHAR_T +#define DYNARRAY_PREFIX char_buffer_ +#ifndef COMPILE_WSCANF +/* We need 256 array elements for processing %[...] specifiers. */ +# define DYNARRAY_INITIAL_SIZE 256 +#endif +#include /* Read formatted input from S according to the format string FORMAT, using the argument list in ARG. @@ -337,7 +274,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Workspace. */ CHAR_T *tw; /* Temporary pointer. */ struct char_buffer charbuf; - scratch_buffer_init (&charbuf.scratch); + char_buffer_init (&charbuf); #ifdef __va_copy __va_copy (arg, argptr); @@ -485,7 +422,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, argpos = 0; /* Prepare temporary buffer. */ - char_buffer_rewind (&charbuf); + char_buffer_clear (&charbuf); /* Check for a positional parameter specification. */ if (ISDIGIT ((UCHAR_T) *f)) @@ -1692,7 +1629,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, } } - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -1704,7 +1641,9 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* We are pushing all read characters back. */ if (cmpp > thousands) { - charbuf.current -= cmpp - thousands; + char_buffer_resize + (&charbuf, + char_buffer_size (&charbuf) - (cmpp - thousands)); ungetc (c, s); while (--cmpp > thousands) ungetc_not_eof ((unsigned char) *cmpp, s); @@ -1718,7 +1657,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* The last thousands character will be added back by the char_buffer_add below. */ - --charbuf.current; + char_buffer_remove_last (&charbuf); #endif } else @@ -1765,7 +1704,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, } } - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -1777,7 +1716,9 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* We are pushing all read characters back. */ if (cmpp > thousands) { - charbuf.current -= cmpp - thousands; + char_buffer_resize + (&charbuf, + char_buffer_size (&charbuf) - (cmpp - thousands)); ungetc (c, s); while (--cmpp > thousands) ungetc_not_eof ((unsigned char) *cmpp, s); @@ -1791,7 +1732,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* The last thousands character will be added back by the char_buffer_add below. */ - --charbuf.current; + char_buffer_remove_last (&charbuf); #endif } else @@ -1804,7 +1745,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, c = inchar (); } - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -1813,8 +1754,8 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if (char_buffer_size (&charbuf) == 0 || (char_buffer_size (&charbuf) == 1 - && (char_buffer_start (&charbuf)[0] == L_('+') - || char_buffer_start (&charbuf)[0] == L_('-')))) + && (*char_buffer_at (&charbuf, 0) == L_('+') + || *char_buffer_at (&charbuf, 0) == L_('-')))) { /* There was no number. If we are supposed to read a pointer we must recognize "(nil)" as well. */ @@ -1844,7 +1785,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Convert the number. */ char_buffer_add (&charbuf, L_('\0')); - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -1854,21 +1795,21 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, { if (flags & NUMBER_SIGNED) num.q = __strtoll_internal - (char_buffer_start (&charbuf), &tw, base, flags & GROUP); + (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP); else num.uq = __strtoull_internal - (char_buffer_start (&charbuf), &tw, base, flags & GROUP); + (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP); } else { if (flags & NUMBER_SIGNED) num.l = __strtol_internal - (char_buffer_start (&charbuf), &tw, base, flags & GROUP); + (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP); else num.ul = __strtoul_internal - (char_buffer_start (&charbuf), &tw, base, flags & GROUP); + (char_buffer_at (&charbuf, 0), &tw, base, flags & GROUP); } - if (__glibc_unlikely (char_buffer_start (&charbuf) == tw)) + if (__glibc_unlikely (char_buffer_at (&charbuf, 0) == tw)) conv_error (); if (!(flags & SUPPRESS)) @@ -2045,7 +1986,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, while (1) { - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -2061,7 +2002,10 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, char_buffer_add (&charbuf, c); got_digit = 1; } - else if (got_e && charbuf.current[-1] == exp_char + else if (got_e + && *char_buffer_at (&charbuf, + char_buffer_size (&charbuf) - 1) + == exp_char && (c == L_('-') || c == L_('+'))) char_buffer_add (&charbuf, c); else if (got_digit && !got_e @@ -2167,7 +2111,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, --width; } - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -2279,13 +2223,16 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, conversion is done correctly. */ while (1) { - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; goto errout; } - if (got_e && charbuf.current[-1] == exp_char + if (got_e + && *char_buffer_at (&charbuf, + char_buffer_size (&charbuf) - 1) + == exp_char && (c == L_('-') || c == L_('+'))) char_buffer_add (&charbuf, c); else if (char_buffer_size (&charbuf) > 0 && !got_e @@ -2402,7 +2349,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, #endif } - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -2420,7 +2367,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, scan_float: /* Convert the number. */ char_buffer_add (&charbuf, L_('\0')); - if (char_buffer_error (&charbuf)) + if (char_buffer_has_failed (&charbuf)) { __set_errno (ENOMEM); done = EOF; @@ -2429,26 +2376,26 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, if ((flags & LONGDBL) && !__ldbl_is_dbl) { long double d = __strtold_internal - (char_buffer_start (&charbuf), &tw, flags & GROUP); - if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf)) + (char_buffer_at (&charbuf, 0), &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != char_buffer_at (&charbuf, 0)) *ARG (long double *) = negative ? -d : d; } else if (flags & (LONG | LONGDBL)) { double d = __strtod_internal - (char_buffer_start (&charbuf), &tw, flags & GROUP); - if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf)) + (char_buffer_at (&charbuf, 0), &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != char_buffer_at (&charbuf, 0)) *ARG (double *) = negative ? -d : d; } else { float d = __strtof_internal - (char_buffer_start (&charbuf), &tw, flags & GROUP); - if (!(flags & SUPPRESS) && tw != char_buffer_start (&charbuf)) + (char_buffer_at (&charbuf, 0), &tw, flags & GROUP); + if (!(flags & SUPPRESS) && tw != char_buffer_at (&charbuf, 0)) *ARG (float *) = negative ? -d : d; } - if (__glibc_unlikely (tw == char_buffer_start (&charbuf))) + if (__glibc_unlikely (tw == char_buffer_at (&charbuf, 0))) conv_error (); if (!(flags & SUPPRESS)) @@ -2494,13 +2441,12 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, #else /* Fill WP with byte flags indexed by character. We will use this flag map for matching input characters. */ - if (!scratch_buffer_set_array_size - (&charbuf.scratch, UCHAR_MAX + 1, 1)) + if (!char_buffer_resize (&charbuf, UCHAR_MAX + 1)) { done = EOF; goto errout; } - memset (charbuf.scratch.data, '\0', UCHAR_MAX + 1); + memset (char_buffer_at (&charbuf, 0), '\0', UCHAR_MAX + 1); fc = *f; if (fc == ']' || fc == '-') @@ -2508,7 +2454,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* If ] or - appears before any char in the set, it is not the terminator or separator, but the first char in the set. */ - ((char *)charbuf.scratch.data)[fc] = 1; + *char_buffer_at (&charbuf, fc) = 1; ++f; } @@ -2519,11 +2465,11 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Add all characters from the one before the '-' up to (but not including) the next format char. */ for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc) - ((char *)charbuf.scratch.data)[fc] = 1; + *char_buffer_at (&charbuf, fc) = 1; } else /* Add the character to the flag map. */ - ((char *)charbuf.scratch.data)[fc] = 1; + *char_buffer_at (&charbuf, fc) = 1; if (__glibc_unlikely (fc == '\0')) conv_error(); @@ -2652,7 +2598,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, do { - if (((char *) charbuf.scratch.data)[c] == not_in) + if (*char_buffer_at (&charbuf, c) == not_in) { ungetc_not_eof (c, s); break; @@ -2880,7 +2826,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, #else do { - if (((char *) charbuf.scratch.data)[c] == not_in) + if (*char_buffer_at (&charbuf, c) == not_in) { ungetc_not_eof (c, s); break; @@ -3020,7 +2966,7 @@ _IO_vfscanf_internal (_IO_FILE *s, const char *format, _IO_va_list argptr, /* Unlock stream. */ UNLOCK_STREAM (s); - scratch_buffer_free (&charbuf.scratch); + char_buffer_free (&charbuf); if (errp != NULL) *errp |= errval;