From patchwork Mon Oct 30 12:58:35 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 23962 Received: (qmail 111833 invoked by alias); 30 Oct 2017 12:58:42 -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 111819 invoked by uid 89); 30 Oct 2017 12:58:41 -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=failed!, 1977, 1997, l0 X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C5AD0C058EDD Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=fweimer@redhat.com Subject: Re: [PATCH] array_length, array_end macros for internal use To: libc-alpha@sourceware.org References: <9c9b0fdf-5b87-7e58-0b0b-c8469e56c0a4@redhat.com> From: Florian Weimer Message-ID: <37e10e6e-1df1-12fa-176b-e5ef69e5d564@redhat.com> Date: Mon, 30 Oct 2017 13:58:35 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 MIME-Version: 1.0 In-Reply-To: <9c9b0fdf-5b87-7e58-0b0b-c8469e56c0a4@redhat.com> Any further comments on this patch? Thanks, Florian 2017-10-21 Florian Weimer Add array_length and array_end macros. * include/array_length.h: New file. * stdio-common/bug16.c (do_test): Use array_length. * stdio-common/errlist.c (_sys_nerr): Likewise. * stdio-common/printf_fp.c (PRINTF_FP_FETCH): Likewise. * stdio-common/printf_fphex.c (__printf_fphex): Use array_end. * stdio-common/psiginfo.c (psiginfo): Use array_length. * stdio-common/test-vfprintf.c (nlocs): Remove definition. (do_test): Use array_length. * stdio-common/tst-fphex.c (do_test): Use array_end, array_length. * stdio-common/tst-long-dbl-fphex.c (do_test): Use array_length. * stdio-common/tst-printf-round.c (do_test): Likewise. * stdio-common/tst-swprintf.c (nbuf): Remove definition. (CHECK): Use array_length. * stdio-common/tstdiomisc.c (t3, F): Likewise. * stdio-common/tstscanf.c (main): Likewise. * stdio-common/vfprintf.c (process_string_arg): Likewise. diff --git a/include/array_length.h b/include/array_length.h new file mode 100644 index 0000000000..0bcc52bb14 --- /dev/null +++ b/include/array_length.h @@ -0,0 +1,36 @@ +/* The array_length and array_end macros. + Copyright (C) 1991-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _ARRAY_LENGTH_H +#define _ARRAY_LENGTH_H + +/* array_length (VAR) is the number of elements in the array VAR. VAR + must evaluate to an array, not a pointer. */ +#define array_length(var) \ + __extension__ ({ \ + _Static_assert (!__builtin_types_compatible_p \ + (__typeof (var), __typeof (&(var)[0])), \ + "argument must be an array"); \ + sizeof (var) / sizeof ((var)[0]); \ + }) + +/* array_end (VAR) is a pointer one past the end of the array VAR. + VAR must evaluate to an array, not a pointer. */ +#define array_end(var) (&(var)[array_length (var)]) + +#endif /* _ARRAY_LENGTH_H */ diff --git a/stdio-common/bug16.c b/stdio-common/bug16.c index 1112c39d05..91bc452826 100644 --- a/stdio-common/bug16.c +++ b/stdio-common/bug16.c @@ -1,3 +1,4 @@ +#include #include #include @@ -19,7 +20,7 @@ do_test (void) char buf[100]; int ret = 0; - for (size_t i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) + for (size_t i = 0; i < array_length (tests); ++i) { snprintf (buf, sizeof (buf), "%.0LA", tests[i].val); diff --git a/stdio-common/errlist.c b/stdio-common/errlist.c index 0f1b72b37d..e8d0f62519 100644 --- a/stdio-common/errlist.c +++ b/stdio-common/errlist.c @@ -15,9 +15,9 @@ License along with the GNU C Library; if not, see . */ +#include #include - const char *const _sys_errlist[] = { "Error 0", /* 0 */ @@ -33,4 +33,4 @@ const char *const _sys_errlist[] = "Too many open files", /* 10 = EMFILE */ }; -const int _sys_nerr = sizeof (_sys_errlist) / sizeof (_sys_errlist[0]); +const int _sys_nerr = array_length (_sys_errlist); diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index 994497cd22..52ba46bd08 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -21,6 +21,7 @@ /* The gmp headers need some configuration frobs. */ #define HAVE_ALLOCA 1 +#include #include #include #include @@ -371,8 +372,7 @@ __printf_fp_l (FILE *fp, locale_t loc, else \ { \ p.fracsize = __mpn_extract_##SUFFIX \ - (fp_input, \ - (sizeof (fp_input) / sizeof (fp_input[0])), \ + (fp_input, array_length (fp_input), \ &p.exponent, &is_neg, VAR); \ to_shift = 1 + p.fracsize * BITS_PER_MP_LIMB - MANT_DIG; \ } \ diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c index 004d2aa716..938b0b32e0 100644 --- a/stdio-common/printf_fphex.c +++ b/stdio-common/printf_fphex.c @@ -17,6 +17,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -320,8 +321,8 @@ __printf_fphex (FILE *fp, /* Look for trailing zeroes. */ if (! zero_mantissa) { - wnumend = &wnumbuf[sizeof wnumbuf / sizeof wnumbuf[0]]; - numend = &numbuf[sizeof numbuf / sizeof numbuf[0]]; + wnumend = array_end (wnumbuf); + numend = array_end (numbuf); while (wnumend[-1] == L'0') { --wnumend; diff --git a/stdio-common/psiginfo.c b/stdio-common/psiginfo.c index 7bf2e2d13f..b9c455b8f5 100644 --- a/stdio-common/psiginfo.c +++ b/stdio-common/psiginfo.c @@ -15,6 +15,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -116,7 +117,7 @@ psiginfo (const siginfo_t *pinfo, const char *s) case sig: \ base = C(codestrs_, sig).str; \ offarr = C (codes_, sig); \ - offarr_len = sizeof (C (codes_, sig)) / sizeof (C (codes_, sig)[0]);\ + offarr_len = array_length (C (codes_, sig)); \ break H (SIGILL); diff --git a/stdio-common/test-vfprintf.c b/stdio-common/test-vfprintf.c index f8bb9cee58..0fcc1adc0e 100644 --- a/stdio-common/test-vfprintf.c +++ b/stdio-common/test-vfprintf.c @@ -17,6 +17,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -32,8 +33,6 @@ const char *locs[] = { "C", "de_DE.ISO-8859-1", "de_DE.UTF-8", "ja_JP.EUC-JP" }; -#define nlocs (sizeof (locs) / sizeof (locs[0])) - char large[50000]; @@ -56,7 +55,7 @@ do_test (void) } unlink (buf); - for (i = 0; i < nlocs; ++i) + for (i = 0; i < array_length (locs); ++i) { FILE *fp; struct stat st; diff --git a/stdio-common/tst-fphex.c b/stdio-common/tst-fphex.c index c2e8961d62..efba482537 100644 --- a/stdio-common/tst-fphex.c +++ b/stdio-common/tst-fphex.c @@ -1,5 +1,6 @@ /* Test program for %a printf formats. */ +#include #include #include @@ -49,12 +50,10 @@ do_test (void) const struct testcase *t; int result = 0; - for (t = testcases; - t < &testcases[sizeof testcases / sizeof testcases[0]]; - ++t) + for (t = testcases; t < array_end (testcases); ++t) { CHAR_T buf[1024]; - int n = SPRINT (buf, sizeof buf / sizeof (buf[0]), t->fmt, t->value); + int n = SPRINT (buf, array_length (buf), t->fmt, t->value); if (n != STR_LEN (t->expect) || STR_CMP (buf, t->expect) != 0) { PRINT (L_("" S "\tExpected \"" S "\" (%Zu)\n\tGot \"" diff --git a/stdio-common/tst-long-dbl-fphex.c b/stdio-common/tst-long-dbl-fphex.c index 1170c74c4c..6a402a1c89 100644 --- a/stdio-common/tst-long-dbl-fphex.c +++ b/stdio-common/tst-long-dbl-fphex.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include /* Prototype for our test function. */ @@ -28,9 +29,9 @@ do_test (void) int result = 0; const long double x = 24.5; wchar_t a[16]; - swprintf (a, sizeof a / sizeof a[0], L"%La\n", x); + swprintf (a, array_length (a), L"%La\n", x); wchar_t A[16]; - swprintf (A, sizeof A / sizeof A[0], L"%LA\n", x); + swprintf (A, array_length (a), L"%LA\n", x); /* Here wprintf can return four valid variants. We must accept all of them. */ diff --git a/stdio-common/tst-printf-round.c b/stdio-common/tst-printf-round.c index e0073f2856..a5db3b88c2 100644 --- a/stdio-common/tst-printf-round.c +++ b/stdio-common/tst-printf-round.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -167,7 +168,7 @@ do_test (void) int save_round_mode __attribute__ ((unused)) = fegetround (); int result = 0; - for (size_t i = 0; i < sizeof (dec_tests) / sizeof (dec_tests[0]); i++) + for (size_t i = 0; i < array_length (dec_tests); i++) { result |= test_dec_in_one_mode (dec_tests[i].d, dec_tests[i].fmt, dec_tests[i].rn, "default rounding mode"); @@ -197,7 +198,7 @@ do_test (void) #endif } - for (size_t i = 0; i < sizeof (hex_tests) / sizeof (hex_tests[0]); i++) + for (size_t i = 0; i < array_length (hex_tests); i++) { result |= test_hex_in_one_mode (hex_tests[i].d, hex_tests[i].fmt, hex_tests[i].rn, "default rounding mode"); diff --git a/stdio-common/tst-sscanf.c b/stdio-common/tst-sscanf.c index c070e14cd7..9ccd86e7b0 100644 --- a/stdio-common/tst-sscanf.c +++ b/stdio-common/tst-sscanf.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -184,7 +185,7 @@ do_test (void) break; } - for (i = 0; i < sizeof (int_tests) / sizeof (int_tests[0]); ++i) + for (i = 0; i < array_length (int_tests); ++i) { long dummy; int ret; @@ -198,7 +199,7 @@ do_test (void) } } - for (i = 0; i < sizeof (double_tests) / sizeof (double_tests[0]); ++i) + for (i = 0; i < array_length (double_tests); ++i) { double dummy; int ret; @@ -212,7 +213,7 @@ do_test (void) } } - for (i = 0; i < sizeof (double_tests2) / sizeof (double_tests2[0]); ++i) + for (i = 0; i < array_length (double_tests2); ++i) { double dummy; int ret; diff --git a/stdio-common/tst-swprintf.c b/stdio-common/tst-swprintf.c index ce62c6bf68..07194eb67d 100644 --- a/stdio-common/tst-swprintf.c +++ b/stdio-common/tst-swprintf.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -16,7 +17,6 @@ static int do_test (void) { wchar_t buf[1000]; -#define nbuf (sizeof (buf) / sizeof (buf[0])) int result = 0; ssize_t n; @@ -27,7 +27,7 @@ do_test (void) } #define CHECK(fmt, nexp, exp) \ - n = swprintf (buf, nbuf, fmt, input); \ + n = swprintf (buf, array_length (buf), fmt, input); \ if (n != nexp) \ { \ printf ("swprintf (.., .., L\"%ls\", \"%ls\") return %d, not %d\n", \ diff --git a/stdio-common/tstdiomisc.c b/stdio-common/tstdiomisc.c index 89009e0549..c2fc73deb1 100644 --- a/stdio-common/tstdiomisc.c +++ b/stdio-common/tstdiomisc.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -66,8 +67,7 @@ t3 (void) retval = sprintf (buf, "%p", (char *) NULL); result |= retval != 5 || strcmp (buf, "(nil)") != 0; - retval = swprintf (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), - L"%p", (char *) NULL); + retval = swprintf (wbuf, array_length (wbuf), L"%p", (char *) NULL); result |= retval != 5 || wcscmp (wbuf, L"(nil)") != 0; return result; @@ -142,38 +142,38 @@ F (void) printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", buf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", qnanval, qnanval, qnanval, qnanval, qnanval, qnanval, qnanval, qnanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", -qnanval, -qnanval, -qnanval, -qnanval, -qnanval, -qnanval, -qnanval, -qnanval); result |= wcscmp (wbuf, L"-nan -NAN -nan -NAN -nan -NAN -nan -NAN") != 0; printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", snanval, snanval, snanval, snanval, snanval, snanval, snanval, snanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", msnanval, msnanval, msnanval, msnanval, msnanval, msnanval, msnanval, msnanval); result |= wcscmp (wbuf, L"-nan -NAN -nan -NAN -nan -NAN -nan -NAN") != 0; printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", infval, infval, infval, infval, infval, infval, infval, infval); result |= wcscmp (wbuf, L"inf INF inf INF inf INF inf INF") != 0; printf ("expected L\"inf INF inf INF inf INF inf INF\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), L"%a %A %e %E %f %F %g %G", + swprintf (wbuf, array_length (wbuf), L"%a %A %e %E %f %F %g %G", -infval, -infval, -infval, -infval, -infval, -infval, -infval, -infval); result |= wcscmp (wbuf, L"-inf -INF -inf -INF -inf -INF -inf -INF") != 0; @@ -223,14 +223,14 @@ F (void) printf ("expected \"-inf -INF -inf -INF -inf -INF -inf -INF\", got \"%s\"\n", buf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", lqnanval, lqnanval, lqnanval, lqnanval, lqnanval, lqnanval, lqnanval, lqnanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval, -lqnanval); @@ -238,14 +238,14 @@ F (void) printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", lsnanval, lsnanval, lsnanval, lsnanval, lsnanval, lsnanval, lsnanval, lsnanval); result |= wcscmp (wbuf, L"nan NAN nan NAN nan NAN nan NAN") != 0; printf ("expected L\"nan NAN nan NAN nan NAN nan NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval, lmsnanval); @@ -253,14 +253,14 @@ F (void) printf ("expected L\"-nan -NAN -nan -NAN -nan -NAN -nan -NAN\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", linfval, linfval, linfval, linfval, linfval, linfval, linfval, linfval); result |= wcscmp (wbuf, L"inf INF inf INF inf INF inf INF") != 0; printf ("expected L\"inf INF inf INF inf INF inf INF\", got L\"%S\"\n", wbuf); - swprintf (wbuf, sizeof wbuf / sizeof (wbuf[0]), + swprintf (wbuf, array_length (wbuf), L"%La %LA %Le %LE %Lf %LF %Lg %LG", -linfval, -linfval, -linfval, -linfval, -linfval, -linfval, -linfval, -linfval); diff --git a/stdio-common/tstscanf.c b/stdio-common/tstscanf.c index 50d0f33acf..d2ef4e8dee 100644 --- a/stdio-common/tstscanf.c +++ b/stdio-common/tstscanf.c @@ -15,6 +15,7 @@ License along with the GNU C Library; if not, see . */ +#include #ifdef BSD #include #else @@ -154,7 +155,7 @@ main (int argc, char **argv) { int count; - if (rounds++ >= sizeof (ok) / sizeof (ok[0])) + if (rounds++ >= array_length (ok)) { fputs ("test failed!\n", stdout); result = 1; diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 23d2679f39..e272237307 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -15,6 +15,7 @@ License along with the GNU C Library; if not, see . */ +#include #include #include #include @@ -995,11 +996,10 @@ static const uint8_t jump_table[] = if (string == NULL) \ { \ /* Write "(null)" if there's space. */ \ - if (prec == -1 \ - || prec >= (int) (sizeof (null) / sizeof (null[0])) - 1) \ + if (prec == -1 || prec >= (int) array_length (null) - 1) \ { \ string = (CHAR_T *) null; \ - len = (sizeof (null) / sizeof (null[0])) - 1; \ + len = array_length (null) - 1; \ } \ else \ { \