From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-3.4 required=3.0 tests=AWL,BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_PASS shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id 05E901F9FD for ; Mon, 1 Mar 2021 08:29:39 +0000 (UTC) Received: from localhost ([::1]:37462 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lGdvu-0007GV-46 for normalperson@yhbt.net; Mon, 01 Mar 2021 03:29:38 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:44032) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lGdvq-0007GM-VX for bug-gnulib@gnu.org; Mon, 01 Mar 2021 03:29:34 -0500 Received: from zimbra.cs.ucla.edu ([131.179.128.68]:35930) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lGdvo-0001Qc-6l for bug-gnulib@gnu.org; Mon, 01 Mar 2021 03:29:34 -0500 Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 61F76160137 for ; Mon, 1 Mar 2021 00:29:29 -0800 (PST) Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id VUgaf2g8B5zA; Mon, 1 Mar 2021 00:29:27 -0800 (PST) Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 7869A160119; Mon, 1 Mar 2021 00:29:27 -0800 (PST) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id UOe3oyFnpTfM; Mon, 1 Mar 2021 00:29:27 -0800 (PST) Received: from penguin.CS.UCLA.EDU (Penguin.CS.UCLA.EDU [131.179.64.200]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 46169160103; Mon, 1 Mar 2021 00:29:27 -0800 (PST) From: Paul Eggert To: bug-gnulib@gnu.org Subject: [PATCH 1/2] parse-datetime2: new module Date: Mon, 1 Mar 2021 00:29:21 -0800 Message-Id: <20210301082922.1121342-1-eggert@cs.ucla.edu> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass client-ip=131.179.128.68; envelope-from=eggert@cs.ucla.edu; helo=zimbra.cs.ucla.edu X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paul Eggert Errors-To: bug-gnulib-bounces+normalperson=yhbt.net@gnu.org Sender: "bug-gnulib" This splits the old parse-datetime into two parts; the first is parse-datetime2 which supports all the new bells and whistles, the second is parse-datetime, which reverts to its original intent. This avoids some bogus diagnostics when build GNU Tar with gcc -flto -fanalyze and with --enable-gcc-warnings. And it slims down the executable a bit. * NEWS: Mention this. * lib/parse-datetime.y (parser_control) [!GNULIB_PARSE_DATETIME2]: Omit parse_datetime_debug member. (debugging): New function. Use it everywhere the old code would load parse_datetime_debug. (parse_datetime_body): New static function, with the body of the old parse_datetime2. Set pc.parse_datetime_debug only if GNULIB_PARSE_DATETIME2. (parse_datetime2, parse_datetime): Use this new function. (parse_datetime2) [!GNULIB_PARSE_DATETIME2]: Remove. --- ChangeLog | 21 ++++++++ NEWS | 5 ++ lib/parse-datetime.y | 122 +++++++++++++++++++++++++++---------------- 3 files changed, 102 insertions(+), 46 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9bc60f88e..f4bf4fced 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2021-03-01 Paul Eggert + + parse-datetime2: new module + This splits the old parse-datetime into two parts; the + first is parse-datetime2 which supports all the new bells + and whistles, the second is parse-datetime, which reverts to + its original intent. This avoids some bogus diagnostics + when build GNU Tar with gcc -flto -fanalyze and + with --enable-gcc-warnings. And it slims down the + executable a bit. + * NEWS: Mention this. + * lib/parse-datetime.y (parser_control) [!GNULIB_PARSE_DATETIME2]: + Omit parse_datetime_debug member. + (debugging): New function. Use it everywhere the old code + would load parse_datetime_debug. + (parse_datetime_body): New static function, with the body + of the old parse_datetime2. Set pc.parse_datetime_debug + only if GNULIB_PARSE_DATETIME2. + (parse_datetime2, parse_datetime): Use this new function. + (parse_datetime2) [!GNULIB_PARSE_DATETIME2]: Remove. + 2021-02-27 Bruno Haible =20 string-buffer: Fixes. diff --git a/NEWS b/NEWS index c347ecd96..318055ae8 100644 --- a/NEWS +++ b/NEWS @@ -60,6 +60,11 @@ User visible incompatible changes =20 Date Modules Changes =20 +2021-02-28 parse-datetime The parse_datetime2 function has been moved + to the new parse-datetime2 module, so that + programs that need just parse_datetime need + not build the fancier function. + 2020-12-23 execute These functions no longer execute scripts wi= thout spawn-pipe '#!' marker through /bin/sh. To execute such= a posix_spawn script as a shell script, either add a '#!/b= in/sh' diff --git a/lib/parse-datetime.y b/lib/parse-datetime.y index b8a832fcd..552fe5c90 100644 --- a/lib/parse-datetime.y +++ b/lib/parse-datetime.y @@ -221,8 +221,10 @@ typedef struct idx_t zones_seen; bool year_seen; =20 +#ifdef GNULIB_PARSE_DATETIME2 /* Print debugging output to stderr. */ bool parse_datetime_debug; +#endif =20 /* Which of the 'seen' parts have been printed when debugging. */ bool debug_dates_seen; @@ -239,6 +241,16 @@ typedef struct table local_time_zone_table[3]; } parser_control; =20 +static bool +debugging (parser_control const *pc) +{ +#ifdef GNULIB_PARSE_DATETIME2 + return pc->parse_datetime_debug; +#else + return false; +#endif +} + union YYSTYPE; static int yylex (union YYSTYPE *, parser_control *); static int yyerror (parser_control const *, char const *); @@ -421,7 +433,7 @@ debug_print_current_time (char const *item, parser_co= ntrol *pc) { bool space =3D false; =20 - if (!pc->parse_datetime_debug) + if (!debugging (pc)) return; =20 /* no newline, more items printed below */ @@ -521,7 +533,7 @@ debug_print_relative_time (char const *item, parser_c= ontrol const *pc) { bool space =3D false; =20 - if (!pc->parse_datetime_debug) + if (!debugging (pc)) return; =20 /* no newline, more items printed below */ @@ -802,7 +814,7 @@ date: you want portability, use the ISO 8601 format. */ if (4 <=3D $1.digits) { - if (pc->parse_datetime_debug) + if (debugging (pc)) { intmax_t digits =3D $1.digits; dbg_printf (_("warning: value %"PRIdMAX" has %"PRIdMAX" = digits. " @@ -816,7 +828,7 @@ date: } else { - if (pc->parse_datetime_debug) + if (debugging (pc)) dbg_printf (_("warning: value %"PRIdMAX" has less than 4 d= igits. " "Assuming MM/DD/YY[YY]\n"), $1.value); @@ -1504,7 +1516,7 @@ yylex (union YYSTYPE *lvalp, parser_control *pc) tp =3D lookup_word (pc, buff); if (! tp) { - if (pc->parse_datetime_debug) + if (debugging (pc)) dbg_printf (_("error: unknown word '%s'\n"), buff); return '?'; } @@ -1651,7 +1663,7 @@ debug_mktime_not_ok (struct tm const *tm0, struct t= m const *tm1, const bool dst_shift =3D eq_sec && eq_min && !eq_hour && eq_mday && eq_month && eq_year; =20 - if (!pc->parse_datetime_debug) + if (!debugging (pc)) return; =20 dbg_printf (_("error: invalid date/time value:\n")); @@ -1690,29 +1702,15 @@ debug_mktime_not_ok (struct tm const *tm0, struct= tm const *tm1, : _("missing timezone"))); } =20 -/* The original interface: run with debug=3Dfalse and the default timezo= ne. */ -bool -parse_datetime (struct timespec *result, char const *p, - struct timespec const *now) -{ - char const *tzstring =3D getenv ("TZ"); - timezone_t tz =3D tzalloc (tzstring); - if (!tz) - return false; - bool ok =3D parse_datetime2 (result, p, now, 0, tz, tzstring); - tzfree (tz); - return ok; -} - /* Parse a date/time string, storing the resulting time value into *RESU= LT. The string itself is pointed to by P. Return true if successful. P can be an incomplete or relative time specification; if so, use *NOW as the basis for the returned time. Default to timezone TZDEFAULT, which corresponds to tzalloc (TZSTRING). */ -bool -parse_datetime2 (struct timespec *result, char const *p, - struct timespec const *now, unsigned int flags, - timezone_t tzdefault, char const *tzstring) +static bool +parse_datetime_body (struct timespec *result, char const *p, + struct timespec const *now, unsigned int flags, + timezone_t tzdefault, char const *tzstring) { struct tm tm; struct tm tm0; @@ -1803,10 +1801,12 @@ parse_datetime2 (struct timespec *result, char co= nst *p, =20 parser_control pc; pc.input =3D p; +#ifdef GNULIB_PARSE_DATETIME2 pc.parse_datetime_debug =3D (flags & PARSE_DATETIME_DEBUG) !=3D 0; +#endif if (INT_ADD_WRAPV (tmp.tm_year, TM_YEAR_BASE, &pc.year.value)) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: initial year out of range\n")); goto fail; } @@ -1900,7 +1900,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, =20 if (yyparse (&pc) !=3D 0) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf ((input_sentinel <=3D pc.input ? _("error: parsing failed\n") : _("error: parsing failed, stopped at '%s'\n")), @@ -1911,7 +1911,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, =20 /* Determine effective timezone source. */ =20 - if (pc.parse_datetime_debug) + if (debugging (&pc)) { dbg_printf (_("input timezone: ")); =20 @@ -1953,7 +1953,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_se= en | (pc.local_zones_seen + pc.zones_seen))) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) { if (pc.times_seen > 1) dbg_printf ("error: seen multiple time parts\n"); @@ -1969,11 +1969,11 @@ parse_datetime2 (struct timespec *result, char co= nst *p, goto fail; } =20 - if (! to_tm_year (pc.year, pc.parse_datetime_debug, &tm.tm_year) + if (! to_tm_year (pc.year, debugging (&pc), &tm.tm_year) || INT_ADD_WRAPV (pc.month, -1, &tm.tm_mon) || INT_ADD_WRAPV (pc.day, 0, &tm.tm_mday)) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: year, month, or day overflow\n")); goto fail; } @@ -1984,14 +1984,14 @@ parse_datetime2 (struct timespec *result, char co= nst *p, { char const *mrd =3D (pc.meridian =3D=3D MERam ? "am" : pc.meridian =3D=3D MERpm ?"pm" : ""); - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: invalid hour %"PRIdMAX"%s\n"), pc.hour, mrd); goto fail; } tm.tm_min =3D pc.minutes; tm.tm_sec =3D pc.seconds.tv_sec; - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf ((pc.times_seen ? _("using specified time as starting value: '%= s'\n") : _("using current time as starting value: '%s'= \n")), @@ -2001,7 +2001,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, { tm.tm_hour =3D tm.tm_min =3D tm.tm_sec =3D 0; pc.seconds.tv_nsec =3D 0; - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf ("warning: using midnight as starting time: 00:00= :00\n"); } =20 @@ -2047,7 +2047,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, timezone_t tz2 =3D tzalloc (tz2buf); if (!tz2) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: tzalloc (\"%s\") failed\n"), t= z2buf); goto fail; } @@ -2092,7 +2092,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, =20 if (Start =3D=3D (time_t) -1) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: day '%s' " "(day ordinal=3D%"PRIdMAX" number=3D%d) " "resulted in an invalid date: '%s'\n"), @@ -2103,14 +2103,14 @@ parse_datetime2 (struct timespec *result, char co= nst *p, goto fail; } =20 - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("new start date: '%s' is '%s'\n"), str_days (&pc, dbg_ord, sizeof dbg_ord), debug_strfdatetime (&tm, &pc, dbg_tm, sizeof dbg= _tm)); =20 } =20 - if (pc.parse_datetime_debug) + if (debugging (&pc)) { if (!pc.dates_seen && !pc.days_seen) dbg_printf (_("using current date as starting value: '%s'\n"= ), @@ -2128,7 +2128,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, /* Add relative date. */ if (pc.rel.year | pc.rel.month | pc.rel.day) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) { if ((pc.rel.year !=3D 0 || pc.rel.month !=3D 0) && tm.tm_m= day !=3D 15) dbg_printf (_("warning: when adding relative months/year= s, " @@ -2145,7 +2145,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, || INT_ADD_WRAPV (tm.tm_mon, pc.rel.month, &month) || INT_ADD_WRAPV (tm.tm_mday, pc.rel.day, &day)) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: %s:%d\n"), __FILE__, __LINE__); goto fail; } @@ -2159,7 +2159,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, Start =3D mktime_z (tz, &tm); if (Start =3D=3D (time_t) -1) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: adding relative date resulted " "in an invalid date: '%s'\n"), debug_strfdatetime (&tm, &pc, dbg_tm, @@ -2167,7 +2167,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, goto fail; } =20 - if (pc.parse_datetime_debug) + if (debugging (&pc)) { dbg_printf (_("after date adjustment " "(%+"PRIdMAX" years, %+"PRIdMAX" months, " @@ -2244,7 +2244,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, overflow |=3D INT_SUBTRACT_WRAPV (Start, delta, &t1); if (overflow) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: timezone %d caused time_t overflow= \n"), pc.time_zone); goto fail; @@ -2252,7 +2252,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, Start =3D t1; } =20 - if (pc.parse_datetime_debug) + if (debugging (&pc)) { intmax_t Starti =3D Start; dbg_printf (_("'%s' =3D %"PRIdMAX" epoch-seconds\n"), @@ -2282,7 +2282,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, || INT_ADD_WRAPV (t2, pc.rel.seconds, &t3) || INT_ADD_WRAPV (t3, d4, &t4)) { - if (pc.parse_datetime_debug) + if (debugging (&pc)) dbg_printf (_("error: adding relative time caused an " "overflow\n")); goto fail; @@ -2291,7 +2291,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, result->tv_sec =3D t4; result->tv_nsec =3D normalized_ns; =20 - if (pc.parse_datetime_debug + if (debugging (&pc) && (pc.rel.hour | pc.rel.minutes | pc.rel.seconds | pc.rel.n= s)) { dbg_printf (_("after time adjustment (%+"PRIdMAX" hours, " @@ -2322,7 +2322,7 @@ parse_datetime2 (struct timespec *result, char cons= t *p, } } =20 - if (pc.parse_datetime_debug) + if (debugging (&pc)) { /* Special case: using 'date -u' simply set TZ=3DUTC0 */ if (! tzstring) @@ -2373,6 +2373,36 @@ parse_datetime2 (struct timespec *result, char con= st *p, return ok; } =20 +#ifdef GNULIB_PARSE_DATETIME2 +/* Parse a date/time string, storing the resulting time value into *RESU= LT. + The string itself is pointed to by P. Return true if successful. + P can be an incomplete or relative time specification; if so, use + *NOW as the basis for the returned time. Default to timezone + TZDEFAULT, which corresponds to tzalloc (TZSTRING). */ +bool +parse_datetime2 (struct timespec *result, char const *p, + struct timespec const *now, unsigned int flags, + timezone_t tzdefault, char const *tzstring) +{ + return parse_datetime_body (result, p, now, flags, tzdefault, tzstring= ); +} +#endif + + +/* The plain interface: run with debug=3Dfalse and the default timezone.= */ +bool +parse_datetime (struct timespec *result, char const *p, + struct timespec const *now) +{ + char const *tzstring =3D getenv ("TZ"); + timezone_t tz =3D tzalloc (tzstring); + if (!tz) + return false; + bool ok =3D parse_datetime_body (result, p, now, 0, tz, tzstring); + tzfree (tz); + return ok; +} + #if TEST =20 int --=20 2.29.2