Module Name: src
Committed By: christos
Date: Tue Apr 28 17:00:24 UTC 2015
Modified Files:
src/lib/libc/time: Makefile NEWS private.h tz-link.htm zic.c
Removed Files:
src/lib/libc/time: ialloc.c scheck.c
Log Message:
welcome to tzcode 2015d (zic performance improvements and cleanups)
To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/lib/libc/time/Makefile
cvs rdiff -u -r1.10 -r1.11 src/lib/libc/time/NEWS
cvs rdiff -u -r1.9 -r0 src/lib/libc/time/ialloc.c
cvs rdiff -u -r1.39 -r1.40 src/lib/libc/time/private.h
cvs rdiff -u -r1.12 -r0 src/lib/libc/time/scheck.c
cvs rdiff -u -r1.21 -r1.22 src/lib/libc/time/tz-link.htm
cvs rdiff -u -r1.52 -r1.53 src/lib/libc/time/zic.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libc/time/Makefile
diff -u src/lib/libc/time/Makefile:1.27 src/lib/libc/time/Makefile:1.28
--- src/lib/libc/time/Makefile:1.27 Tue Mar 24 16:01:18 2015
+++ src/lib/libc/time/Makefile Tue Apr 28 13:00:24 2015
@@ -5,7 +5,7 @@
PACKAGE= tzcode
# Version numbers of the code and data distributions.
-VERSION= 2015b
+VERSION= 2015d
# Email address for bug reports.
BUGEMAIL= [email protected]
@@ -120,6 +120,7 @@ LDLIBS=
# -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h"
# -DHAVE_STRFTIME_L=1 if <time.h> declares locale_t and strftime_l
# This defaults to 0 if _POSIX_VERSION < 200809, 1 otherwise.
+# -DHAVE_STRDUP=0 if your system lacks the strdup function
# -DHAVE_SYMLINK=0 if your system lacks the symlink function
# -DHAVE_SYS_STAT_H=0 if your compiler lacks a "sys/stat.h"
# -DHAVE_SYS_WAIT_H=0 if your compiler lacks a "sys/wait.h"
@@ -150,18 +151,18 @@ LDLIBS=
# $(GCC_DEBUG_FLAGS) if you are using GCC and want lots of checking
GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-common -fstrict-aliasing \
-Wall -Wextra \
- -Wbad-function-cast -Wcast-align -Wcast-qual \
+ -Wbad-function-cast -Wcast-align -Wdate-time \
-Wdeclaration-after-statement \
+ -Wdouble-promotion \
-Wformat=2 -Winit-self -Wjump-misses-init \
- -Wmissing-declarations -Wmissing-noreturn -Wmissing-prototypes \
- -Wnested-externs -Wno-address -Wno-cast-qual \
- -Wno-format-nonliteral -Wno-sign-compare -Wno-sign-conversion \
- -Wno-type-limits \
- -Wno-unused-parameter -Woverlength-strings -Wpointer-arith \
+ -Wlogical-op -Wmissing-prototypes -Wnested-externs \
+ -Wold-style-definition -Woverlength-strings -Wpointer-arith \
-Wshadow -Wstrict-prototypes -Wsuggest-attribute=const \
-Wsuggest-attribute=format -Wsuggest-attribute=noreturn \
-Wsuggest-attribute=pure -Wtrampolines \
- -Wwrite-strings
+ -Wunused -Wwrite-strings \
+ -Wno-address -Wno-format-nonliteral -Wno-sign-compare \
+ -Wno-type-limits -Wno-unused-parameter
#
# If you want to use System V compatibility code, add
# -DUSG_COMPAT
@@ -331,13 +332,13 @@ AR= ar
# ':' on typical hosts; 'ranlib' on the ancient hosts that still need ranlib.
RANLIB= :
-TZCOBJS= zic.o scheck.o ialloc.o
+TZCOBJS= zic.o
TZDOBJS= zdump.o localtime.o asctime.o
DATEOBJS= date.o localtime.o strftime.o asctime.o
LIBSRCS= localtime.c asctime.c difftime.c
LIBOBJS= localtime.o asctime.o difftime.o
HEADERS= tzfile.h private.h
-NONLIBSRCS= zic.c zdump.c scheck.c ialloc.c
+NONLIBSRCS= zic.c zdump.c
NEWUCBSRCS= date.c strftime.c
SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) \
tzselect.ksh workman.sh
@@ -655,9 +656,7 @@ zonenames: $(TDATA)
asctime.o: private.h tzfile.h
date.o: private.h
difftime.o: private.h
-ialloc.o: private.h
localtime.o: private.h tzfile.h
-scheck.o: private.h
strftime.o: private.h tzfile.h
zdump.o: version.h
zic.o: private.h tzfile.h version.h
Index: src/lib/libc/time/NEWS
diff -u src/lib/libc/time/NEWS:1.10 src/lib/libc/time/NEWS:1.11
--- src/lib/libc/time/NEWS:1.10 Tue Mar 24 16:01:18 2015
+++ src/lib/libc/time/NEWS Tue Apr 28 13:00:24 2015
@@ -1,5 +1,79 @@
News for the tz database
+Release 2015d - 2015-04-24 08:09:46 -0700
+
+ Changes affecting future time stamps
+
+ Egypt will not observe DST in 2015 and will consider canceling it
+ permanently. For now, assume no DST indefinitely.
+ (Thanks to Ahmed Nazmy and Tim Parenti.)
+
+ Changes affecting past time stamps
+
+ America/Whitehorse switched from UTC-9 to UTC-8 on 1967-05-28, not
+ 1966-07-01. Also, Yukon's time zone history is documented better.
+ (Thanks to Brian Inglis and Dennis Ferguson.)
+
+ Change affecting past and future time zone abbreviations
+
+ The abbreviations for Hawaii-Aleutian standard and daylight times
+ have been changed from HAST/HADT to HST/HDT, as per US Government
+ Printing Office style. This affects only America/Adak since 1983,
+ as America/Honolulu was already using the new style.
+
+ Changes affecting code
+
+ zic has some minor performance improvements.
+
+
+Release 2015c - 2015-04-11 08:55:55 -0700
+
+ Changes affecting future time stamps
+
+ Egypt's spring-forward transition is at 24:00 on April's last Thursday,
+ not 00:00 on April's last Friday. 2015's transition will therefore be on
+ Thursday, April 30 at 24:00, not Friday, April 24 at 00:00. Similar fixes
+ apply to 2026, 2037, 2043, etc. (Thanks to Steffen Thorsen.)
+
+ Changes affecting past time stamps
+
+ The following changes affect some pre-1991 Chile-related time stamps
+ in America/Santiago, Antarctica/Palmer, and Pacific/Easter.
+
+ The 1910 transition was January 10, not January 1.
+
+ The 1918 transition was September 10, not September 1.
+
+ The UTC-4 time observed from 1932 to 1942 is now considered to be
+ standard time, not year-round DST.
+
+ Santiago observed DST (UTC-3) from 1946-07-15 through 1946-08-31,
+ then reverted to standard time, then switched its time zone to
+ UTC-5 on 1947-04-01.
+
+ Assume transitions before 1968 were at 00:00, since we have no data
+ saying otherwise.
+
+ The spring 1988 transition was 1988-10-09, not 1988-10-02.
+ The fall 1990 transition was 1990-03-11, not 1990-03-18.
+
+ Assume no UTC offset change for Pacific/Easter on 1890-01-01,
+ and omit all transitions on Pacific/Easter from 1942 through 1946
+ since we have no data suggesting that they existed.
+
+ One more zone has been turned into a link, as it differed
+ from an existing zone only for older time stamps. As usual,
+ this change affects UTC offsets in pre-1970 time stamps only.
+ The zone's old contents have been moved to the 'backzone' file.
+ The affected zone is America/Montreal.
+
+ Changes affecting commentary
+
+ Mention the TZUpdater tool.
+
+ Mention "The Time Now". (Thanks to Brandon Ramsey.)
+
+
Release 2015b - 2015-03-19 23:28:11 -0700
Changes affecting future time stamps
Index: src/lib/libc/time/private.h
diff -u src/lib/libc/time/private.h:1.39 src/lib/libc/time/private.h:1.40
--- src/lib/libc/time/private.h:1.39 Tue Mar 24 16:01:18 2015
+++ src/lib/libc/time/private.h Tue Apr 28 13:00:24 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: private.h,v 1.39 2015/03/24 20:01:18 christos Exp $ */
+/* $NetBSD: private.h,v 1.40 2015/04/28 17:00:24 christos Exp $ */
#ifndef PRIVATE_H
#define PRIVATE_H
@@ -54,6 +54,10 @@
#define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */
+#ifndef HAVE_STRDUP
+#define HAVE_STRDUP 1
+#endif
+
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
@@ -467,14 +471,6 @@ time_t time2posix_z(timezone_t __restric
#endif
/*
-** Private function declarations.
-*/
-
-char * icatalloc(char * old, const char * new);
-char * icpyalloc(const char * string);
-const char * scheck(const char * string, const char * format);
-
-/*
** Finally, some convenience items.
*/
Index: src/lib/libc/time/tz-link.htm
diff -u src/lib/libc/time/tz-link.htm:1.21 src/lib/libc/time/tz-link.htm:1.22
--- src/lib/libc/time/tz-link.htm:1.21 Sat Jan 31 13:55:17 2015
+++ src/lib/libc/time/tz-link.htm Tue Apr 28 13:00:24 2015
@@ -8,7 +8,7 @@
<meta http-equiv="Content-type" content='text/html; charset="UTF-8"'>
<meta name="DC.Creator" content="Eggert, Paul">
<meta name="DC.Contributor" content="Olson, Arthur David">
-<meta name="DC.Date" content="2015-01-29">
+<meta name="DC.Date" content="2015-03-25">
<meta name="DC.Description"
content="Sources of information about time zones and daylight saving time">
<meta name="DC.Identifier"
@@ -194,6 +194,7 @@ multiple time zones.</li>
<li><a href="http://www.zeitverschiebung.net/en/">Time Difference</a>
calculates the current time difference between locations.</li>
<li><a href="http://www.wx-now.com">Weather Now</a> lists the weather too.</li>
+<li><a href="http://www.thetimenow.com">The Time Now</a> also lists weather.</li>
<li><a href="http://worldtime.io">worldtime.io</a>
also contains data about time zone boundaries; it supports queries via place
names and shows location maps.</li>
@@ -282,6 +283,10 @@ and from <abbr title="Common Locale Data
into an <abbr>ICU</abbr>-specific format.
<abbr>ICU</abbr> is freely available under a
<abbr>BSD</abbr>-style license.</li>
+<li>The <a
+href="http://www.oracle.com/technetwork/java/javase/tzupdater-readme-136440.html">TZUpdater
+tool</a> compiles <code><abbr>tz</abbr></code> source into the format used by
+Oracle Java.</li>
<li><a href="http://www.joda.org/joda-time/">Joda-Time – Java date
and time <abbr title="Application Program Interface">API</abbr></a>
contains a class
Index: src/lib/libc/time/zic.c
diff -u src/lib/libc/time/zic.c:1.52 src/lib/libc/time/zic.c:1.53
--- src/lib/libc/time/zic.c:1.52 Tue Oct 7 18:14:46 2014
+++ src/lib/libc/time/zic.c Tue Apr 28 13:00:24 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: zic.c,v 1.52 2014/10/07 22:14:46 christos Exp $ */
+/* $NetBSD: zic.c,v 1.53 2015/04/28 17:00:24 christos Exp $ */
/*
** This file is in the public domain, so clarified as of
** 2006-07-17 by Arthur David Olson.
@@ -10,7 +10,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: zic.c,v 1.52 2014/10/07 22:14:46 christos Exp $");
+__RCSID("$NetBSD: zic.c,v 1.53 2015/04/28 17:00:24 christos Exp $");
#endif /* !defined lint */
#include "private.h"
@@ -41,8 +41,6 @@ typedef int_fast64_t zic_t;
#define MKDIR_UMASK 0755
#endif
-#define end(cp) (strchr((cp), '\0'))
-
struct rule {
const char * r_filename;
int r_linenum;
@@ -381,18 +379,40 @@ size_product(size_t nitems, size_t items
return nitems * itemsize;
}
+#if !HAVE_STRDUP
+static char *
+strdup(char const *str)
+{
+ char *result = malloc(strlen(str) + 1);
+ return result ? strcpy(result, str) : result;
+}
+#endif
+
static ATTRIBUTE_PURE void *
-memcheck(void *const ptr)
+memcheck(void *ptr)
{
if (ptr == NULL)
memory_exhausted(strerror(errno));
return ptr;
}
-#define emalloc(size) memcheck(malloc(size))
-#define erealloc(ptr, size) memcheck(realloc((ptr), (size)))
-#define ecpyalloc(ptr) memcheck(icpyalloc(ptr))
-#define ecatalloc(oldp, newp) memcheck(icatalloc((oldp), (newp)))
+static void *
+zic_malloc(size_t size)
+{
+ return memcheck(malloc(size));
+}
+
+static void *
+zic_realloc(void *ptr, size_t size)
+{
+ return memcheck(realloc(ptr, size));
+}
+
+static char *
+ecpyalloc(char const *str)
+{
+ return memcheck(strdup(str));
+}
static void *
growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
@@ -404,7 +424,7 @@ growalloc(void *ptr, size_t itemsize, in
if ((amax - 1) / 3 * 2 < *nitems_alloc)
memory_exhausted(_("int overflow"));
*nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
- return erealloc(ptr, size_product(*nitems_alloc, itemsize));
+ return zic_realloc(ptr, size_product(*nitems_alloc, itemsize));
}
}
@@ -647,6 +667,11 @@ componentcheck(char const *name, char co
{
enum { component_len_max = 14 };
size_t component_len = component_end - component;
+ if (component_len == 0) {
+ fprintf(stderr, _("%s: file name '%s' contains empty component"),
+ progname, name);
+ exit(EXIT_FAILURE);
+ }
if (0 < component_len && component_len <= 2
&& component[0] == '.' && component_end[-1] == '.') {
fprintf(stderr, _("%s: file name '%s' contains"
@@ -699,6 +724,21 @@ namecheck(const char *name)
componentcheck(name, component, cp);
}
+static char *
+relname(char const *dir, char const *base)
+{
+ if (*base == '/')
+ return ecpyalloc(base);
+ else {
+ size_t dir_len = strlen(dir);
+ bool needs_slash = dir_len && dir[dir_len - 1] != '/';
+ char *result = zic_malloc(dir_len + needs_slash + strlen(base) + 1);
+ result[dir_len] = '/';
+ strcpy(result + dir_len + needs_slash, base);
+ return memcpy(result, dir, dir_len);
+ }
+}
+
static void
dolink(const char *const fromfield, const char *const tofield)
{
@@ -707,20 +747,8 @@ dolink(const char *const fromfield, cons
int fromisdir;
namecheck(tofield);
- if (fromfield[0] == '/')
- fromname = ecpyalloc(fromfield);
- else {
- fromname = ecpyalloc(directory);
- fromname = ecatalloc(fromname, "/");
- fromname = ecatalloc(fromname, fromfield);
- }
- if (tofield[0] == '/')
- toname = ecpyalloc(tofield);
- else {
- toname = ecpyalloc(directory);
- toname = ecatalloc(toname, "/");
- toname = ecatalloc(toname, tofield);
- }
+ fromname = relname(directory, fromfield);
+ toname = relname(directory, tofield);
/*
** We get to be careful here since
** there's a fair chance of root running us.
@@ -744,6 +772,8 @@ dolink(const char *const fromfield, cons
if (result != 0) {
const char *s = fromfield;
const char *t;
+ char *p;
+ size_t dotdots = 0;
char * symlinkcontents = NULL;
do
@@ -752,16 +782,16 @@ dolink(const char *const fromfield, cons
&& ! strncmp (fromfield, tofield,
++s - fromfield));
- for (s = tofield + (t - fromfield);
- (s = strchr(s, '/'));
- s++)
- symlinkcontents =
- ecatalloc(symlinkcontents,
- "../");
- symlinkcontents = ecatalloc(symlinkcontents, t);
+ for (s = tofield + (t - fromfield); *s; s++)
+ dotdots += *s == '/';
+ symlinkcontents
+ = zic_malloc(3 * dotdots + strlen(t) + 1);
+ for (p = symlinkcontents; dotdots-- != 0; p += 3)
+ memcpy(p, "../", 3);
+ strcpy(p, t);
result = symlink(symlinkcontents, toname);
if (result == 0)
-warning(_("hard link failed, symbolic link used"));
+ warning(_("hard link failed, symbolic link used"));
free(symlinkcontents);
}
if (result != 0) {
@@ -841,7 +871,7 @@ itsdir(const char *const name)
return S_ISDIR(st.st_mode) != 0;
#else
{
- char *nameslashdot = ecatalloc(ecpyalloc(name), "/.");
+ char *nameslashdot = relname(name, ".");
res = stat(nameslashdot, &st);
free(nameslashdot);
return res == 0;
@@ -1036,6 +1066,7 @@ gethms(char const *string, char const *e
{
zic_t hh;
int mm, ss, sign;
+ char xs;
if (string == NULL || *string == '\0')
return 0;
@@ -1045,12 +1076,12 @@ gethms(char const *string, char const *e
sign = -1;
++string;
} else sign = 1;
- if (sscanf(string, scheck(string, "%"SCNdZIC), &hh) == 1)
+ if (sscanf(string, "%"SCNdZIC"%c", &hh, &xs) == 1)
mm = ss = 0;
- else if (sscanf(string, scheck(string, "%"SCNdZIC":%d"), &hh, &mm) == 2)
+ else if (sscanf(string, "%"SCNdZIC":%d%c", &hh, &mm, &xs) == 2)
ss = 0;
- else if (sscanf(string, scheck(string, "%"SCNdZIC":%d:%d"),
- &hh, &mm, &ss) != 3) {
+ else if (sscanf(string, "%"SCNdZIC":%d:%d%c", &hh, &mm, &ss, &xs)
+ != 3) {
error("%s", errstring);
return 0;
}
@@ -1228,6 +1259,7 @@ inleap(char **const fields, const int nf
int month, day;
zic_t dayoff, tod;
zic_t t;
+ char xs;
if (nfields != LEAP_FIELDS) {
error(_("wrong number of fields on Leap line"));
@@ -1235,7 +1267,7 @@ inleap(char **const fields, const int nf
}
dayoff = 0;
cp = fields[LP_YEAR];
- if (sscanf(cp, scheck(cp, "%"SCNdZIC), &year) != 1) {
+ if (sscanf(cp, "%"SCNdZIC"%c", &year, &xs) != 1) {
/*
** Leapin' Lizards!
*/
@@ -1270,7 +1302,7 @@ inleap(char **const fields, const int nf
++j;
}
cp = fields[LP_DAY];
- if (sscanf(cp, scheck(cp, "%d"), &day) != 1 ||
+ if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
day <= 0 || day > len_months[isleap(year)][month]) {
error(_("invalid day of month"));
return;
@@ -1356,6 +1388,7 @@ rulesub(struct rule *const rp, const cha
const char * cp;
char * dp;
char * ep;
+ char xs;
if ((lp = byword(monthp, mon_names)) == NULL) {
error(_("invalid month name"));
@@ -1407,7 +1440,7 @@ rulesub(struct rule *const rp, const cha
_("%s: panic: Invalid l_value %d\n"),
progname, lp->l_value);
exit(EXIT_FAILURE);
- } else if (sscanf(cp, scheck(cp, "%"SCNdZIC), &rp->r_loyear) != 1) {
+ } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) {
error(_("invalid starting year"));
return;
}
@@ -1429,7 +1462,7 @@ rulesub(struct rule *const rp, const cha
_("%s: panic: Invalid l_value %d\n"),
progname, lp->l_value);
exit(EXIT_FAILURE);
- } else if (sscanf(cp, scheck(cp, "%"SCNdZIC), &rp->r_hiyear) != 1) {
+ } else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_hiyear, &xs) != 1) {
error(_("invalid ending year"));
return;
}
@@ -1482,7 +1515,7 @@ rulesub(struct rule *const rp, const cha
}
rp->r_wday = lp->l_value;
}
- if (sscanf(ep, scheck(ep, "%d"), &rp->r_dayofmonth) != 1 ||
+ 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"));
@@ -1556,10 +1589,10 @@ writezone(const char *const name, const
int leapcnt32, leapi32;
int timecnt32, timei32;
int pass;
- static char * fullname;
+ char * fullname;
static const struct tzhead tzh0;
static struct tzhead tzh;
- zic_t *ats = emalloc(size_product(timecnt, sizeof *ats + 1));
+ zic_t *ats = zic_malloc(size_product(timecnt, sizeof *ats + 1));
void *typesptr = ats + timecnt;
unsigned char *types = typesptr;
@@ -1643,9 +1676,7 @@ writezone(const char *const name, const
--leapcnt32;
++leapi32;
}
- fullname = erealloc(fullname,
- strlen(directory) + 1 + strlen(name) + 1);
- (void) sprintf(fullname, "%s/%s", directory, name); /* XXX: sprintf is safe */
+ fullname = relname(directory, name);
/*
** Remove old file, if any, to snap links.
*/
@@ -1864,15 +1895,16 @@ writezone(const char *const name, const
(void) fprintf(fp, "\n%s\n", string);
close_file(fp, fullname);
free(ats);
+ free(fullname);
}
-static void
+static size_t
doabbr(char *const abbr, const int abbrlen, const char *const format,
const char *const letters, bool isdst, bool doquotes)
{
char * cp;
char * slashp;
- int len;
+ size_t len;
slashp = strchr(format, '/');
if (slashp == NULL) {
@@ -1885,18 +1917,18 @@ doabbr(char *const abbr, const int abbrl
(void) memcpy(abbr, format, slashp - format);
abbr[slashp - format] = '\0';
}
+ len = strlen(abbr);
if (!doquotes)
- return;
+ return len;
for (cp = abbr; is_alpha(*cp); cp++)
continue;
- len = strlen(abbr);
if (len > 0 && *cp == '\0')
- return;
+ return len;
abbr[len + 2] = '\0';
abbr[len + 1] = '>';
- for ( ; len > 0; --len)
- abbr[len] = abbr[len - 1];
+ memmove(abbr + 1, abbr, len);
abbr[0] = '<';
+ return len + 2;
}
static void
@@ -1908,17 +1940,18 @@ updateminmax(const zic_t x)
max_year = x;
}
-static bool
+static int
stringoffset(char *result, zic_t offset)
{
int hours;
int minutes;
int seconds;
+ bool negative = offset < 0;
+ int len = negative;
- result[0] = '\0';
- if (offset < 0) {
- strcpy(result, "-");
+ if (negative) {
offset = -offset;
+ result[0] = '-';
}
seconds = offset % SECSPERMIN;
offset /= SECSPERMIN;
@@ -1927,15 +1960,15 @@ stringoffset(char *result, zic_t offset)
hours = offset;
if (hours >= HOURSPERDAY * DAYSPERWEEK) {
result[0] = '\0';
- return false;
+ return 0;
}
- sprintf(end(result), "%d", hours);
+ len += sprintf(result + len, "%d", hours);
if (minutes != 0 || seconds != 0) {
- sprintf(end(result), ":%02d", minutes);
+ len += sprintf(result + len, ":%02d", minutes);
if (seconds != 0)
- sprintf(end(result), ":%02d", seconds);
+ len += sprintf(result + len, ":%02d", seconds);
}
- return true;
+ return len;
}
static int
@@ -1945,7 +1978,6 @@ stringrule(char *result, const struct ru
zic_t tod = rp->r_tod;
int compat = 0;
- result = end(result);
if (rp->r_dycode == DC_DOM) {
int month, total;
@@ -1956,9 +1988,9 @@ stringrule(char *result, const struct ru
total += len_months[0][month];
/* Omit the "J" in Jan and Feb, as that's shorter. */
if (rp->r_month <= 1)
- sprintf(result, "%d", total + rp->r_dayofmonth - 1);
+ result += sprintf(result, "%d", total + rp->r_dayofmonth - 1);
else
- sprintf(result, "J%d", total + rp->r_dayofmonth);
+ result += sprintf(result, "J%d", total + rp->r_dayofmonth);
} else {
int week;
int wday = rp->r_wday;
@@ -1985,16 +2017,16 @@ stringrule(char *result, const struct ru
} else return -1; /* "cannot happen" */
if (wday < 0)
wday += DAYSPERWEEK;
- sprintf(result, "M%d.%d.%d",
- rp->r_month + 1, week, wday);
+ result += sprintf(result, "M%d.%d.%d",
+ rp->r_month + 1, week, wday);
}
if (rp->r_todisgmt)
tod += gmtoff;
if (rp->r_todisstd && rp->r_stdoff == 0)
tod += dstoff;
if (tod != 2 * SECSPERMIN * MINSPERHOUR) {
- strcat(result, "/");
- if (! stringoffset(end(result), tod))
+ *result++ = '/';
+ if (! stringoffset(result, tod))
return -1;
if (tod < 0) {
if (compat < 2013)
@@ -2035,6 +2067,8 @@ stringzone(char *result, const int resul
const char * abbrvar;
int compat = 0;
int c;
+ size_t len;
+ int offsetlen;
struct rule stdr, dstr;
result[0] = '\0';
@@ -2102,31 +2136,37 @@ stringzone(char *result, const int resul
if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0))
return -1;
abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar;
- doabbr(result, resultlen, zp->z_format, abbrvar, false, true);
- if (! stringoffset(end(result), -zp->z_gmtoff)) {
+ len = doabbr(result, resultlen, zp->z_format, abbrvar, false, true);
+ offsetlen = stringoffset(result + len, -zp->z_gmtoff);
+ if (! offsetlen) {
result[0] = '\0';
return -1;
}
+ len += offsetlen;
if (dstrp == NULL)
return compat;
- doabbr(end(result), resultlen - strlen(result),
- zp->z_format, dstrp->r_abbrvar, true, true);
- if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR)
- if (! stringoffset(end(result),
- -(zp->z_gmtoff + dstrp->r_stdoff))) {
+ len += doabbr(result + len, resultlen - len, zp->z_format,
+ dstrp->r_abbrvar, true, true);
+ if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) {
+ offsetlen = stringoffset(result + len,
+ -(zp->z_gmtoff + dstrp->r_stdoff));
+ if (! offsetlen) {
result[0] = '\0';
return -1;
}
- (void) strcat(result, ",");
- c = stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff);
+ len += offsetlen;
+ }
+ result[len++] = ',';
+ c = stringrule(result + len, dstrp, dstrp->r_stdoff, zp->z_gmtoff);
if (c < 0) {
result[0] = '\0';
return -1;
}
if (compat < c)
compat = c;
- strcat(result, ",");
- c = stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff);
+ len += strlen(result + len);
+ result[len++] = ',';
+ c = stringrule(result + len, stdrp, dstrp->r_stdoff, zp->z_gmtoff);
if (c < 0) {
result[0] = '\0';
return -1;
@@ -2163,9 +2203,9 @@ outzone(const struct zone *const zpfirst
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
max_envvar_len = 2 * max_abbr_len + 5 * 9;
- startbuf = emalloc(max_abbr_len + 1);
- ab = emalloc(max_abbr_len + 1);
- envvar = emalloc(max_envvar_len + 1);
+ startbuf = zic_malloc(max_abbr_len + 1);
+ ab = zic_malloc(max_abbr_len + 1);
+ envvar = zic_malloc(max_envvar_len + 1);
INITIALIZE(untiltime);
INITIALIZE(starttime);
/*
@@ -2582,7 +2622,7 @@ yearistype(const int year, const char *c
if (type == NULL || *type == '\0')
return true;
- buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type));
+ buf = zic_realloc(buf, 132 + strlen(yitcommand) + strlen(type));
(void)sprintf(buf, "%s %d %s", yitcommand, year, type); /* XXX: sprintf is safe */
result = system(buf);
if (WIFEXITED(result)) switch (WEXITSTATUS(result)) {
@@ -2708,7 +2748,7 @@ getfields(char *cp)
if (cp == NULL)
return NULL;
- array = emalloc(size_product(strlen(cp) + 1, sizeof *array));
+ array = zic_malloc(size_product(strlen(cp) + 1, sizeof *array));
nsubs = 0;
for ( ; ; ) {
while (is_space(*cp))
@@ -2737,26 +2777,36 @@ getfields(char *cp)
return array;
}
+static _Noreturn void
+time_overflow(void)
+{
+ error(_("time overflow"));
+ exit(EXIT_FAILURE);
+}
+
static ATTRIBUTE_PURE zic_t
oadd(const zic_t t1, const zic_t t2)
{
- if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2) {
- error(_("time overflow"));
- exit(EXIT_FAILURE);
- }
+ if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2)
+ time_overflow();
return t1 + t2;
}
static ATTRIBUTE_PURE zic_t
tadd(const zic_t t1, const zic_t t2)
{
- if (t1 == max_time && t2 > 0)
- return max_time;
- if (t1 == min_time && t2 < 0)
- return min_time;
- if (t1 < 0 ? t2 < min_time - t1 : max_time - t1 < t2) {
- error(_("time overflow"));
- exit(EXIT_FAILURE);
+ if (t1 < 0) {
+ if (t2 < min_time - t1) {
+ if (t1 != min_time)
+ time_overflow();
+ return min_time;
+ }
+ } else {
+ if (max_time - t1 < t2) {
+ if (t1 != max_time)
+ time_overflow();
+ return max_time;
+ }
}
return t1 + t2;
}