From patchwork Wed Sep 4 18:52:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Adhemerval Zanella X-Patchwork-Id: 1980978 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256 header.s=google header.b=Lx4gaBuo; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4WzWqR0gH2z1yg3 for ; Thu, 5 Sep 2024 04:53:55 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E7494385DDDA for ; Wed, 4 Sep 2024 18:53:52 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id 464B53861833 for ; Wed, 4 Sep 2024 18:52:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 464B53861833 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 464B53861833 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725475970; cv=none; b=PbUwwOITAC5CxzikbuIyGLuP6qJ7TwC0Jr9UWoD8uMsWaozKSHMRFd98/iZ4PoQidW/gP6leYTxK3u9Nir9LXFUF/b6cVJa223mDb+4EhOqUKde0+2/sNhSV9fyohISeSbRUc9ntk/Ex5BMlztu68o+IIS1Rzx4qqJGCxGMA+lA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725475970; c=relaxed/simple; bh=36f4j35njSaH1y+C7096mOMfU29tQMZRUHp67qmcnzA=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=vf95Rm6oKSvQHtZpveOCuB3q9YEsSYNBLCQLU+S+IVwcMRdwWZ85NZhA/u1gQILaCDGLD1OCYSfJHMbZj7Et26MtdVDJIfZslamP5tpWkUDayQAdRfZa74oZ9z0p7vFj4eSCE73fYugrJOiY7KITTr9QZ6oOrlYMtwYBnaNDAGI= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-717877183a2so425164b3a.1 for ; Wed, 04 Sep 2024 11:52:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1725475964; x=1726080764; darn=sourceware.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=jckVOkyQ4MNUTRtSqv7yeybmKdYtgBhqn+FykYoe1uA=; b=Lx4gaBuorRNzKHDaAyVqzNSJKEuxBJydqnAjSr6Y+spplhm+TruVbIDJyJ2KTYvsZx D/t//Ty6JOT/nyuqfF3DsP9ikR3uP8ARqab/yGt71pzHp1ogNXiGFVG4w99HDo5mvjQg D9BvZtlWVlt5NPPU1zbvwaKPlMjzsdLm5ooiAO1pBwIhbQTs7AvJy5SQEivKuEHKSR4K Nfo//ux/rNret5xYWfryijx2e7JuXIVMFqb+U+V6Ufkf0JRI6cAZLwM+tL6xOTqTohuH W3EcwzBJD7IXtQybxYlgKGvOY/1FiEjbIO+6InjrUMgaUBbQ0DvojELdS7dVUPvcoE/+ tnWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725475964; x=1726080764; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=jckVOkyQ4MNUTRtSqv7yeybmKdYtgBhqn+FykYoe1uA=; b=cQnxTg92WfwCWp4DnUtScZ2JsF/73BBLoQ7vWDkAl1YoVWbWzCpDAX1ngUn9vWp7oB BkycKgoqmR8xgd+vsmUjqdsvFvpBFfjEw+1Vwt2BTZxGOp8hSjpSlL4hds1OEDbDcFKn ELjUG1V2DOuBNiSvHLABvLSC0wZPydvSLrRzMqDl7BSfqMFqDlyFWb5b2UdN6C5DchQi bl18HJqbcCx98B5UAVCJsPiDe8KAXkXLhLlNIijUozxOYNUKGX/kkX/IGuKOl8GsuoVs 9xYS594kLTd0uWL3uY9xxF1DTCFzXAj4RVPNDkdw1SbWBLque6Txq0+Bx1xQHNSx0YUD ZvqA== X-Gm-Message-State: AOJu0YwLN96IhiKNAOcHF15costHPyPh6XDpsd1aDh/8/fVgEssTYwX2 Q1tOBwmV0jIE0Wci/5gvQRqo+jEnJs1SNeQcokml0FUGGd5ErkDd14wV9yxhMGr00wCyjkIANdI G21U= X-Google-Smtp-Source: AGHT+IHZnUuwgQwV/YqezDv1JISBz1lYogsiwyFzx+YEjebC9FBWwrkYdtwx+Wz31YZUIOtIS91mGw== X-Received: by 2002:a05:6a20:9d92:b0:1cc:eafb:ddfb with SMTP id adf61e73a8af0-1cecdf2e0b9mr17444718637.26.1725475963021; Wed, 04 Sep 2024 11:52:43 -0700 (PDT) Received: from mandiga.. ([2804:1b3:a7c3:e912:1301:81fd:2901:4eab]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-2d85b3b95cesm13856460a91.53.2024.09.04.11.52.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 11:52:42 -0700 (PDT) From: Adhemerval Zanella To: libc-alpha@sourceware.org Cc: Joseph Myers , Paul Eggert Subject: [PATCH v2] timezone: sync to TZDB main Date: Wed, 4 Sep 2024 15:52:21 -0300 Message-ID: <20240904185238.3432520-1-adhemerval.zanella@linaro.org> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org Sync tzselect, zdump, zic to TZDB main commit 812aff32. This patch incorporates the following TZDB source code changes: 812aff32 Improve historical transitions in Mexico 1921-1997 52662566 Adjust to mailing list software change 7748036b Mention Internet RFC 9557 339e81d1 Mention Levine’s proposal to replace leap seconds b4e6ad2d No leap second on 2024-12-31 7eb5bf88 Asia/Choibalsan is now an alias for Asia/Ulaanbaatar 43450cbf Improve historical data for Portugal and former possessions. 13d7348b Typo and validation fixes. 3c39cde8 Fix typo for “removed” in a comment 03fd9e45 More documentation updates for POSIX.1-2024 eb3bcceb POSIX.1-2014 is now published 913b0410 tzselect: support POSIX.1-2024 offset range b5318b55 Document POSIX.1-2024 better 837609b7 Fix typo when making .txt man pages d56ae6ee SUPPORT_C89 now defaults to 1, not 0 b1fe113d Port ! to Solaris make 8f1fd321 Avoid crash in Solaris 10 /usr/xpg4/bin/make e0fcfdd6 Use ‘export VAR=VAL’ syntax eba43166 Avoid an awk invocation via $'...' 36479a80 Avoid some subshells in tzselect 7f6cf054 * tzselect.ksh: Assume POSIX.2 awk. a1cf1daf * tzselect.ksh: Assume POSIX.2 $PWD. a9b8e536 Assume POSIX.2 command substitution eaa4ef16 Avoid subshells when possible 9dac9eb7 Prefer $PWD to $(pwd) in Makefile fada6a4c Prefer $(CMD) to `CMD` in Makefile 3e871b9a Assume POSIX.2 and eschew ‘expr’ c5d67805 difftime isn’t pure either 5857c056 * CONTRIBUTING: Document build assumptions. 6822cc82 ‘make check’ no longer depends on curl+Internet cc6eb255 Document GCC bug 114833 and workaround bcbc86bf Scale back on function attribute use c0789e46 C23 [[reproducible]] and [[unsequenced]] fixups bbd88154 More updates to GCC_DEBUG_FLAGS for GCC 14 1a35b7c8 Spelling fixes f71085f2 POSIX.1-2024 removes asctime_r, ctime_r 70856f8e Adjust to refactored location of ctime, ctime_r aacd151d Update GCC_DEBUG_FLAGS for GCC 14 967dcf3b Sub-second history for Maputo and Zurich 782d0826 Make EET, MET and WET links a0b09c02 Mark CET, CST6CDT etc. as obsolescent db7fb40d Document SMPTE timecodes and rolling leaps 97232e18 Don’t be so sure about leap seconds going away 5b6a74fb Update some URLs a75a6251 * zic.8: Tweak for consistency. 1e75b31f Document what %s means before any rule applies 00c96cbb Conform to RFC 8536 section 3.2 for default type 3e944959 Document problems with stripped-down TZif readers 20fc91cf Shanks is likely wrong about Maputo switch to CAT d99589b6 * zic.8: Add missing tab character. 94e6b3b0 Switch to %z in main dataform 2cd57b93 Treat W-Eur like Port when reguarding ad6f6d94 Check that main.zi agrees with sources a43b030f .gitignore: Add .pdf, .ps, .s. Remove obsolete ‘yearistype’. 253ca020 * theory.html: ‘CLT’ → ‘LTC’ (per Michael H Deckers) a3dee8c8 * NEWS: ‘how’ → ‘now’ (thanks to Paul Goyette). ea6341c5 * theory.html: Mention NASA and CLT (per Arthur David Olson). 0dcebe37 America/Scoresbysund matches America/Nuuk from now on b1e07fb0 Update Vzic link (thanks to Allen Winter) a4b05030 Fix wday/mday typo in previous patch 732a4803 Document how to detect mktime failure reliably a64067e9 ziguard.awk: generalize for proposed Portugal patch 59c861fd Line up zdump examples 66c106c9 tzfile.5: srcfix e5553001 Fix .RS/.RE problem in tzfile.5 d647eb01 Add Doctorow book 59d4a1ba Asia/Almaty matches Asia/Tashkent from now on d4d3c3ba * asia: Update Philippine URLs (thanks to Guy Harris). 9fc11a27 Port unlikely overflow check to C23 b52a2969 Fix 2023d NEWS typo e48c5b53 Cite "The NTP Leap Second File" b1dc2122 Update Israel tz-link 6cf4e912 Extrapolate less from the 2022 CGPM resolution. It fixes glibc build with gcc master [1]. Checked on x86_64-linux-gnu and on i686-linux-gnu. [1] https://sourceware.org/pipermail/libc-alpha/2024-September/159571.html --- SHARED-FILES | 6 +- timezone/private.h | 114 +++++++++++++++++++++++--------------- timezone/tzfile.h | 8 ++- timezone/tzselect.ksh | 125 +++++++++++++++++++----------------------- timezone/zdump.c | 10 ++-- timezone/zic.c | 31 +++++------ 6 files changed, 152 insertions(+), 142 deletions(-) diff --git a/SHARED-FILES b/SHARED-FILES index cb0356ce32..30e2e56495 100644 --- a/SHARED-FILES +++ b/SHARED-FILES @@ -180,9 +180,9 @@ unicode: # The following files are shared with the upstream tzcode project and must be # updated regularly to stay in sync with the upstream releases. # -# Currently synced to TZDB 2024a, announced and distributed here: -# https://mm.icann.org/pipermail/tz-announce/2024-February/000081.html -# https://data.iana.org/time-zones/releases/tzdb-2024a.tar.lz +# Currently synced to TZDB main commit 812aff32b32c02266361d5538351e0db2a1aee5b +# provided by: +# https://github.com/eggert/tz tzcode: timezone/private.h timezone/tzfile.h diff --git a/timezone/private.h b/timezone/private.h index 0dac6af4e3..c33041049f 100644 --- a/timezone/private.h +++ b/timezone/private.h @@ -19,19 +19,22 @@ /* PORT_TO_C89 means the code should work even if the underlying compiler and library support only C89 plus C99's 'long long' - and perhaps a few other extensions to C89. SUPPORT_C89 means the - tzcode library should support C89 callers in addition to the usual - support for C99-and-later callers; however, C89 support can trigger - latent bugs in C99-and-later callers. These macros are obsolescent, - and the plan is to remove them along with any code needed only when - they are nonzero. A good time to do that might be in the year 2029 + and perhaps a few other extensions to C89. + + This macro is obsolescent, and the plan is to remove it along with + associated code. A good time to do that might be in the year 2029 because RHEL 7 (whose GCC defaults to C89) extended life cycle support (ELS) is scheduled to end on 2028-06-30. */ #ifndef PORT_TO_C89 # define PORT_TO_C89 0 #endif + +/* SUPPORT_C89 means the tzcode library should support C89 callers + in addition to the usual support for C99-and-later callers. + This defaults to 1 as POSIX requires, even though that can trigger + latent bugs in callers. */ #ifndef SUPPORT_C89 -# define SUPPORT_C89 0 +# define SUPPORT_C89 1 #endif #ifndef __STDC_VERSION__ @@ -69,10 +72,6 @@ ** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'. */ -#ifndef HAVE_DECL_ASCTIME_R -# define HAVE_DECL_ASCTIME_R 1 -#endif - #if !defined HAVE__GENERIC && defined __has_extension # if !__has_extension(c_generic_selections) # define HAVE__GENERIC 0 @@ -236,6 +235,31 @@ # include /* for R_OK, and other POSIX goodness */ #endif /* HAVE_UNISTD_H */ +/* SUPPORT_POSIX2008 means the tzcode library should support + POSIX.1-2017-and-earlier callers in addition to the usual support for + POSIX.1-2024-and-later callers; however, this can be + incompatible with POSIX.1-2024-and-later callers. + This macro is obsolescent, and the plan is to remove it + along with any code needed only when it is nonzero. + A good time to do that might be in the year 2034. + This macro's name is SUPPORT_POSIX2008 because _POSIX_VERSION == 200809 + in POSIX.1-2017, a minor revision of POSIX.1-2008. */ +#ifndef SUPPORT_POSIX2008 +# if defined _POSIX_VERSION && _POSIX_VERSION <= 200809 +# define SUPPORT_POSIX2008 1 +# else +# define SUPPORT_POSIX2008 0 +# endif +#endif + +#ifndef HAVE_DECL_ASCTIME_R +# if SUPPORT_POSIX2008 +# define HAVE_DECL_ASCTIME_R 1 +# else +# define HAVE_DECL_ASCTIME_R 0 +# endif +#endif + #ifndef HAVE_STRFTIME_L # if _POSIX_VERSION < 200809 # define HAVE_STRFTIME_L 0 @@ -460,14 +484,6 @@ typedef unsigned long uintmax_t; # define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r) #endif -#if 3 <= __GNUC__ -# define ATTRIBUTE_MALLOC __attribute__((malloc)) -# define ATTRIBUTE_FORMAT(spec) __attribute__((format spec)) -#else -# define ATTRIBUTE_MALLOC /* empty */ -# define ATTRIBUTE_FORMAT(spec) /* empty */ -#endif - #if (defined __has_c_attribute \ && (202311 <= __STDC_VERSION__ || !defined __STRICT_ANSI__)) # define HAVE___HAS_C_ATTRIBUTE true @@ -535,24 +551,27 @@ typedef unsigned long uintmax_t; # endif #endif #ifndef ATTRIBUTE_REPRODUCIBLE -# if 3 <= __GNUC__ -# define ATTRIBUTE_REPRODUCIBLE __attribute__((pure)) -# else -# define ATTRIBUTE_REPRODUCIBLE /* empty */ -# endif +# define ATTRIBUTE_REPRODUCIBLE /* empty */ #endif -#if HAVE___HAS_C_ATTRIBUTE -# if __has_c_attribute(unsequenced) -# define ATTRIBUTE_UNSEQUENCED [[unsequenced]] -# endif +/* GCC attributes that are useful in tzcode. + __attribute__((pure)) is stricter than [[reproducible]], + so the latter is an adequate substitute in non-GCC C23 platforms. */ +#if __GNUC__ < 3 +# define ATTRIBUTE_FORMAT(spec) /* empty */ +# define ATTRIBUTE_PURE ATTRIBUTE_REPRODUCIBLE +#else +# define ATTRIBUTE_FORMAT(spec) __attribute__((format spec)) +# define ATTRIBUTE_PURE __attribute__((pure)) #endif -#ifndef ATTRIBUTE_UNSEQUENCED -# if 3 <= __GNUC__ -# define ATTRIBUTE_UNSEQUENCED __attribute__((const)) -# else -# define ATTRIBUTE_UNSEQUENCED /* empty */ -# endif + +/* Avoid GCC bug 114833 . + Remove this macro and its uses when the bug is fixed in a GCC release, + because only the latest GCC matters for $(GCC_DEBUG_FLAGS). */ +#ifdef GCC_LINT +# define ATTRIBUTE_PURE_114833 ATTRIBUTE_PURE +#else +# define ATTRIBUTE_PURE_114833 /* empty */ #endif #if (__STDC_VERSION__ < 199901 && !defined restrict \ @@ -604,12 +623,8 @@ typedef time_tz tz_time_t; # undef asctime # define asctime tz_asctime -# undef asctime_r -# define asctime_r tz_asctime_r # undef ctime # define ctime tz_ctime -# undef ctime_r -# define ctime_r tz_ctime_r # undef difftime # define difftime tz_difftime # undef gmtime @@ -654,6 +669,12 @@ typedef time_tz tz_time_t; # define tzfree tz_tzfree # undef tzset # define tzset tz_tzset +# if SUPPORT_POSIX2008 +# undef asctime_r +# define asctime_r tz_asctime_r +# undef ctime_r +# define ctime_r tz_ctime_r +# endif # if HAVE_STRFTIME_L # undef strftime_l # define strftime_l tz_strftime_l @@ -679,10 +700,12 @@ typedef time_tz tz_time_t; # define DEPRECATED_IN_C23 ATTRIBUTE_DEPRECATED # endif DEPRECATED_IN_C23 char *asctime(struct tm const *); -char *asctime_r(struct tm const *restrict, char *restrict); DEPRECATED_IN_C23 char *ctime(time_t const *); +#if SUPPORT_POSIX2008 +char *asctime_r(struct tm const *restrict, char *restrict); char *ctime_r(time_t const *, char *); -ATTRIBUTE_UNSEQUENCED double difftime(time_t, time_t); +#endif +double difftime(time_t, time_t); size_t strftime(char *restrict, size_t, char const *restrict, struct tm const *restrict); # if HAVE_STRFTIME_L @@ -713,7 +736,7 @@ void tzset(void); time_t timegm(struct tm *); #endif -#if !HAVE_DECL_ASCTIME_R && !defined asctime_r +#if !HAVE_DECL_ASCTIME_R && !defined asctime_r && SUPPORT_POSIX2008 extern char *asctime_r(struct tm const *restrict, char *restrict); #endif @@ -798,10 +821,10 @@ timezone_t tzalloc(char const *); void tzfree(timezone_t); # if STD_INSPIRED # if TZ_TIME_T || !defined posix2time_z -ATTRIBUTE_REPRODUCIBLE time_t posix2time_z(timezone_t, time_t); +ATTRIBUTE_PURE time_t posix2time_z(timezone_t, time_t); # endif # if TZ_TIME_T || !defined time2posix_z -ATTRIBUTE_REPRODUCIBLE time_t time2posix_z(timezone_t, time_t); +ATTRIBUTE_PURE time_t time2posix_z(timezone_t, time_t); # endif # endif #endif @@ -973,8 +996,9 @@ enum { /* How many years to generate (in zic.c) or search through (in localtime.c). This is two years larger than the obvious 400, to avoid edge cases. - E.g., suppose a non-POSIX.1-2017 rule applies from 2012 on with transitions - in March and September, plus one-off transitions in November 2013. + E.g., suppose a rule applies from 2012 on with transitions + in March and September, plus one-off transitions in November 2013, + and suppose the rule cannot be expressed as a proleptic TZ string. If zic looked only at the last 400 years, it would set max_year=2413, with the intent that the 400 years 2014 through 2413 will be repeated. The last transition listed in the tzfile would be in 2413-09, diff --git a/timezone/tzfile.h b/timezone/tzfile.h index 3155010ed1..b154146654 100644 --- a/timezone/tzfile.h +++ b/timezone/tzfile.h @@ -76,14 +76,16 @@ struct tzhead { ** If tzh_version is '2' or greater, the above is followed by a second instance ** of tzhead and a second instance of the data in which each coded transition ** time uses 8 rather than 4 chars, -** then a POSIX-TZ-environment-variable-style string for use in handling +** then a POSIX.1-2017 proleptic TZ string for use in handling ** instants after the last transition time stored in the file ** (with nothing between the newlines if there is no POSIX.1-2017 ** representation for such instants). ** -** If tz_version is '3' or greater, the above is extended as follows. +** If tz_version is '3' or greater, the TZ string can be any POSIX.1-2024 +** proleptic TZ string, which means the above is extended as follows. ** First, the TZ string's hour offset may range from -167 -** through 167 as compared to the POSIX-required 0 through 24. +** through 167 as compared to the range 0 through 24 required +** by POSIX.1-2017 and earlier. ** Second, its DST start time may be January 1 at 00:00 and its stop ** time December 31 at 24:00 plus the difference between DST and ** standard time, indicating DST all year. diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh index 38941bbc55..ca3d82c6aa 100755 --- a/timezone/tzselect.ksh +++ b/timezone/tzselect.ksh @@ -20,12 +20,6 @@ REPORT_BUGS_TO=tz@iana.org # Korn Shell # MirBSD Korn Shell # -# For portability to Solaris 10 /bin/sh (supported by Oracle through -# January 2027) this script avoids some POSIX features and common -# extensions, such as $(...), $((...)), ! CMD, unquoted ^, ${#ID}, -# ${ID##PAT}, ${ID%%PAT}, and $10. Although some of these constructs -# work sometimes, it's simpler to avoid them entirely. -# # This script also uses several features of POSIX awk. # If your host lacks awk, or has an old awk that does not conform to POSIX, # you can use any of the following free programs instead: @@ -45,7 +39,6 @@ set -f # Specify default values for environment variables if they are unset. : ${AWK=awk} -: ${PWD=`pwd`} : ${TZDIR=$PWD} # Output one argument as-is to standard output, with trailing newline. @@ -54,13 +47,6 @@ say() { printf '%s\n' "$1" } -# Check for awk POSIX compliance. -($AWK -v x=y 'BEGIN { exit 123 }') <>/dev/null >&0 2>&0 -[ $? = 123 ] || { - say >&2 "$0: Sorry, your '$AWK' program is not POSIX compatible." - exit 1 -} - coord= location_limit=10 zonetabtype=zone1970 @@ -117,8 +103,7 @@ then else doselect() { # Field width of the prompt numbers. - print_nargs_length="BEGIN {print length(\"$#\");}" - select_width=`$AWK "$print_nargs_length"` + select_width=${##} select_i= @@ -129,14 +114,14 @@ else select_i=0 for select_word do - select_i=`$AWK "BEGIN { print $select_i + 1 }"` + select_i=$(($select_i + 1)) printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word" done;; *[!0-9]*) echo >&2 'Please enter a number in range.';; *) if test 1 -le $select_i && test $select_i -le $#; then - shift `$AWK "BEGIN { print $select_i - 1 }"` + shift $(($select_i - 1)) select_result=$1 break fi @@ -170,7 +155,7 @@ do esac done -shift `$AWK "BEGIN { print $OPTIND - 1 }"` +shift $(($OPTIND - 1)) case $# in 0) ;; *) say >&2 "$0: $1: unknown argument"; exit 1 @@ -178,11 +163,13 @@ esac # translit=true to try transliteration. # This is false if U+12345 CUNEIFORM SIGN URU TIMES KI has length 1 -# which means awk (and presumably the shell) do not need transliteration. -if $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) == 1 }'; then - translit=true -else - translit=false +# which means the shell and (presumably) awk do not need transliteration. +# It is true if the byte string has some other length in characters, or +# if this is a POSIX.1-2017 or earlier shell that does not support $'...'. +CUNEIFORM_SIGN_URU_TIMES_KI=$'\360\222\215\205' +if test ${#CUNEIFORM_SIGN_URU_TIMES_KI} = 1 +then translit=false +else translit=true fi # Read into shell variable $1 the contents of file $2. @@ -192,10 +179,10 @@ fi # if that does not work, fall back on 'cat'. read_file() { { $translit && { - eval "$1=\`(iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\"\`" || - eval "$1=\`(iconv -f UTF-8) 2>/dev/null <\"\$2\"\`" + eval "$1=\$( (iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\")" || + eval "$1=\$( (iconv -f UTF-8) 2>/dev/null <\"\$2\")" }; } || - eval "$1=\`cat <\"\$2\"\`" || { + eval "$1=\$(cat <\"\$2\")" || { say >&2 "$0: time zone files are not set up correctly" exit 1 } @@ -403,7 +390,7 @@ while echo >&2 \ 'Please select a continent, ocean, "coord", "TZ", "time", or "now".' - quoted_continents=` + quoted_continents=$( $AWK ' function handle_entry(entry) { entry = substr(entry, 1, index(entry, "/") - 1) @@ -433,12 +420,12 @@ while sort -u | tr '\n' ' ' echo '' - ` + ) eval ' doselect '"$quoted_continents"' \ "coord - I want to use geographical coordinates." \ - "TZ - I want to specify the timezone using a POSIX.1-2017 TZ string." \ + "TZ - I want to specify the timezone using a proleptic TZ string." \ "time - I know local time already." \ "now - Like \"time\", but configure only for timestamps from now on." continent=$select_result @@ -462,16 +449,17 @@ while case $continent in TZ) - # Ask the user for a POSIX.1-2017 TZ string. Check that it conforms. + # Ask the user for a proleptic TZ string. Check that it conforms. check_POSIX_TZ_string=' BEGIN { tz = substr(ARGV[1], 2) ARGV[1] = "" tzname = ("(<[[:alnum:]+-][[:alnum:]+-][[:alnum:]+-]+>" \ "|[[:alpha:]][[:alpha:]][[:alpha:]]+)") - time = ("(2[0-4]|[0-1]?[0-9])" \ - "(:[0-5][0-9](:[0-5][0-9])?)?") - offset = "[-+]?" time + sign = "[-+]?" + hhmm = "(:[0-5][0-9](:[0-5][0-9])?)?" + offset = sign "(2[0-4]|[0-1]?[0-9])" hhmm + time = sign "(16[0-7]|(1[0-5]|[0-9]?)[0-9])" hhmm mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]" jdate = ("((J[1-9]|[0-9]|J?[1-9][0-9]" \ "|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])") @@ -492,7 +480,7 @@ while read tz $AWK "$check_POSIX_TZ_string" ="$tz" do - say >&2 "'$tz' is not a conforming POSIX.1-2017 timezone string." + say >&2 "'$tz' is not a conforming POSIX proleptic TZ string." done TZ_for_date=$tz;; *) @@ -507,14 +495,14 @@ while '74 degrees 3 minutes west.' read coord esac - distance_table=` + distance_table=$( $AWK \ "$output_distances_or_times" \ ="$coord" ="$TZ_COUNTRY_TABLE" ="$TZ_ZONE_TABLE" | sort -n | $AWK "{print} NR == $location_limit { exit }" - ` - regions=` + ) + regions=$( $AWK ' BEGIN { distance_table = substr(ARGV[1], 2) @@ -526,13 +514,13 @@ while } } ' ="$distance_table" - ` + ) echo >&2 'Please select one of the following timezones,' echo >&2 'listed roughly in increasing order' \ "of distance from $coord". doselect $regions region=$select_result - tz=` + tz=$( $AWK ' BEGIN { distance_table = substr(ARGV[1], 2) @@ -546,22 +534,22 @@ while } } ' ="$distance_table" ="$region" - `;; + );; *) case $continent in now|time) minute_format='%a %b %d %H:%M' - old_minute=`TZ=UTC0 date +"$minute_format"` + old_minute=$(TZ=UTC0 date +"$minute_format") for i in 1 2 3 do - time_table_command=` + time_table_command=$( $AWK \ -v output_times=1 \ "$output_distances_or_times" \ = = ="$TZ_ZONE_TABLE" - ` - time_table=`eval "$time_table_command"` - new_minute=`TZ=UTC0 date +"$minute_format"` + ) + time_table=$(eval "$time_table_command") + new_minute=$(TZ=UTC0 date +"$minute_format") case $old_minute in "$new_minute") break esac @@ -569,11 +557,11 @@ while done echo >&2 "The system says Universal Time is $new_minute." echo >&2 "Assuming that's correct, what is the local time?" - sorted_table=`say "$time_table" | sort -k2n -k2,5 -k1n` || { + sorted_table=$(say "$time_table" | sort -k2n -k2,5 -k1n) || { say >&2 "$0: cannot sort time table" exit 1 } - eval doselect ` + eval doselect $( $AWK ' BEGIN { sorted_table = substr(ARGV[1], 2) @@ -590,10 +578,10 @@ while } } ' ="$sorted_table" - ` + ) time=$select_result continent_re='^' - zone_table=` + zone_table=$( $AWK ' BEGIN { time = substr(ARGV[1], 2) @@ -609,13 +597,13 @@ while } } ' ="$time" ="$time_table" - ` - countries=` + ) + countries=$( $AWK \ "$output_country_list" \ ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" | sort -f - ` + ) ;; *) continent_re="^$continent/" @@ -623,16 +611,16 @@ while esac # Get list of names of countries in the continent or ocean. - countries=` + countries=$( $AWK \ "$output_country_list" \ ="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" | sort -f - ` + ) # If all zone table entries have comments, and there are # at most 22 entries, asked based on those comments. # This fits the prompt onto old-fashioned 24-line screens. - regions=` + regions=$( $AWK ' BEGIN { TZ_ZONE_TABLE = substr(ARGV[1], 2) @@ -653,7 +641,7 @@ while print comment[i] } ' ="$zone_table" - ` + ) # If there's more than one country, ask the user which one. case $countries in @@ -669,7 +657,7 @@ while # Get list of timezones in the country. - regions=` + regions=$( $AWK ' BEGIN { country = substr(ARGV[1], 2) @@ -696,7 +684,7 @@ while } } ' ="$country" ="$TZ_COUNTRY_TABLE" ="$zone_table" - ` + ) # If there's more than one region, ask the user which one. case $regions in @@ -707,7 +695,7 @@ while esac # Determine tz from country and region. - tz=` + tz=$( $AWK ' BEGIN { country = substr(ARGV[1], 2) @@ -735,7 +723,7 @@ while } } ' ="$country" ="$region" ="$TZ_COUNTRY_TABLE" ="$zone_table" - ` + ) esac # Make sure the corresponding zoneinfo file exists. @@ -754,14 +742,11 @@ while extra_info= for i in 1 2 3 4 5 6 7 8 do - TZdate=`LANG=C TZ="$TZ_for_date" date` - UTdate=`LANG=C TZ=UTC0 date` - if $AWK ' - function getsecs(d) { - return match(d, /.*:[0-5][0-9]/) ? substr(d, RLENGTH - 1, 2) : "" - } - BEGIN { exit getsecs(ARGV[1]) != getsecs(ARGV[2]) } - ' ="$TZdate" ="$UTdate" + TZdate=$(LANG=C TZ="$TZ_for_date" date) + UTdate=$(LANG=C TZ=UTC0 date) + TZsecsetc=${TZdate##*[0-5][0-9]:} + UTsecsetc=${UTdate##*[0-5][0-9]:} + if test "${TZsecsetc%%[!0-9]*}" = "${UTsecsetc%%[!0-9]*}" then extra_info=" Selected time is now: $TZdate. @@ -801,7 +786,7 @@ done case $SHELL in *csh) file=.login line="setenv TZ '$tz'";; -*) file=.profile line="TZ='$tz'; export TZ" +*) file=.profile line="export TZ='$tz'" esac test -t 1 && say >&2 " diff --git a/timezone/zdump.c b/timezone/zdump.c index 7d99cc74bd..e817873337 100644 --- a/timezone/zdump.c +++ b/timezone/zdump.c @@ -89,7 +89,7 @@ static bool warned; static bool errout; static char const *abbr(struct tm const *); -ATTRIBUTE_REPRODUCIBLE static intmax_t delta(struct tm *, struct tm *); +static intmax_t delta(struct tm *, struct tm *); static void dumptime(struct tm const *); static time_t hunt(timezone_t, time_t, time_t, bool); static void show(timezone_t, char *, time_t, bool); @@ -97,7 +97,7 @@ static void showextrema(timezone_t, char *, time_t, struct tm *, time_t); static void showtrans(char const *, struct tm const *, time_t, char const *, char const *); static const char *tformat(void); -ATTRIBUTE_REPRODUCIBLE static time_t yeartot(intmax_t); +ATTRIBUTE_PURE_114833 static time_t yeartot(intmax_t); /* Is C an ASCII digit? */ static bool @@ -134,7 +134,7 @@ size_overflow(void) /* Return A + B, exiting if the result would overflow either ptrdiff_t or size_t. A and B are both nonnegative. */ -ATTRIBUTE_REPRODUCIBLE static ptrdiff_t +ATTRIBUTE_PURE_114833 static ptrdiff_t sumsize(ptrdiff_t a, ptrdiff_t b) { #ifdef ckd_add @@ -162,7 +162,7 @@ xstrsize(char const *str) /* Return a pointer to a newly allocated buffer of size SIZE, exiting on failure. SIZE should be positive. */ -ATTRIBUTE_MALLOC static void * +static void * xmalloc(ptrdiff_t size) { void *p = malloc(size); @@ -932,7 +932,7 @@ showextrema(timezone_t tz, char *zone, time_t lo, struct tm *lotmp, time_t hi) # include /* A substitute for snprintf that is good enough for zdump. */ -ATTRIBUTE_FORMAT((printf, 3, 4)) static int +static int my_snprintf(char *s, size_t size, char const *format, ...) { int n; diff --git a/timezone/zic.c b/timezone/zic.c index 00f00e307a..cf8e79dff4 100644 --- a/timezone/zic.c +++ b/timezone/zic.c @@ -470,7 +470,7 @@ size_overflow(void) memory_exhausted(_("size overflow")); } -ATTRIBUTE_REPRODUCIBLE static ptrdiff_t +ATTRIBUTE_PURE_114833 static ptrdiff_t size_sum(size_t a, size_t b) { #ifdef ckd_add @@ -484,7 +484,7 @@ size_sum(size_t a, size_t b) size_overflow(); } -ATTRIBUTE_REPRODUCIBLE static ptrdiff_t +ATTRIBUTE_PURE_114833 static ptrdiff_t size_product(ptrdiff_t nitems, ptrdiff_t itemsize) { #ifdef ckd_mul @@ -499,7 +499,7 @@ size_product(ptrdiff_t nitems, ptrdiff_t itemsize) size_overflow(); } -ATTRIBUTE_REPRODUCIBLE static ptrdiff_t +ATTRIBUTE_PURE_114833 static ptrdiff_t align_to(ptrdiff_t size, ptrdiff_t alignment) { ptrdiff_t lo_bits = alignment - 1, sum = size_sum(size, lo_bits); @@ -523,7 +523,7 @@ memcheck(void *ptr) return ptr; } -ATTRIBUTE_MALLOC static void * +static void * emalloc(size_t size) { return memcheck(malloc(size)); @@ -535,7 +535,7 @@ erealloc(void *ptr, size_t size) return memcheck(realloc(ptr, size)); } -ATTRIBUTE_MALLOC static char * +static char * estrdup(char const *str) { return memcheck(strdup(str)); @@ -1435,7 +1435,7 @@ relname(char const *target, char const *linkname) /* Return true if A and B must have the same parent dir if A and B exist. Return false if this is not necessarily true (though it might be true). Keep it simple, and do not inspect the file system. */ -static bool +ATTRIBUTE_PURE_114833 static bool same_parent_dirs(char const *a, char const *b) { for (; *a == *b; a++, b++) @@ -2982,10 +2982,10 @@ rule_cmp(struct rule const *a, struct rule const *b) return a->r_dayofmonth - b->r_dayofmonth; } -/* Store into RESULT a POSIX.1-2017 TZ string that represent the future +/* Store into RESULT a proleptic TZ string that represent the future predictions for the zone ZPFIRST with ZONECOUNT entries. Return a compatibility indicator (a TZDB release year) if successful, a - negative integer if no such TZ string exissts. */ + negative integer if no such TZ string exists. */ static int stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount) { @@ -3177,8 +3177,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) if (noise) { if (!*envvar) warning("%s %s", - _("no POSIX.1-2017 environment variable" - " for zone"), + _("no proleptic TZ string for zone"), zpfirst->z_name); else if (compat != 0) { /* Circa-COMPAT clients, and earlier clients, might @@ -3442,7 +3441,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount) if (do_extend) { /* ** If we're extending the explicitly listed observations for - ** 400 years because we can't fill the POSIX.1-2017 TZ field, + ** 400 years because we can't fill the proleptic TZ field, ** check whether we actually ended up explicitly listing ** observations through that period. If there aren't any ** near the end of the 400-year period, add a redundant @@ -3627,7 +3626,7 @@ lowerit(char a) } /* case-insensitive equality */ -ATTRIBUTE_REPRODUCIBLE static bool +ATTRIBUTE_PURE_114833 static bool ciequal(register const char *ap, register const char *bp) { while (lowerit(*ap) == lowerit(*bp++)) @@ -3636,7 +3635,7 @@ ciequal(register const char *ap, register const char *bp) return false; } -ATTRIBUTE_REPRODUCIBLE static bool +ATTRIBUTE_PURE_114833 static bool itsabbr(register const char *abbr, register const char *word) { if (lowerit(*abbr) != lowerit(*word)) @@ -3652,7 +3651,7 @@ itsabbr(register const char *abbr, register const char *word) /* Return true if ABBR is an initial prefix of WORD, ignoring ASCII case. */ -ATTRIBUTE_REPRODUCIBLE static bool +ATTRIBUTE_PURE_114833 static bool ciprefix(char const *abbr, char const *word) { do @@ -3762,7 +3761,7 @@ time_overflow(void) exit(EXIT_FAILURE); } -ATTRIBUTE_REPRODUCIBLE static zic_t +ATTRIBUTE_PURE_114833 static zic_t oadd(zic_t t1, zic_t t2) { #ifdef ckd_add @@ -3776,7 +3775,7 @@ oadd(zic_t t1, zic_t t2) time_overflow(); } -ATTRIBUTE_REPRODUCIBLE static zic_t +ATTRIBUTE_PURE_114833 static zic_t tadd(zic_t t1, zic_t t2) { #ifdef ckd_add