aboutsummaryrefslogtreecommitdiff
path: root/zic.c
diff options
context:
space:
mode:
Diffstat (limited to 'zic.c')
-rw-r--r--zic.c351
1 files changed, 181 insertions, 170 deletions
diff --git a/zic.c b/zic.c
index 7ecf3b9115f3..d5e521d6b664 100644
--- a/zic.c
+++ b/zic.c
@@ -262,7 +262,6 @@ static void checkabbr(char const *);
static void check_for_signal(void);
static void dolink(const char *, const char *, bool);
static int getfields(char *, char **, int);
-static zic_t gethms(const char * string, const char * errstring);
static zic_t getsave(char *, bool *);
static void inexpires(char **, int);
static void infile(int, char const *);
@@ -280,6 +279,7 @@ static void mkdirs(char const *, bool);
static zic_t oadd(zic_t t1, zic_t t2);
static zic_t omul(zic_t, zic_t);
static void outzone(const struct zone * zp, ptrdiff_t ntzones);
+static void remove_temp(char const *);
static zic_t rpytime(const struct rule * rp, zic_t wantedy);
static bool rulesub(struct rule * rp,
const char * loyearp, const char * hiyearp,
@@ -413,10 +413,10 @@ enum {
};
/* The maximum number of fields on any of the above lines.
- (The "+"s pacify gcc -Wenum-compare.) */
+ (This uses INT_PROMOTE to pacify gcc -Wenum-compare.) */
enum {
- MAX_FIELDS = max(max(+RULE_FIELDS, +LINK_FIELDS),
- max(+LEAP_FIELDS, +EXPIRES_FIELDS))
+ MAX_FIELDS = max(max(INT_PROMOTE(RULE_FIELDS), INT_PROMOTE(LINK_FIELDS)),
+ max(INT_PROMOTE(LEAP_FIELDS), INT_PROMOTE(EXPIRES_FIELDS)))
};
/*
@@ -704,7 +704,7 @@ eat(int fnum, lineno num)
}
ATTRIBUTE_FORMAT((printf, 1, 0)) static void
-verror(const char *const string, va_list args)
+verror(char const *msgid, va_list args)
{
check_for_signal();
/*
@@ -715,7 +715,7 @@ verror(const char *const string, va_list args)
if (filenum)
fprintf(stderr, _("\"%s\", line %"PRIdMAX": "),
filename(filenum), linenum);
- vfprintf(stderr, string, args);
+ vfprintf(stderr, _(msgid), args);
if (rfilenum)
fprintf(stderr, _(" (rule from \"%s\", line %"PRIdMAX")"),
filename(rfilenum), rlinenum);
@@ -723,22 +723,22 @@ verror(const char *const string, va_list args)
}
ATTRIBUTE_FORMAT((printf, 1, 2)) static void
-error(const char *const string, ...)
+error(char const *msgid, ...)
{
va_list args;
- va_start(args, string);
- verror(string, args);
+ va_start(args, msgid);
+ verror(msgid, args);
va_end(args);
errors = true;
}
ATTRIBUTE_FORMAT((printf, 1, 2)) static void
-warning(const char *const string, ...)
+warning(char const *msgid, ...)
{
va_list args;
fprintf(stderr, _("warning: "));
- va_start(args, string);
- verror(string, args);
+ va_start(args, msgid);
+ verror(msgid, args);
va_end(args);
warnings = true;
}
@@ -841,7 +841,7 @@ close_file(FILE *stream, char const *dir, char const *name,
name ? name : "", name ? ": " : "",
e);
if (tempname)
- remove(tempname);
+ remove_temp(tempname);
exit(EXIT_FAILURE);
}
}
@@ -1039,7 +1039,7 @@ make_links(void)
/* If this pass examined all its links, start the next pass. */
if (i == j) {
if (nalinks - i == pass_size) {
- error(_("\"Link %s %s\" is part of a link cycle"),
+ error(N_("\"Link %s %s\" is part of a link cycle"),
links[i].l_target, links[i].l_linkname);
break;
}
@@ -1050,7 +1050,7 @@ make_links(void)
/* Diagnose self links, which the cycle detection algorithm would not
otherwise catch. */
if (strcmp(links[i].l_target, links[i].l_linkname) == 0) {
- error(_("link %s targets itself"), links[i].l_target);
+ error(N_("link %s targets itself"), links[i].l_target);
continue;
}
@@ -1070,11 +1070,11 @@ make_links(void)
if (noise && i < nlinks) {
if (l)
- warning(_("link %s targeting link %s mishandled by pre-2023 zic"),
+ warning(N_("link %s targeting link %s mishandled by pre-2023 zic"),
links[i].l_linkname, links[i].l_target);
else if (bsearch(links[i].l_target, links, nlinks, sizeof *links,
bsearch_linkcmp))
- warning(_("link %s targeting link %s"),
+ warning(N_("link %s targeting link %s"),
links[i].l_linkname, links[i].l_target);
}
check_for_signal();
@@ -1264,14 +1264,14 @@ main(int argc, char **argv)
case 'b':
if (strcmp(optarg, "slim") == 0) {
if (0 < bloat)
- error(_("incompatible -b options"));
+ error(N_("incompatible -b options"));
bloat = -1;
} else if (strcmp(optarg, "fat") == 0) {
if (bloat < 0)
- error(_("incompatible -b options"));
+ error(N_("incompatible -b options"));
bloat = 1;
} else
- error(_("invalid option: -b '%s'"), optarg);
+ error(N_("invalid option: -b '%s'"), optarg);
break;
case 'd':
if (directory)
@@ -1300,8 +1300,8 @@ main(int argc, char **argv)
if (psxrules)
duplicate_options("-p");
if (strcmp(optarg, "-") != 0)
- warning(_("-p is obsolete"
- " and likely ineffective"));
+ warning(N_("-p is obsolete"
+ " and likely ineffective"));
psxrules = optarg;
break;
case 't':
@@ -1320,7 +1320,7 @@ main(int argc, char **argv)
}
break;
case 'y':
- warning(_("-y ignored"));
+ warning(N_("-y ignored"));
break;
case 'L':
if (leapsec)
@@ -1349,7 +1349,7 @@ main(int argc, char **argv)
}
break;
case 's':
- warning(_("-s ignored"));
+ warning(N_("-s ignored"));
break;
}
if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
@@ -1419,30 +1419,30 @@ componentcheck(char const *name, char const *component,
ptrdiff_t component_len = component_end - component;
if (component_len == 0) {
if (!*name)
- error(_("empty file name"));
+ error(N_("empty file name"));
else
- error(_(component == name
- ? "file name '%s' begins with '/'"
- : *component_end
- ? "file name '%s' contains '//'"
- : "file name '%s' ends with '/'"),
- name);
+ error((component == name
+ ? N_("file name '%s' begins with '/'")
+ : *component_end
+ ? N_("file name '%s' contains '//'")
+ : N_("file name '%s' ends with '/'")),
+ name);
return false;
}
if (0 < component_len && component_len <= 2
&& component[0] == '.' && component_end[-1] == '.') {
int len = component_len;
- error(_("file name '%s' contains '%.*s' component"),
+ error(N_("file name '%s' contains '%.*s' component"),
name, len, component);
return false;
}
if (noise) {
if (0 < component_len && component[0] == '-')
- warning(_("file name '%s' component contains leading '-'"),
+ warning(N_("file name '%s' component contains leading '-'"),
name);
if (component_len_max < component_len)
- warning(_("file name '%s' contains overlength component"
- " '%.*s...'"),
+ warning(N_("file name '%s' contains overlength component"
+ " '%.*s...'"),
name, component_len_max, component);
}
return true;
@@ -1469,8 +1469,8 @@ namecheck(const char *name)
unsigned char c = *cp;
if (noise && !strchr(benign, c)) {
warning((strchr(printable_and_not_benign, c)
- ? _("file name '%s' contains byte '%c'")
- : _("file name '%s' contains byte '\\%o'")),
+ ? N_("file name '%s' contains byte '%c'")
+ : N_("file name '%s' contains byte '\\%o'")),
name, c);
}
if (c == '/') {
@@ -1658,16 +1658,25 @@ rename_dest(char *tempname, char const *name)
if (tempname) {
if (rename(tempname, name) != 0) {
int rename_errno = errno;
- remove(tempname);
fprintf(stderr, _("%s: rename to %s%s%s: %s\n"),
progname, diagdir(name), diagslash(name), name,
strerror(rename_errno));
+ remove_temp(tempname);
exit(EXIT_FAILURE);
}
free(tempname);
}
}
+/* Remove the temporary file TEMP, diagnosing any failure. */
+static void
+remove_temp(char const *temp)
+{
+ if (remove(temp) < 0)
+ fprintf(stderr, _("%s: Can't remove temporary file %s%s%s: %s\n"),
+ progname, diagdir(temp), diagslash(temp), temp, strerror(errno));
+}
+
/* Create symlink contents suitable for symlinking TARGET to LINKNAME, as a
freshly allocated string. TARGET should be a relative file name, and
is relative to the global variable DIRECTORY. LINKNAME can be either
@@ -1818,7 +1827,7 @@ dolink(char const *target, char const *linkname, bool staysymlink)
free(linkalloc);
if (symlink_errno == 0) {
if (link_errno != ENOTSUP && link_errno != EEXIST)
- warning(_("symbolic link used because hard link failed: %s"),
+ warning(N_("symbolic link used because hard link failed: %s"),
strerror(link_errno));
} else {
FILE *fp, *tp;
@@ -1836,12 +1845,12 @@ dolink(char const *target, char const *linkname, bool staysymlink)
close_file(tp, directory, linkname, tempname);
close_file(fp, directory, target, NULL);
if (link_errno != ENOTSUP)
- warning(_("copy used because hard link failed: %s"),
+ warning(N_("copy used because hard link failed: %s"),
strerror(link_errno));
else if (symlink_errno < 0)
- warning(_("copy used because symbolic link not obvious"));
+ warning(N_("copy used because symbolic link not obvious"));
else if (symlink_errno != ENOTSUP)
- warning(_("copy used because symbolic link failed: %s"),
+ warning(N_("copy used because symbolic link failed: %s"),
strerror(symlink_errno));
}
}
@@ -1892,9 +1901,9 @@ associate(void)
if (rules[i].r_filenum == rules[i + 1].r_filenum)
continue;
eat(rules[i].r_filenum, rules[i].r_linenum);
- warning(_("same rule name in multiple files"));
+ warning(N_("same rule name in multiple files"));
eat(rules[i + 1].r_filenum, rules[i + 1].r_linenum);
- warning(_("same rule name in multiple files"));
+ warning(N_("same rule name in multiple files"));
for (j = i + 2; j < nrules; ++j) {
if (strcmp(rules[i].r_name,
rules[j].r_name) != 0)
@@ -1940,7 +1949,7 @@ associate(void)
** a '%s' in the format is a bad thing.
*/
if (zp->z_format_specifier == 's')
- error("%s", _("%s in ruleless zone"));
+ error(N_("%%s in ruleless zone"));
}
}
if (errors)
@@ -1958,21 +1967,21 @@ inputline(FILE *fp, char *buf, ptrdiff_t bufsize)
for (; (ch = getc(fp)) != '\n'; check_for_signal()) {
if (ch < 0) {
if (ferror(fp)) {
- error(_("input error"));
+ error(N_("input error"));
exit(EXIT_FAILURE);
}
if (linelen == 0)
return false;
- error(_("unterminated line"));
+ error(N_("unterminated line"));
exit(EXIT_FAILURE);
}
if (!ch) {
- error(_("NUL input byte"));
+ error(N_("NUL input byte"));
exit(EXIT_FAILURE);
}
buf[linelen++] = ch;
if (linelen == bufsize) {
- error(_("line too long"));
+ error(N_("line too long"));
exit(EXIT_FAILURE);
}
}
@@ -2018,7 +2027,7 @@ infile(int fnum, char const *name)
= fnum < 0 ? leap_line_codes : zi_line_codes;
lp = byword(fields[0], line_codes);
if (lp == NULL)
- error(_("input line of unknown type"));
+ error(N_("input line of unknown type"));
else switch (lp->l_value) {
case LC_RULE:
inrule(fields, nfields);
@@ -2046,7 +2055,7 @@ infile(int fnum, char const *name)
}
close_file(fp, NULL, filename(fnum), NULL);
if (wantcont)
- error(_("expected continuation line not found"));
+ error(N_("expected continuation line not found"));
}
/*
@@ -2054,13 +2063,13 @@ infile(int fnum, char const *name)
** h -h hh:mm -hh:mm hh:mm:ss -hh:mm:ss
** into a number of seconds.
** A null string maps to zero.
-** Call error with errstring and return zero on errors.
+** Call error with msgid and return zero on errors.
*/
static zic_t
-gethms(char const *string, char const *errstring)
+gethms(char const *string, char const *msgid)
{
- zic_t hh;
+ zic_t hh, r;
int sign, mm = 0, ss = 0;
char hhx, mmx, ssx, xr = '0', xs;
int tenths = 0;
@@ -2082,29 +2091,37 @@ gethms(char const *string, char const *errstring)
case 7:
ok &= ssx == '.';
if (ok && noise)
- warning(_("fractional seconds rejected by"
- " pre-2018 versions of zic"));
+ warning(N_("fractional seconds rejected by"
+ " pre-2018 versions of zic"));
ATTRIBUTE_FALLTHROUGH;
case 5: ok &= mmx == ':'; ATTRIBUTE_FALLTHROUGH;
case 3: ok &= hhx == ':'; ATTRIBUTE_FALLTHROUGH;
case 1: break;
}
- if (!ok) {
- error("%s", errstring);
- return 0;
- }
- if (hh < 0 ||
+ if (!ok || hh < 0 ||
mm < 0 || mm >= MINSPERHOUR ||
ss < 0 || ss > SECSPERMIN) {
- error("%s", errstring);
+ error(N_("%s: %s"), string, _(msgid));
return 0;
}
ss += 5 + ((ss ^ 1) & (xr == '0')) <= tenths; /* Round to even. */
if (noise && (hh > HOURSPERDAY ||
(hh == HOURSPERDAY && (mm != 0 || ss != 0))))
-warning(_("values over 24 hours not handled by pre-2007 versions of zic"));
- return oadd(omul(hh, sign * SECSPERHOUR),
- sign * (mm * SECSPERMIN + ss));
+ warning(N_("values over 24 hours"
+ " not handled by pre-2007 versions of zic"));
+ r = oadd(omul(hh, sign * SECSPERHOUR), sign * (mm * SECSPERMIN + ss));
+
+ /* Check that 4 * R fits in zic_t. This is more than enough
+ for times of day and for UT offsets in TZif files, and it
+ avoids later problems during arithmetic on these numbers,
+ as stringzone can compute up to 3 times one of these values
+ when computing fake timezones, and stringrule can do a bit more.
+ Do not limit R strictly to 32 bits here, as it is OK to go
+ over the TZif limit temporarily so long as the result fits. */
+ omul(r, 4);
+ /* Discard omul's return value, as it is not needed here. */
+
+ return r;
}
static zic_t
@@ -2120,7 +2137,7 @@ getsave(char *field, bool *isdst)
case 's': dst = 0; *ep = '\0'; break;
}
}
- save = gethms(field, _("invalid saved time"));
+ save = gethms(field, N_("invalid saved time"));
*isdst = dst < 0 ? save != 0 : dst;
return save;
}
@@ -2131,7 +2148,7 @@ inrule(char **fields, int nfields)
struct rule r;
if (nfields != RULE_FIELDS) {
- error(_("wrong number of fields on Rule line"));
+ error(N_("wrong number of fields on Rule line"));
return;
}
switch (*fields[RF_NAME]) {
@@ -2140,7 +2157,7 @@ inrule(char **fields, int nfields)
case '+': case '-':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
+ error(N_("Invalid rule name \"%s\""), fields[RF_NAME]);
return;
}
r.r_filenum = filenum;
@@ -2164,23 +2181,23 @@ inzone(char **fields, int nfields)
register ptrdiff_t i;
if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
- error(_("wrong number of fields on Zone line"));
+ error(N_("wrong number of fields on Zone line"));
return false;
}
if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0) {
- error(_("\"Zone %s\" line and -l option are mutually exclusive"),
+ error(N_("\"Zone %s\" line and -l option are mutually exclusive"),
tzdefault);
return false;
}
if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
- error(_("\"Zone %s\" line and -p option are mutually exclusive"),
+ error(N_("\"Zone %s\" line and -p option are mutually exclusive"),
TZDEFRULES);
return false;
}
for (i = 0; i < nzones; ++i)
if (zones[i].z_name != NULL &&
strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
- error(_("duplicate zone name %s"
+ error(N_("duplicate zone name %s"
" (file \"%s\", line %"PRIdMAX")"),
fields[ZF_NAME],
filename(zones[i].z_filenum),
@@ -2194,7 +2211,7 @@ static bool
inzcont(char **fields, int nfields)
{
if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) {
- error(_("wrong number of fields on Zone continuation line"));
+ error(N_("wrong number of fields on Zone continuation line"));
return false;
}
return inzsub(fields, nfields, true);
@@ -2233,12 +2250,12 @@ inzsub(char **fields, int nfields, bool iscont)
}
z.z_filenum = filenum;
z.z_linenum = linenum;
- z.z_stdoff = gethms(fields[i_stdoff], _("invalid UT offset"));
+ z.z_stdoff = gethms(fields[i_stdoff], N_("invalid UT offset"));
cp = strchr(fields[i_format], '%');
if (cp) {
if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
|| strchr(fields[i_format], '/')) {
- error(_("invalid abbreviation format"));
+ error(N_("invalid abbreviation format"));
return false;
}
}
@@ -2264,8 +2281,8 @@ inzsub(char **fields, int nfields, bool iscont)
z.z_untilrule.r_loyear);
if (iscont && nzones > 0 &&
zones[nzones - 1].z_untiltime >= z.z_untiltime) {
- error(_("Zone continuation line end time is"
- " not after end time of previous line"));
+ error(N_("Zone continuation line end time is"
+ " not after end time of previous line"));
return false;
}
}
@@ -2275,7 +2292,7 @@ inzsub(char **fields, int nfields, bool iscont)
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"),
+ warning(N_("format '%s' not handled by pre-2015 versions of zic"),
fields[i_format]);
}
zones = growalloc(zones, sizeof *zones, nzones, &nzones_alloc);
@@ -2305,7 +2322,7 @@ getleapdatetime(char **fields, bool expire_line)
/*
** Leapin' Lizards!
*/
- error(_("invalid leaping year"));
+ error(N_("invalid leaping year"));
return -1;
}
if (!expire_line) {
@@ -2327,7 +2344,7 @@ getleapdatetime(char **fields, bool expire_line)
dayoff = oadd(dayoff, i);
}
if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
- error(_("invalid month name"));
+ error(N_("invalid month name"));
return -1;
}
month = lp->l_value;
@@ -2340,15 +2357,15 @@ getleapdatetime(char **fields, bool expire_line)
cp = fields[LP_DAY];
if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
day <= 0 || day > len_months[isleap(year)][month]) {
- error(_("invalid day of month"));
+ error(N_("invalid day of month"));
return -1;
}
dayoff = oadd(dayoff, day - 1);
t = omul(dayoff, SECSPERDAY);
- tod = gethms(fields[LP_TIME], _("invalid time of day"));
+ tod = gethms(fields[LP_TIME], N_("invalid time of day"));
t = tadd(t, tod);
if (t < 0)
- error(_("leap second precedes Epoch"));
+ error(N_("leap second precedes Epoch"));
return t;
}
@@ -2356,13 +2373,13 @@ static void
inleap(char **fields, int nfields)
{
if (nfields != LEAP_FIELDS)
- error(_("wrong number of fields on Leap line"));
+ error(N_("wrong number of fields on Leap line"));
else {
zic_t t = getleapdatetime(fields, false);
if (0 <= t) {
struct lookup const *lp = byword(fields[LP_ROLL], leap_types);
if (!lp)
- error(_("invalid Rolling/Stationary field on Leap line"));
+ error(N_("invalid Rolling/Stationary field on Leap line"));
else {
int correction = 0;
if (!fields[LP_CORR][0]) /* infile() turns "-" into "". */
@@ -2370,7 +2387,7 @@ inleap(char **fields, int nfields)
else if (strcmp(fields[LP_CORR], "+") == 0)
correction = 1;
else
- error(_("invalid CORRECTION field on Leap line"));
+ error(N_("invalid CORRECTION field on Leap line"));
if (correction)
leapadd(t, correction, lp->l_value);
}
@@ -2382,9 +2399,9 @@ static void
inexpires(char **fields, int nfields)
{
if (nfields != EXPIRES_FIELDS)
- error(_("wrong number of fields on Expires line"));
+ error(N_("wrong number of fields on Expires line"));
else if (0 <= leapexpires)
- error(_("multiple Expires lines"));
+ error(N_("multiple Expires lines"));
else
leapexpires = getleapdatetime(fields, true);
}
@@ -2395,11 +2412,11 @@ inlink(char **fields, int nfields)
struct link l;
if (nfields != LINK_FIELDS) {
- error(_("wrong number of fields on Link line"));
+ error(N_("wrong number of fields on Link line"));
return;
}
if (*fields[LF_TARGET] == '\0') {
- error(_("blank TARGET field on Link line"));
+ error(N_("blank TARGET field on Link line"));
return;
}
if (! namecheck(fields[LF_LINKNAME]))
@@ -2424,7 +2441,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
char xs;
if ((lp = byword(monthp, mon_names)) == NULL) {
- error(_("invalid month name"));
+ error(N_("invalid month name"));
return false;
}
rp->r_month = lp->l_value;
@@ -2453,7 +2470,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
break;
}
}
- rp->r_tod = gethms(dp, _("invalid time of day"));
+ rp->r_tod = gethms(dp, N_("invalid time of day"));
free(dp);
/*
** Year work.
@@ -2462,14 +2479,14 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
lp = byword(cp, begin_years);
if (lp) switch (lp->l_value) {
case YR_MINIMUM:
- warning(_("FROM year \"%s\" is obsolete;"
- " treated as %d"),
+ warning(N_("FROM year \"%s\" is obsolete;"
+ " treated as %d"),
cp, YEAR_32BIT_MIN - 1);
rp->r_loyear = YEAR_32BIT_MIN - 1;
break;
default: unreachable();
} else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) {
- error(_("invalid starting year"));
+ error(N_("invalid starting year"));
return false;
}
cp = hiyearp;
@@ -2484,16 +2501,16 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
break;
default: unreachable();
} else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_hiyear, &xs) != 1) {
- error(_("invalid ending year"));
+ error(N_("invalid ending year"));
return false;
}
if (rp->r_loyear > rp->r_hiyear) {
- error(_("starting year greater than ending year"));
+ error(N_("starting year greater than ending year"));
return false;
}
if (*typep != '\0') {
- error(_("year type \"%s\" is unsupported; use \"-\" instead"),
- typep);
+ error(N_("year type \"%s\" is unsupported; use \"-\" instead"),
+ typep);
return false;
}
/*
@@ -2526,12 +2543,12 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
if (rp->r_dycode != DC_DOM) {
*ep++ = 0;
if (*ep++ != '=') {
- error(_("invalid day of month"));
+ error(N_("invalid day of month"));
free(dp);
return false;
}
if ((lp = byword(dp, wday_names)) == NULL) {
- error(_("invalid weekday name"));
+ error(N_("invalid weekday name"));
free(dp);
return false;
}
@@ -2540,7 +2557,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
if (sscanf(ep, "%d%c", &rp->r_dayofmonth, &xs) != 1 ||
rp->r_dayofmonth <= 0 ||
(rp->r_dayofmonth > len_months[1][rp->r_month])) {
- error(_("invalid day of month"));
+ error(N_("invalid day of month"));
free(dp);
return false;
}
@@ -2722,15 +2739,15 @@ writezone(const char *const name, const char *const string, char version,
if (noise) {
if (1200 < timecnt) {
if (TZ_MAX_TIMES < timecnt)
- warning(_("reference clients mishandle"
- " more than %d transition times"),
+ warning(N_("reference clients mishandle"
+ " more than %d transition times"),
TZ_MAX_TIMES);
else
- warning(_("pre-2014 clients may mishandle"
- " more than 1200 transition times"));
+ warning(N_("pre-2014 clients may mishandle"
+ " more than 1200 transition times"));
}
if (TZ_MAX_LEAPS < leapcnt)
- warning(_("reference clients mishandle more than %d leap seconds"),
+ warning(N_("reference clients mishandle more than %d leap seconds"),
TZ_MAX_LEAPS);
}
/*
@@ -2771,16 +2788,16 @@ writezone(const char *const name, const char *const string, char version,
continue;
if (r->leapexpiry) {
if (noise)
- warning(_("%s: pre-2021b clients may mishandle"
- " leap second expiry"),
+ warning(N_("%s: pre-2021b clients may mishandle"
+ " leap second expiry"),
name);
version = '4';
}
if (0 < r->leapcount
&& leap[r->leapbase].corr != 1 && leap[r->leapbase].corr != -1) {
if (noise)
- warning(_("%s: pre-2021b clients may mishandle"
- " leap second table truncation"),
+ warning(N_("%s: pre-2021b clients may mishandle"
+ " leap second table truncation"),
name);
version = '4';
}
@@ -2828,7 +2845,7 @@ writezone(const char *const name, const char *const string, char version,
thismax = max_time;
}
if (toomanytimes)
- error(_("too many transition times"));
+ error(N_("too many transition times"));
locut = thismin < lo_time && lo_time <= thismax;
hicut = thismin <= hi_time && hi_time < thismax;
@@ -2995,8 +3012,8 @@ writezone(const char *const name, const char *const string, char version,
}
if (pass == 2 && noise && 50 < thischarcnt)
- warning(_("%s: pre-2026 reference clients mishandle"
- " more than 50 bytes of abbreviations"),
+ warning(N_("%s: pre-2026 reference clients mishandle"
+ " more than 50 bytes of abbreviations"),
name);
/* Output a LO_TIME transition if needed; see limitrange.
@@ -3081,26 +3098,21 @@ writezone(const char *const name, const char *const string, char version,
static char const *
abbroffset(char *buf, zic_t offset)
{
- char sign = '+';
- int seconds, minutes;
-
- if (offset < 0) {
- offset = -offset;
- sign = '-';
- }
-
- seconds = offset % SECSPERMIN;
- offset /= SECSPERMIN;
- minutes = offset % MINSPERHOUR;
- offset /= MINSPERHOUR;
- if (100 <= offset) {
- error(_("%%z UT offset magnitude exceeds 99:59:59"));
+ zic_t offset_lim = 100L * SECSPERHOUR;
+ if (! (-offset_lim < offset && offset < offset_lim)) {
+ error(N_("%%z UT offset magnitude exceeds 99:59:59"));
return "%z";
} else {
+ char sign = offset < 0 ? '-' : '+';
+ int_fast32_t abs_offset = offset < 0 ? -offset : offset;
+ int seconds = abs_offset % SECSPERMIN;
+ int abs_minutes_offset = abs_offset / SECSPERMIN;
+ int minutes = abs_minutes_offset % MINSPERHOUR;
+ int hours = abs_minutes_offset / MINSPERHOUR;
char *p = buf;
*p++ = sign;
- *p++ = '0' + offset / 10;
- *p++ = '0' + offset % 10;
+ *p++ = '0' + hours / 10;
+ *p++ = '0' + hours % 10;
if (minutes | seconds) {
*p++ = '0' + minutes / 10;
*p++ = '0' + minutes % 10;
@@ -3475,15 +3487,14 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
do_extend = compat < 0;
if (noise) {
if (!*envvar)
- warning("%s %s",
- _("no proleptic TZ string for zone"),
+ warning(N_("no proleptic TZ string for zone %s"),
zpfirst->z_name);
else if (compat != 0) {
/* Circa-COMPAT clients, and earlier clients, might
not work for this zone when given dates before
1970 or after 2038. */
- warning(_("%s: pre-%d clients may mishandle"
- " distant timestamps"),
+ warning(N_("%s: pre-%d clients may mishandle"
+ " distant timestamps"),
zpfirst->z_name, compat);
}
}
@@ -3528,7 +3539,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
int type;
save = zp->z_save;
doabbr(startbuf, zp, NULL, zp->z_isdst, save, false);
- type = addtype(oadd(zp->z_stdoff, save),
+ type = addtype(zp->z_stdoff + save,
startbuf, zp->z_isdst, startttisstd,
startttisut);
if (usestart) {
@@ -3600,22 +3611,22 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
r->r_filenum, r->r_linenum);
offset = r->r_todisut ? 0 : stdoff;
if (!r->r_todisstd)
- offset = oadd(offset, save);
+ offset += save;
jtime = r->r_temp;
jtime = tadd(jtime, -offset);
if (k < 0 || jtime < ktime) {
k = j;
ktime = jtime;
} else if (jtime == ktime) {
- char const *dup_rules_msg =
- _("two rules for same instant");
+ static char const dup_rules_msgid[] =
+ N_("two rules for same instant");
eats(zp->z_filenum, zp->z_linenum,
r->r_filenum, r->r_linenum);
- warning("%s", dup_rules_msg);
+ warning(dup_rules_msgid);
r = &zp->z_rules[k];
eats(zp->z_filenum, zp->z_linenum,
r->r_filenum, r->r_linenum);
- error("%s", dup_rules_msg);
+ error(dup_rules_msgid);
}
}
if (k < 0)
@@ -3624,7 +3635,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
rp->r_todo = false;
if (useuntil && ktime >= untiltime) {
if (!*startbuf
- && (oadd(zp->z_stdoff, rp->r_save)
+ && (zp->z_stdoff + rp->r_save
== startoff))
doabbr(startbuf, zp, rp->r_abbrvar,
rp->r_isdst, rp->r_save,
@@ -3636,8 +3647,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
usestart = false;
if (usestart) {
if (ktime < starttime) {
- startoff = oadd(zp->z_stdoff,
- save);
+ startoff = zp->z_stdoff + save;
doabbr(startbuf, zp,
rp->r_abbrvar,
rp->r_isdst,
@@ -3646,8 +3656,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
continue;
}
if (*startbuf == '\0'
- && startoff == oadd(zp->z_stdoff,
- save)) {
+ && startoff == (zp->z_stdoff
+ + save)) {
doabbr(startbuf,
zp,
rp->r_abbrvar,
@@ -3660,7 +3670,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
rp->r_filenum, rp->r_linenum);
doabbr(ab, zp, rp->r_abbrvar,
rp->r_isdst, rp->r_save, false);
- offset = oadd(zp->z_stdoff, rp->r_save);
+ offset = zp->z_stdoff + rp->r_save;
type = addtype(offset, ab, rp->r_isdst,
rp->r_todisstd, rp->r_todisut);
if (defaulttype < 0 && !rp->r_isdst)
@@ -3681,7 +3691,7 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
isdst, save, false);
eat(zp->z_filenum, zp->z_linenum);
if (*startbuf == '\0')
- error(_("can't determine time zone abbreviation"
+ error(N_("can't determine time zone abbreviation"
" to use just after until time"));
else {
int type = addtype(startoff, startbuf, isdst,
@@ -3784,7 +3794,7 @@ addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
/* RFC 9636 section 3.2 specifies this range for utoff. */
if (! (-TWO_31_MINUS_1 <= utoff && utoff <= TWO_31_MINUS_1)) {
- error(_("UT offset out of range"));
+ error(N_("UT offset out of range"));
exit(EXIT_FAILURE);
}
if (!want_bloat())
@@ -3813,7 +3823,7 @@ addtype(zic_t utoff, char const *abbr, bool isdst, bool ttisstd, bool ttisut)
** many.
*/
if (typecnt >= TZ_MAX_TYPES) {
- error(_("too many local time types"));
+ error(N_("too many local time types"));
exit(EXIT_FAILURE);
}
i = typecnt++;
@@ -3831,7 +3841,7 @@ leapadd(zic_t t, int correction, int rolling)
register ptrdiff_t i;
if (rolling && (lo_time != min_time || hi_time != max_time)) {
- error(_("Rolling leap seconds not supported with -r"));
+ error(N_("Rolling leap seconds not supported with -r"));
exit(EXIT_FAILURE);
}
leap = growalloc(leap, sizeof *leap, leapcnt, &leap_alloc);
@@ -3857,7 +3867,7 @@ adjleap(void)
*/
for (i = 0; i < leapcnt; ++i) {
if (leap[i].trans - prevtrans < 28 * SECSPERDAY) {
- error(_("Leap seconds too close together"));
+ error(N_("Leap seconds too close together"));
exit(EXIT_FAILURE);
}
prevtrans = leap[i].trans;
@@ -3868,7 +3878,7 @@ adjleap(void)
if (0 <= leapexpires) {
leapexpires = oadd(leapexpires, last);
if (! (leapcnt == 0 || (leap[leapcnt - 1].trans < leapexpires))) {
- error(_("last Leap time does not precede Expires time"));
+ error(N_("last Leap time does not precede Expires time"));
exit(EXIT_FAILURE);
}
}
@@ -3978,7 +3988,7 @@ byword(const char *word, const struct lookup *table)
Warn about any usage of the undocumented prefix "last-". */
if (table == lasts && ciprefix("last", word) && word[4]) {
if (word[4] == '-')
- warning(_("\"%s\" is undocumented; use \"last%s\" instead"),
+ warning(N_("\"%s\" is undocumented; use \"last%s\" instead"),
word, word + 5);
else {
word += 4;
@@ -4009,7 +4019,7 @@ byword(const char *word, const struct lookup *table)
for (lp = table; lp->l_word; lp++)
if (itsabbr(word, lp->l_word)) {
if (pre_2017c_match) {
- warning(_("\"%s\" is ambiguous in pre-2017c zic"), word);
+ warning(N_("\"%s\" is ambiguous in pre-2017c zic"), word);
break;
}
pre_2017c_match = true;
@@ -4040,7 +4050,7 @@ getfields(char *cp, char **array, int arrayelts)
if (*dp != '\0')
++dp;
else {
- error(_("Odd number of quotation marks"));
+ error(N_("Odd number of quotation marks"));
exit(EXIT_FAILURE);
}
} while (*cp && *cp != '#' && !is_space(*cp));
@@ -4048,7 +4058,7 @@ getfields(char *cp, char **array, int arrayelts)
++cp;
*dp = '\0';
if (nsubs == arrayelts) {
- error(_("Too many input fields"));
+ error(N_("Too many input fields"));
exit(EXIT_FAILURE);
}
array[nsubs++] = dstart + (*dstart == '-' && dp == dstart + 1);
@@ -4059,7 +4069,7 @@ getfields(char *cp, char **array, int arrayelts)
ATTRIBUTE_NORETURN static void
time_overflow(void)
{
- error(_("time overflow"));
+ error(N_("time overflow"));
exit(EXIT_FAILURE);
}
@@ -4128,11 +4138,11 @@ rpytime(const struct rule *rp, zic_t wantedy)
y = EPOCH_YEAR;
/* dayoff = floor((wantedy - y) / YEARSPERREPEAT) * DAYSPERREPEAT,
- sans overflow. */
+ checking for overflow. */
yrem = wantedy % YEARSPERREPEAT - y % YEARSPERREPEAT;
- dayoff = ((wantedy / YEARSPERREPEAT - y / YEARSPERREPEAT
- + yrem / YEARSPERREPEAT - (yrem % YEARSPERREPEAT < 0))
- * DAYSPERREPEAT);
+ dayoff = omul ((wantedy / YEARSPERREPEAT - y / YEARSPERREPEAT
+ + yrem / YEARSPERREPEAT - (yrem % YEARSPERREPEAT < 0)),
+ DAYSPERREPEAT);
/* wantedy = y + ((wantedy - y) mod YEARSPERREPEAT), sans overflow. */
wantedy = y + (yrem + 2 * YEARSPERREPEAT) % YEARSPERREPEAT;
@@ -4151,7 +4161,7 @@ rpytime(const struct rule *rp, zic_t wantedy)
if (rp->r_dycode == DC_DOWLEQ)
--i;
else {
- error(_("use of 2/29 in non leap-year"));
+ error(N_("use of 2/29 in non leap-year"));
exit(EXIT_FAILURE);
}
}
@@ -4177,8 +4187,9 @@ rpytime(const struct rule *rp, zic_t wantedy)
}
if (i < 0 || i >= len_months[isleap(y)][m]) {
if (noise)
- warning(_("rule goes past start/end of month; \
-will not work with pre-2004 versions of zic"));
+ warning(N_("rule goes past start/end of month;"
+ " will not work with pre-2004"
+ " versions of zic"));
}
}
t = omul(dayoff, SECSPERDAY);
@@ -4198,13 +4209,13 @@ checkabbr(char const *string)
|| *cp == '-' || *cp == '+')
++cp;
if (noise && cp - string < 3)
- mp = _("time zone abbreviation has fewer than 3 characters");
+ mp = N_("time zone abbreviation has fewer than 3 characters");
if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN)
- mp = _("time zone abbreviation has too many characters");
+ mp = N_("time zone abbreviation has too many characters");
if (*cp != '\0')
-mp = _("time zone abbreviation differs from POSIX standard");
+ mp = N_("time zone abbreviation differs from POSIX standard");
if (mp != NULL)
- warning("%s (%s)", mp, string);
+ warning(N_("%s (%s)"), _(mp), string);
}
}
@@ -4243,7 +4254,7 @@ addabbr(char chs[TZ_MAX_CHARS], int *pnchs, char const *abbr)
i += clen + 1;
}
if (TZ_MAX_CHARS < nchs + nchs_incr) {
- error(_("too many, or too long, time zone abbreviations"));
+ error(N_("too many, or too long, time zone abbreviations"));
exit(EXIT_FAILURE);
}
memmove(&chs[i + nchs_incr], &chs[i], nchs - i);
@@ -4301,7 +4312,7 @@ mkdirs(char const *argname, bool ancestors)
int err = errno;
if (err == ELOOP || err == ENAMETOOLONG
|| err == ENOENT || err == ENOTDIR) {
- error(_("%s: Can't create directory %s: %s"),
+ error(N_("%s: Can't create directory %s: %s"),
progname, name, strerror(err));
exit(EXIT_FAILURE);
}