From 7e8b7b5f38f9a9e3a8750310d0dd018af71231e4 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 9 Aug 2021 14:23:05 -0700 Subject: [PROPOSED] Remove some lint found by GCC, Clang * localtime.c (transtime): Use UNREACHABLE instead of INITIALIZE to pacify GCC, as this gives more information to the reader. * localtime.c (tzparse): * zic.c (rpytime): Omit unnecessary initialization. * private.h (UNREACHABLE): New macro. * zdump.c (main, hunt): Redo to avoid need for INITIALIZE. The code is arguably cleaner that way anyway. * zic.c (infile, rulesub): Use UNREACHABLE instead of a panic message. (inrule): Do not rely on r if rulesub fails. (inzsub): Avoid unlikely small memory leaks, by not calling ecpyalloc until checks have succeeded. --- localtime.c | 4 +-- private.h | 13 +++++++++ zdump.c | 25 ++++++++--------- zic.c | 77 ++++++++++++++++++++++++----------------------------- 4 files changed, 63 insertions(+), 56 deletions(-) diff --git a/localtime.c b/localtime.c index 9840b89..c986be5 100644 --- a/localtime.c +++ b/localtime.c @@ -979,7 +979,6 @@ transtime(const int year, register const struct rule *const rulep, register int i; int d, m1, yy0, yy1, yy2, dow; - INITIALIZE(value); leapyear = isleap(year); switch (rulep->r_type) { @@ -1045,6 +1044,8 @@ transtime(const int year, register const struct rule *const rulep, for (i = 0; i < rulep->r_mon - 1; ++i) value += mon_lengths[leapyear][i] * SECSPERDAY; break; + + default: UNREACHABLE(); } /* @@ -1274,7 +1275,6 @@ tzparse(const char *name, struct state *sp, struct state *basep) ** Initially we're assumed to be in standard time. */ isdst = false; - theiroffset = theirstdoffset; /* ** Now juggle transition times and types ** tracking offsets as you do. diff --git a/private.h b/private.h index 6425298..9dbb071 100644 --- a/private.h +++ b/private.h @@ -685,6 +685,19 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE; # define UNINIT_TRAP 0 #endif +#ifdef DEBUG +# define UNREACHABLE() abort() +#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__) +# define UNREACHABLE() __builtin_unreachable() +#elif defined __has_builtin +# if __has_builtin(__builtin_unreachable) +# define UNREACHABLE() __builtin_unreachable() +# endif +#endif +#ifndef UNREACHABLE +# define UNREACHABLE() ((void) 0) +#endif + /* ** For the benefit of GNU folk... ** '_(MSGID)' uses the current locale's message library string for MSGID. diff --git a/zdump.c b/zdump.c index bf2da67..b3f3448 100644 --- a/zdump.c +++ b/zdump.c @@ -519,9 +519,12 @@ main(int argc, char *argv[]) } } gmtzinit(); - INITIALIZE(now); - if (! (iflag | vflag | Vflag)) + if (iflag | vflag | Vflag) + now = 0; + else { now = time(NULL); + now |= !now; + } longest = 0; for (i = optind; i < argc; i++) { size_t arglen = strlen(argv[i]); @@ -539,7 +542,7 @@ main(int argc, char *argv[]) perror(argv[i]); return EXIT_FAILURE; } - if (! (iflag | vflag | Vflag)) { + if (now) { show(tz, argv[i], now, false); tzfree(tz); continue; @@ -557,7 +560,6 @@ main(int argc, char *argv[]) } if (t + 1 < cutlotime) t = cutlotime - 1; - INITIALIZE (ab); tm_ok = my_localtime_rz(tz, &t, &tm) != NULL; if (tm_ok) { ab = saveabbr(&abbrev, &abbrevsize, &tm); @@ -565,7 +567,8 @@ main(int argc, char *argv[]) showtrans("\nTZ=%f", &tm, t, ab, argv[i]); showtrans("-\t-\t%Q", &tm, t, ab, argv[i]); } - } + } else + ab = NULL; while (t < cuthitime - 1) { time_t newt = ((t < absolute_max_time - SECSPERDAY / 2 && t + SECSPERDAY / 2 < cuthitime - 1) @@ -574,9 +577,9 @@ main(int argc, char *argv[]) struct tm *newtmp = localtime_rz(tz, &newt, &newtm); bool newtm_ok = newtmp != NULL; if (tm_ok != newtm_ok - || (tm_ok && (delta(&newtm, &tm) != newt - t - || newtm.tm_isdst != tm.tm_isdst - || strcmp(abbr(&newtm), ab) != 0))) { + || (ab && (delta(&newtm, &tm) != newt - t + || newtm.tm_isdst != tm.tm_isdst + || strcmp(abbr(&newtm), ab) != 0))) { newt = hunt(tz, argv[i], t, newt, false); newtmp = localtime_rz(tz, &newt, &newtm); newtm_ok = newtmp != NULL; @@ -669,7 +672,6 @@ hunt(timezone_t tz, char *name, time_t lot, time_t hit, bool only_ok) { static char * loab; static size_t loabsize; - char const * ab; struct tm lotm; struct tm tm; @@ -679,9 +681,8 @@ hunt(timezone_t tz, char *name, time_t lot, time_t hit, bool only_ok) LOT, and tzname needs to be changed back. */ bool lotm_ok = my_localtime_rz(tz, &lot, &lotm) != NULL; bool tm_ok; + char const *ab = lotm_ok ? saveabbr(&loab, &loabsize, &lotm) : NULL; - if (lotm_ok) - ab = saveabbr(&loab, &loabsize, &lotm); for ( ; ; ) { /* T = average of LOT and HIT, rounding down. Avoid overflow, even on oddball C89 platforms @@ -696,7 +697,7 @@ hunt(timezone_t tz, char *name, time_t lot, time_t hit, bool only_ok) tm_ok = my_localtime_rz(tz, &t, &tm) != NULL; if (lotm_ok == tm_ok && (only_ok - || (lotm_ok && tm.tm_isdst == lotm.tm_isdst + || (ab && tm.tm_isdst == lotm.tm_isdst && delta(&tm, &lotm) == t - lot && strcmp(abbr(&tm), ab) == 0))) { lot = t; diff --git a/zic.c b/zic.c index 8d1ea03..ddcb1e5 100644 --- a/zic.c +++ b/zic.c @@ -164,7 +164,7 @@ static void newabbr(const char * abbr); static zic_t oadd(zic_t t1, zic_t t2); static void outzone(const struct zone * zp, ptrdiff_t ntzones); static zic_t rpytime(const struct rule * rp, zic_t wantedy); -static void rulesub(struct rule * rp, +static bool rulesub(struct rule * rp, const char * loyearp, const char * hiyearp, const char * typep, const char * monthp, const char * dayp, const char * timep); @@ -1374,11 +1374,7 @@ infile(const char *name) inexpires(fields, nfields); wantcont = false; break; - default: /* "cannot happen" */ - fprintf(stderr, -_("%s: panic: Invalid l_value %d\n"), - progname, lp->l_value); - exit(EXIT_FAILURE); + default: UNREACHABLE(); } } free(fields); @@ -1489,8 +1485,10 @@ inrule(char **fields, int nfields) r.r_filename = filename; r.r_linenum = linenum; r.r_save = getsave(fields[RF_SAVE], &r.r_isdst); - rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], fields[RF_COMMAND], - fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); + if (!rulesub(&r, fields[RF_LOYEAR], fields[RF_HIYEAR], + fields[RF_COMMAND], fields[RF_MONTH], fields[RF_DAY], + fields[RF_TOD])) + return; r.r_name = ecpyalloc(fields[RF_NAME]); r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); if (max_abbrvar_len < strlen(r.r_abbrvar)) @@ -1549,6 +1547,7 @@ inzsub(char **fields, int nfields, bool iscont) register char * cp; char * cp1; struct zone z; + size_t format_len; register int i_stdoff, i_rule, i_format; register int i_untilyear, i_untilmonth; register int i_untilday, i_untiltime; @@ -1562,7 +1561,6 @@ inzsub(char **fields, int nfields, bool iscont) i_untilmonth = ZFC_TILMONTH; i_untilday = ZFC_TILDAY; i_untiltime = ZFC_TILTIME; - z.z_name = NULL; } else if (!namecheck(fields[ZF_NAME])) return false; else { @@ -1573,7 +1571,6 @@ inzsub(char **fields, int nfields, bool iscont) i_untilmonth = ZF_TILMONTH; i_untilday = ZF_TILDAY; i_untiltime = ZF_TILTIME; - z.z_name = ecpyalloc(fields[ZF_NAME]); } z.z_filename = filename; z.z_linenum = linenum; @@ -1585,29 +1582,24 @@ inzsub(char **fields, int nfields, bool iscont) return false; } } - z.z_rule = ecpyalloc(fields[i_rule]); - z.z_format = cp1 = ecpyalloc(fields[i_format]); z.z_format_specifier = cp ? *cp : '\0'; - if (z.z_format_specifier == 'z') { - if (noise) - warning(_("format '%s' not handled by pre-2015 versions of zic"), - z.z_format); - cp1[cp - fields[i_format]] = 's'; - } - if (max_format_len < strlen(z.z_format)) - max_format_len = strlen(z.z_format); + format_len = strlen(fields[i_format]); + if (max_format_len < format_len) + max_format_len = format_len; hasuntil = nfields > i_untilyear; if (hasuntil) { z.z_untilrule.r_filename = filename; z.z_untilrule.r_linenum = linenum; - rulesub(&z.z_untilrule, + if (!rulesub( + &z.z_untilrule, fields[i_untilyear], "only", "", (nfields > i_untilmonth) ? fields[i_untilmonth] : "Jan", (nfields > i_untilday) ? fields[i_untilday] : "1", - (nfields > i_untiltime) ? fields[i_untiltime] : "0"); + (nfields > i_untiltime) ? fields[i_untiltime] : "0")) + return false; z.z_untiltime = rpytime(&z.z_untilrule, z.z_untilrule.r_loyear); if (iscont && nzones > 0 && @@ -1622,6 +1614,15 @@ inzsub(char **fields, int nfields, bool iscont) return false; } } + z.z_name = iscont ? NULL : ecpyalloc(fields[ZF_NAME]); + z.z_rule = ecpyalloc(fields[i_rule]); + z.z_format = cp1 = ecpyalloc(fields[i_format]); + if (z.z_format_specifier == 'z') { + cp1[cp - fields[i_format]] = 's'; + if (noise) + warning(_("format '%s' not handled by pre-2015 versions of zic"), + fields[i_format]); + } zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc); zones[nzones++] = z; /* @@ -1764,7 +1765,7 @@ inlink(char **fields, int nfields) links[nlinks++] = l; } -static void +static bool rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, const char *typep, const char *monthp, const char *dayp, const char *timep) @@ -1777,7 +1778,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, if ((lp = byword(monthp, mon_names)) == NULL) { error(_("invalid month name")); - return; + return false; } rp->r_month = lp->l_value; rp->r_todisstd = false; @@ -1820,14 +1821,10 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, case YR_MAXIMUM: rp->r_loyear = ZIC_MAX; break; - default: /* "cannot happen" */ - fprintf(stderr, - _("%s: panic: Invalid l_value %d\n"), - progname, lp->l_value); - exit(EXIT_FAILURE); + default: UNREACHABLE(); } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) { error(_("invalid starting year")); - return; + return false; } cp = hiyearp; lp = byword(cp, end_years); @@ -1842,23 +1839,19 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, case YR_ONLY: rp->r_hiyear = rp->r_loyear; break; - default: /* "cannot happen" */ - fprintf(stderr, - _("%s: panic: Invalid l_value %d\n"), - progname, lp->l_value); - exit(EXIT_FAILURE); + default: UNREACHABLE(); } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_hiyear, &xs) != 1) { error(_("invalid ending year")); - return; + return false; } if (rp->r_loyear > rp->r_hiyear) { error(_("starting year greater than ending year")); - return; + return false; } if (*typep != '\0') { error(_("year type \"%s\" is unsupported; use \"-\" instead"), typep); - return; + return false; } /* ** Day work. @@ -1888,12 +1881,12 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, if (*ep++ != '=') { error(_("invalid day of month")); free(dp); - return; + return false; } if ((lp = byword(dp, wday_names)) == NULL) { error(_("invalid weekday name")); free(dp); - return; + return false; } rp->r_wday = lp->l_value; } @@ -1902,10 +1895,11 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp, (rp->r_dayofmonth > len_months[1][rp->r_month])) { error(_("invalid day of month")); free(dp); - return; + return false; } } free(dp); + return true; } static void @@ -3423,7 +3417,6 @@ rpytime(const struct rule *rp, zic_t wantedy) return min_time; if (wantedy == ZIC_MAX) return max_time; - dayoff = 0; m = TM_JANUARY; y = EPOCH_YEAR; -- 2.30.2