Module Name:    src
Committed By:   christos
Date:           Sun Jun 21 16:06:51 UTC 2015

Modified Files:
        src/lib/libc/time: Makefile NEWS localtime.c private.h tzselect.ksh
            zdump.c zic.8 zic.c

Log Message:
merge tzcode2015e:

  Changes affecting code

    When displaying data, tzselect converts it to the current locale's
    encoding if the iconv command works.  (Problem reported by random832.)

    tzselect no longer mishandles Dominica, fixing a bug introduced
    in Release 2014f.  (Problem reported by Owen Leibman.)

    zic -l no longer fails when compiled with -DTZDEFAULT=\"/etc/localtime\".
    This fixes a bug introduced in Release 2014f.
    (Problem reported by Leonardo Chiquitto.)


To generate a diff of this commit:
cvs rdiff -u -r1.28 -r1.29 src/lib/libc/time/Makefile
cvs rdiff -u -r1.11 -r1.12 src/lib/libc/time/NEWS
cvs rdiff -u -r1.94 -r1.95 src/lib/libc/time/localtime.c
cvs rdiff -u -r1.40 -r1.41 src/lib/libc/time/private.h \
    src/lib/libc/time/zdump.c
cvs rdiff -u -r1.13 -r1.14 src/lib/libc/time/tzselect.ksh
cvs rdiff -u -r1.24 -r1.25 src/lib/libc/time/zic.8
cvs rdiff -u -r1.53 -r1.54 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.28 src/lib/libc/time/Makefile:1.29
--- src/lib/libc/time/Makefile:1.28	Tue Apr 28 13:00:24 2015
+++ src/lib/libc/time/Makefile	Sun Jun 21 12:06:51 2015
@@ -5,7 +5,7 @@
 PACKAGE=	tzcode
 
 # Version numbers of the code and data distributions.
-VERSION=	2015d
+VERSION=	2015e
 
 # Email address for bug reports.
 BUGEMAIL=	t...@iana.org
@@ -293,23 +293,24 @@ TAB_CHAR=	'	'
 SAFE_CHARSET1=	$(TAB_CHAR)' !\"'$$sharp'$$%&'\''()*+,./0123456789:;<=>?@'
 SAFE_CHARSET2=	'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\^_`'
 SAFE_CHARSET3=	'abcdefghijklmnopqrstuvwxyz{|}~'
-SAFE_CHARSET=	]$(SAFE_CHARSET1)$(SAFE_CHARSET2)$(SAFE_CHARSET3)-
-SAFE_CHAR=	'['$(SAFE_CHARSET)']'
-# NONSYM_CHAR is a regular expression that matches any character
-# except for a small number of symbols, where we prefer to stick with
+SAFE_CHARSET=	$(SAFE_CHARSET1)$(SAFE_CHARSET2)$(SAFE_CHARSET3)
+SAFE_CHAR=	'[]'$(SAFE_CHARSET)'-]'
+
+# OK_CHAR matches any character allowed in the distributed files.
+# This is the same as SAFE_CHAR, except that multibyte letters are
+# also allowed so that commentary can contain people's names and quote
+# non-English sources.  For non-letters the sources are limited to
 # ASCII renderings for the convenience of maintainers whose text editors
 # mishandle UTF-8 by default (e.g., XEmacs 21.4.22).
-NONSYM_CHAR=	'[^–—°′″≈≠≤≥±−×÷∞←→↔·•§¶«»‘’‚‛“”„‟‹›「」『』〝〞〟]'
+OK_CHAR=	'[][:alpha:]'$(SAFE_CHARSET)'-]'
 
 # SAFE_LINE matches a line of safe characters.
-# SAFE_SHARP_LINE is similar, except any character can follow '#';
+# SAFE_SHARP_LINE is similar, except any OK character can follow '#';
 # this is so that comments can contain non-ASCII characters.
-# NONSYM_LINE matches a line of non-symbols.
-# VALID_LINE matches a line of any validly-encoded characters.
+# OK_LINE matches a line of OK characters.
 SAFE_LINE=	'^'$(SAFE_CHAR)'*$$'
-SAFE_SHARP_LINE='^'$(SAFE_CHAR)'*('$$sharp$(NONSYM_CHAR)'*)?$$'
-NONSYM_LINE=	'^'$(NONSYM_CHAR)'*$$'
-VALID_LINE=	'^.*$$'
+SAFE_SHARP_LINE='^'$(SAFE_CHAR)'*('$$sharp$(OK_CHAR)'*)?$$'
+OK_LINE=	'^'$(OK_CHAR)'*$$'
 
 # Flags to give 'tar' when making a distribution.
 # Try to use flags appropriate for GNU tar.
@@ -324,6 +325,8 @@ GZIPFLAGS=	-9 ${GZIP_N_FLAG}
 
 ###############################################################################
 
+#MAKE=		make
+
 cc=		cc
 CC=		$(cc) -DTZDIR=\"$(TZDIR)\"
 
@@ -372,7 +375,7 @@ SHELL=		/bin/sh
 
 all:		tzselect zic zdump libtz.a $(TABDATA)
 
-ALL:		all date
+ALL:		all date $(ENCHILADA)
 
 install:	all $(DATA) $(REDO) $(MANS)
 		mkdir -p $(DESTDIR)$(ETCDIR) $(DESTDIR)$(TZDIR) \
@@ -476,14 +479,11 @@ check:		check_character_set check_white_
 check_character_set: $(ENCHILADA)
 		LC_ALL=en_US.utf8 && export LC_ALL && \
 		sharp='#' && \
-		! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \
+		! grep -Env $(SAFE_LINE) Makefile $(MANS) date.1 $(MANTXTS) \
 			$(MISC) $(SOURCES) $(WEB_PAGES) && \
 		! grep -Env $(SAFE_SHARP_LINE) $(TDATA) backzone \
-			iso3166.tab leapseconds yearistype.sh zone.tab && \
-		test $$(grep -Ecv $(SAFE_SHARP_LINE) Makefile) -eq 1 && \
-		! grep -Env $(NONSYM_LINE) CONTRIBUTING NEWS README Theory \
-			$(MANS) date.1 zone1970.tab && \
-		! grep -Env $(VALID_LINE) $(ENCHILADA)
+			leapseconds yearistype.sh zone.tab && \
+		! grep -Env $(OK_LINE) $(ENCHILADA)
 
 check_white_space: $(ENCHILADA)
 		! grep -En ' '$(TAB_CHAR)"|$$(printf '[\f\r\v]')" $(ENCHILADA)
@@ -574,9 +574,9 @@ set-timestamps.out: $(ENCHILADA)
 # The zics below ensure that each data file can stand on its own.
 # We also do an all-files run to catch links to links.
 
-check_public:	$(ENCHILADA)
-		make maintainer-clean
-		make "CFLAGS=$(GCC_DEBUG_FLAGS)" $(ENCHILADA) all
+check_public:
+		$(MAKE) maintainer-clean
+		$(MAKE) "CFLAGS=$(GCC_DEBUG_FLAGS)" ALL
 		mkdir tzpublic
 		for i in $(TDATA) ; do \
 		  $(zic) -v -d tzpublic $$i 2>&1 || exit; \
@@ -595,8 +595,8 @@ check_time_t_alternatives:
 		zones=`$(AWK) '/^[^#]/ { print $$3 }' <zone1970.tab` && \
 		for type in $(TIME_T_ALTERNATIVES); do \
 		  mkdir -p tzpublic/$$type && \
-		  make clean_misc && \
-		  make TOPDIR=`pwd`/tzpublic/$$type \
+		  $(MAKE) clean_misc && \
+		  $(MAKE) TOPDIR=`pwd`/tzpublic/$$type \
 		    CFLAGS='$(CFLAGS) -Dtime_tz='"'$$type'" \
 		    REDO='$(REDO)' \
 		    install && \
@@ -642,12 +642,12 @@ tzdata$(VERSION).tar.gz.asc: tzdata$(VER
 		gpg --armor --detach-sign $?
 
 typecheck:
-		make clean
+		$(MAKE) clean
 		for i in "long long" unsigned; \
 		do \
-			make CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \
+			$(MAKE) CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \
 			./zdump -v Europe/Rome ; \
-			make clean ; \
+			$(MAKE) clean ; \
 		done
 
 zonenames:	$(TDATA)

Index: src/lib/libc/time/NEWS
diff -u src/lib/libc/time/NEWS:1.11 src/lib/libc/time/NEWS:1.12
--- src/lib/libc/time/NEWS:1.11	Tue Apr 28 13:00:24 2015
+++ src/lib/libc/time/NEWS	Sun Jun 21 12:06:51 2015
@@ -1,5 +1,34 @@
 News for the tz database
 
+
+Release 2015e - 2015-06-13 10:56:02 -0700
+
+  Changes affecting future time stamps
+
+    Morocco will suspend DST from 2015-06-14 03:00 through 2015-07-19 02:00,
+    not 06-13 and 07-18 as we had guessed.  (Thanks to Milamber.)
+
+    Assume Cayman Islands will observe DST starting next year, using US rules.
+    Although it isn't guaranteed, it is the most likely.
+
+  Changes affecting data format
+
+    The file 'iso3166.tab' now uses UTF-8, so that its entries can better
+    spell the names of Åland Islands, Côte d'Ivoire, and Réunion.
+
+  Changes affecting code
+
+    When displaying data, tzselect converts it to the current locale's
+    encoding if the iconv command works.  (Problem reported by random832.)
+
+    tzselect no longer mishandles Dominica, fixing a bug introduced
+    in Release 2014f.  (Problem reported by Owen Leibman.)
+
+    zic -l no longer fails when compiled with -DTZDEFAULT=\"/etc/localtime\".
+    This fixes a bug introduced in Release 2014f.
+    (Problem reported by Leonardo Chiquitto.)
+
+
 Release 2015d - 2015-04-24 08:09:46 -0700
 
   Changes affecting future time stamps

Index: src/lib/libc/time/localtime.c
diff -u src/lib/libc/time/localtime.c:1.94 src/lib/libc/time/localtime.c:1.95
--- src/lib/libc/time/localtime.c:1.94	Tue Mar 24 16:01:18 2015
+++ src/lib/libc/time/localtime.c	Sun Jun 21 12:06:51 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: localtime.c,v 1.94 2015/03/24 20:01:18 christos Exp $	*/
+/*	$NetBSD: localtime.c,v 1.95 2015/06/21 16:06:51 christos Exp $	*/
 
 /*
 ** This file is in the public domain, so clarified as of
@@ -10,7 +10,7 @@
 #if 0
 static char	elsieid[] = "@(#)localtime.c	8.17";
 #else
-__RCSID("$NetBSD: localtime.c,v 1.94 2015/03/24 20:01:18 christos Exp $");
+__RCSID("$NetBSD: localtime.c,v 1.95 2015/06/21 16:06:51 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -230,13 +230,24 @@ init_ttinfo(struct ttinfo *s, int_fast32
 static int_fast32_t
 detzcode(const char *const codep)
 {
-	int_fast32_t	result;
-	int		i;
+	int_fast32_t result;
+	int	i;
+	int_fast32_t one = 1;
+	int_fast32_t halfmaxval = one << (32 - 2);
+	int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
+	int_fast32_t minval = -1 - maxval;
 
-	result = (codep[0] & 0x80) ? -1 : 0;
-	for (i = 0; i < 4; ++i)
+	result = codep[0] & 0x7f;
+	for (i = 1; i < 4; ++i)
 		result = (result << 8) | (codep[i] & 0xff);
-	return result;
+
+	if (codep[0] & 0x80) {
+	  /* Do two's-complement negation even on non-two's-complement machines.
+	     If the result would be minval - 1, return minval.  */
+	    result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
+	    result += minval;
+	}
+ 	return result;
 }
 
 static int_fast64_t
@@ -244,11 +255,22 @@ detzcode64(const char *const codep)
 {
 	int_fast64_t result;
 	int	i;
+	int_fast64_t one = 1;
+	int_fast64_t halfmaxval = one << (64 - 2);
+	int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
+	int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
 
-	result = (codep[0] & 0x80) ? -1 : 0;
-	for (i = 0; i < 8; ++i)
+	result = codep[0] & 0x7f;
+	for (i = 1; i < 8; ++i)
 		result = (result << 8) | (codep[i] & 0xff);
-	return result;
+
+	if (codep[0] & 0x80) {
+	  /* Do two's-complement negation even on non-two's-complement machines.
+	     If the result would be minval - 1, return minval.  */
+	  result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
+	  result += minval;
+	}
+ 	return result;
 }
 
 const char *

Index: src/lib/libc/time/private.h
diff -u src/lib/libc/time/private.h:1.40 src/lib/libc/time/private.h:1.41
--- src/lib/libc/time/private.h:1.40	Tue Apr 28 13:00:24 2015
+++ src/lib/libc/time/private.h	Sun Jun 21 12:06:51 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: private.h,v 1.40 2015/04/28 17:00:24 christos Exp $	*/
+/*	$NetBSD: private.h,v 1.41 2015/06/21 16:06:51 christos Exp $	*/
 
 #ifndef PRIVATE_H
 #define PRIVATE_H
@@ -490,17 +490,20 @@ time_t time2posix_z(timezone_t __restric
 #define TYPE_SIGNED(type) (/*CONSTCOND*/((type) -1) < 0)
 #endif /* !defined TYPE_SIGNED */
 
-#ifdef LOCALTIME_IMPLEMENTATION
-/* The minimum and maximum finite time values.  */
-static time_t const time_t_min =
-  (TYPE_SIGNED(time_t)
-   ? (time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1)
-   : 0);
-static time_t const time_t_max =
-  (TYPE_SIGNED(time_t)
-   ? - (~ 0 < 0) - ((time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1))
-   : -1);
-#endif
+#define TWOS_COMPLEMENT(t) (/*CONSTCOND*/(t) ~ (t) 0 < 0)
+
+/* Max and min values of the integer type T, of which only the bottom
+   B bits are used, and where the highest-order used bit is considered
+   to be a sign bit if T is signed.  */
+#define MAXVAL(t, b) /*LINTED*/					\
+  ((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))			\
+	- 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
+#define MINVAL(t, b)						\
+  ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
+
+/* The minimum and maximum finite time values.  This assumes no padding.  */
+static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
+static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
 
 #ifndef INT_STRLEN_MAXIMUM
 /*
Index: src/lib/libc/time/zdump.c
diff -u src/lib/libc/time/zdump.c:1.40 src/lib/libc/time/zdump.c:1.41
--- src/lib/libc/time/zdump.c:1.40	Thu Oct 23 17:19:53 2014
+++ src/lib/libc/time/zdump.c	Sun Jun 21 12:06:51 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: zdump.c,v 1.40 2014/10/23 21:19:53 christos Exp $	*/
+/*	$NetBSD: zdump.c,v 1.41 2015/06/21 16:06:51 christos Exp $	*/
 /*
 ** This file is in the public domain, so clarified as of
 ** 2009-05-17 by Arthur David Olson.
@@ -6,7 +6,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: zdump.c,v 1.40 2014/10/23 21:19:53 christos Exp $");
+__RCSID("$NetBSD: zdump.c,v 1.41 2015/06/21 16:06:51 christos Exp $");
 #endif /* !defined lint */
 
 /*
@@ -261,13 +261,15 @@ extern char *	optarg;
 extern int	optind;
 
 /* The minimum and maximum finite time values.  */
+enum { atime_shift = CHAR_BIT * sizeof (time_t) - 2 };
 static time_t	absolute_min_time =
   ((time_t) -1 < 0
-    ? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
+    ? (- ((time_t) ~ (time_t) 0 < 0)
+       - (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift)))
     : 0);
 static time_t	absolute_max_time =
   ((time_t) -1 < 0
-    ? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
+    ? (((time_t) 1 << atime_shift) - 1 + ((time_t) 1 << atime_shift))
    : -1);
 static size_t	longest;
 static char *	progname;

Index: src/lib/libc/time/tzselect.ksh
diff -u src/lib/libc/time/tzselect.ksh:1.13 src/lib/libc/time/tzselect.ksh:1.14
--- src/lib/libc/time/tzselect.ksh:1.13	Sat Jan 31 13:55:17 2015
+++ src/lib/libc/time/tzselect.ksh	Sun Jun 21 12:06:51 2015
@@ -1,6 +1,6 @@
 #! /bin/bash
 #
-#	$NetBSD: tzselect.ksh,v 1.13 2015/01/31 18:55:17 christos Exp $
+#	$NetBSD: tzselect.ksh,v 1.14 2015/06/21 16:06:51 christos Exp $
 #
 PKGVERSION='(tzcode) '
 TZVERSION=see_Makefile
@@ -39,10 +39,16 @@ REPORT_BUGS_TO=t...@iana.org
 : ${AWK=awk}
 : ${TZDIR=`pwd`}
 
+# Output one argument as-is to standard output.
+# Safer than 'echo', which can mishandle '\' or leading '-'.
+say() {
+    printf '%s\n' "$1"
+}
+
 # Check for awk Posix compliance.
 ($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
 [ $? = 123 ] || {
-	echo >&2 "$0: Sorry, your '$AWK' program is not Posix compatible."
+	say >&2 "$0: Sorry, your '$AWK' program is not Posix compatible."
 	exit 1
 }
 
@@ -156,16 +162,16 @@ do
     -version)
 	exec echo "tzselect $PKGVERSION$TZVERSION" ;;
     -*)
-	echo >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
+	say >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
     *)
-	echo >&2 "$0: try '$0 --help'"; exit 1 ;;
+	say >&2 "$0: try '$0 --help'"; exit 1 ;;
     esac
 done
 
 shift `expr $OPTIND - 1`
 case $# in
 0) ;;
-*) echo >&2 "$0: $1: unknown argument"; exit 1 ;;
+*) say >&2 "$0: $1: unknown argument"; exit 1 ;;
 esac
 
 # Make sure the tables are readable.
@@ -174,11 +180,26 @@ TZ_ZONE_TABLE=$TZDIR/$zonetabtype.tab
 for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
 do
 	<"$f" || {
-		echo >&2 "$0: time zone files are not set up correctly"
+		say >&2 "$0: time zone files are not set up correctly"
 		exit 1
 	}
 done
 
+# If the current locale does not support UTF-8, convert data to current
+# locale's format if possible, as the shell aligns columns better that way.
+# Check the UTF-8 of U+12345 CUNEIFORM SIGN URU TIMES KI.
+! $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' &&
+    { tmp=`(mktemp -d) 2>/dev/null` || {
+	tmp=${TMPDIR-/tmp}/tzselect.$$ &&
+	(umask 77 && mkdir -- "$tmp")
+    };} &&
+    trap 'status=$?; rm -fr -- "$tmp"; exit $status' 0 HUP INT PIPE TERM &&
+    (iconv -f UTF-8 -t //TRANSLIT <"$TZ_COUNTRY_TABLE" >$tmp/iso3166.tab) \
+        2>/dev/null &&
+    TZ_COUNTRY_TABLE=$tmp/iso3166.tab &&
+    iconv -f UTF-8 -t //TRANSLIT <"$TZ_ZONE_TABLE" >$tmp/$zonetabtype.tab &&
+    TZ_ZONE_TABLE=$tmp/$zonetabtype.tab
+
 newline='
 '
 IFS=$newline
@@ -338,8 +359,7 @@ while
 				exit 0
 			}'
 		do
-			echo >&2 "'$TZ' is not a conforming" \
-				'Posix time zone string.'
+		    say >&2 "'$TZ' is not a conforming Posix time zone string."
 		done
 		TZ_for_date=$TZ;;
 	*)
@@ -361,7 +381,7 @@ while
 		      sort -n |
 		      sed "${location_limit}q"
 		    `
-		    regions=`echo "$distance_table" | $AWK '
+		    regions=`say "$distance_table" | $AWK '
 		      BEGIN { FS = "\t" }
 		      { print $NF }
 		    '`
@@ -371,7 +391,7 @@ while
 			    "of distance from $coord".
 		    doselect $regions
 		    region=$select_result
-		    TZ=`echo "$distance_table" | $AWK -v region="$region" '
+		    TZ=`say "$distance_table" | $AWK -v region="$region" '
 		      BEGIN { FS="\t" }
 		      $NF == region { print $4 }
 		    '`
@@ -431,6 +451,7 @@ while
 					}
 				}
 			}
+			/^#/ { next }
 			$1 ~ cc { print $4 }
 		' <"$TZ_ZONE_TABLE"`
 
@@ -462,6 +483,7 @@ while
 					}
 				}
 			}
+			/^#/ { next }
 			$1 ~ cc && $4 == region { print $3 }
 		' <"$TZ_ZONE_TABLE"`
 		esac
@@ -469,7 +491,7 @@ while
 		# Make sure the corresponding zoneinfo file exists.
 		TZ_for_date=$TZDIR/$TZ
 		<"$TZ_for_date" || {
-			echo >&2 "$0: time zone files are not set up correctly"
+			say >&2 "$0: time zone files are not set up correctly"
 			exit 1
 		}
 	esac
@@ -502,15 +524,15 @@ Universal Time is now:	$UTdate."
 	echo >&2 "The following information has been given:"
 	echo >&2 ""
 	case $country%$region%$coord in
-	?*%?*%)	echo >&2 "	$country$newline	$region";;
-	?*%%)	echo >&2 "	$country";;
-	%?*%?*) echo >&2 "	coord $coord$newline	$region";;
-	%%?*)	echo >&2 "	coord $coord";;
-	*)	echo >&2 "	TZ='$TZ'"
+	?*%?*%)	say >&2 "	$country$newline	$region";;
+	?*%%)	say >&2 "	$country";;
+	%?*%?*) say >&2 "	coord $coord$newline	$region";;
+	%%?*)	say >&2 "	coord $coord";;
+	*)	say >&2 "	TZ='$TZ'"
 	esac
-	echo >&2 ""
-	echo >&2 "Therefore TZ='$TZ' will be used.$extra_info"
-	echo >&2 "Is the above information OK?"
+	say >&2 ""
+	say >&2 "Therefore TZ='$TZ' will be used.$extra_info"
+	say >&2 "Is the above information OK?"
 
 	doselect Yes No
 	ok=$select_result
@@ -525,7 +547,7 @@ case $SHELL in
 *) file=.profile line="TZ='$TZ'; export TZ"
 esac
 
-echo >&2 "
+say >&2 "
 You can make this change permanent for yourself by appending the line
 	$line
 to the file '$file' in your home directory; then log out and log in again.
@@ -533,4 +555,4 @@ to the file '$file' in your home directo
 Here is that TZ value again, this time on standard output so that you
 can use the $0 command in shell scripts:"
 
-echo "$TZ"
+say "$TZ"

Index: src/lib/libc/time/zic.8
diff -u src/lib/libc/time/zic.8:1.24 src/lib/libc/time/zic.8:1.25
--- src/lib/libc/time/zic.8:1.24	Tue Oct  7 17:51:03 2014
+++ src/lib/libc/time/zic.8	Sun Jun 21 12:06:51 2015
@@ -1,4 +1,4 @@
-.\"	$NetBSD: zic.8,v 1.24 2014/10/07 21:51:03 christos Exp $
+.\"	$NetBSD: zic.8,v 1.25 2015/06/21 16:06:51 christos Exp $
 .Dd October 6, 2014
 .Dt ZIC 8
 .Os
@@ -324,7 +324,8 @@ The time at which the UT offset or the r
 It is specified as a year, a month, a day, and a time of day.
 If this is specified,
 the time zone information is generated from the given UT offset
-and rule change until the time specified.
+and rule change until the time specified, which is interpreted using
+the rules in effect just before the transition.
 The month, day, and time of day have the same format as the IN, ON, and AT
 fields of a rule; trailing fields can be omitted, and default to the
 earliest possible value for the missing fields.

Index: src/lib/libc/time/zic.c
diff -u src/lib/libc/time/zic.c:1.53 src/lib/libc/time/zic.c:1.54
--- src/lib/libc/time/zic.c:1.53	Tue Apr 28 13:00:24 2015
+++ src/lib/libc/time/zic.c	Sun Jun 21 12:06:51 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: zic.c,v 1.53 2015/04/28 17:00:24 christos Exp $	*/
+/*	$NetBSD: zic.c,v 1.54 2015/06/21 16:06:51 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.53 2015/04/28 17:00:24 christos Exp $");
+__RCSID("$NetBSD: zic.c,v 1.54 2015/06/21 16:06:51 christos Exp $");
 #endif /* !defined lint */
 
 #include "private.h"
@@ -456,7 +456,8 @@ verror(const char *const string, va_list
 	**	zic ... 2>&1 | error -t "*" -v
 	** on BSD systems.
 	*/
-	fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
+	if (filename)
+	  fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
 	vfprintf(stderr, string, args);
 	if (rfilename != NULL)
 		fprintf(stderr, _(" (rule from \"%s\", line %d)"),
@@ -608,7 +609,7 @@ _("%s: More than one -L option specified
 				noise = true;
 				break;
 			case 's':
-				warning(_("-s ignored\n"));
+				warning(_("-s ignored"));
 				break;
 		}
 	if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
@@ -661,36 +662,43 @@ _("%s: More than one -L option specified
 	return errors ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
-static void
+static bool
 componentcheck(char const *name, char const *component,
 	       char const *component_end)
 {
 	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 (!*name)
+	    error (_("empty file name"));
+	  else
+	    error (_(component == name
+		     ? "file name '%s' begins with '/'"
+		     : *component_end
+		     ? "file name '%s' contains '//'"
+		     : "file name '%s' ends with '/'"),
+		   name);
+	  return false;
 	}
 	if (0 < component_len && component_len <= 2
 	    && component[0] == '.' && component_end[-1] == '.') {
-		fprintf(stderr, _("%s: file name '%s' contains"
-				  " '%.*s' component"),
-			progname, name, (int) component_len, component);
-		exit(EXIT_FAILURE);
+	  error(_("file name '%s' contains '%.*s' component"),
+		name, (int) component_len, component);
+	  return false;
 	}
-	if (!noise)
-		return;
-	if (0 < component_len && component[0] == '-')
-		warning(_("file name '%s' component contains leading '-'"),
-			name);
-	if (component_len_max < component_len)
-		warning(_("file name '%s' contains overlength component"
-			  " '%.*s...'"),
-			name, component_len_max, component);
+	if (noise) {
+	  if (0 < component_len && component[0] == '-')
+	    warning(_("file name '%s' component contains leading '-'"),
+		    name);
+	  if (component_len_max < component_len)
+	    warning(_("file name '%s' contains overlength component"
+		      " '%.*s...'"),
+		    name, component_len_max, component);
+	}
+	return true;
 }
 
-static void
+static bool
 namecheck(const char *name)
 {
 	char const *cp;
@@ -714,14 +722,14 @@ namecheck(const char *name)
 				 ? _("file name '%s' contains byte '%c'")
 				 : _("file name '%s' contains byte '\\%o'")),
 				name, c);
-			return;
 		}
 		if (c == '/') {
-			componentcheck(name, component, cp);
+			if (!componentcheck(name, component, cp))
+			  return false;
 			component = cp + 1;
 		}
 	}
-	componentcheck(name, component, cp);
+	return componentcheck(name, component, cp);
 }
 
 static char *
@@ -746,7 +754,6 @@ dolink(const char *const fromfield, cons
 	char *	toname;
 	int fromisdir;
 
-	namecheck(tofield);
 	fromname = relname(directory, fromfield);
 	toname = relname(directory, tofield);
 	/*
@@ -826,8 +833,8 @@ dolink(const char *const fromfield, cons
 
 #define TIME_T_BITS_IN_FILE	64
 
-static const zic_t min_time = (zic_t) -1 << (TIME_T_BITS_IN_FILE - 1);
-static const zic_t max_time = -1 - ((zic_t) -1 << (TIME_T_BITS_IN_FILE - 1));
+static zic_t const min_time = MINVAL (zic_t, TIME_T_BITS_IN_FILE);
+static zic_t const max_time = MAXVAL (zic_t, TIME_T_BITS_IN_FILE);
 
 /* Estimated time of the Big Bang, in seconds since the POSIX epoch.
    rounded downward to the negation of a power of two that is
@@ -1033,9 +1040,9 @@ infile(const char *name)
 					break;
 				case LC_LEAP:
 					if (name != leapsec)
-						warning(
-_("%s: Leap line in non leap seconds file %s\n"),
-							progname, name);
+					  warning(_("%s: Leap line in non leap"
+						    " seconds file %s"),
+						  progname, name);
 					else	inleap(fields, nfields);
 					wantcont = false;
 					break;
@@ -1191,7 +1198,9 @@ inzsub(char **const fields, const int nf
 		i_untilday = ZFC_TILDAY;
 		i_untiltime = ZFC_TILTIME;
 		z.z_name = NULL;
-	} else {
+	} else if (!namecheck(fields[ZF_NAME]))
+		return false;
+	else {
 		i_gmtoff = ZF_GMTOFF;
 		i_rule = ZF_RULE;
 		i_format = ZF_FORMAT;
@@ -1367,10 +1376,8 @@ inlink(char **const fields, const int nf
 		error(_("blank FROM field on Link line"));
 		return;
 	}
-	if (*fields[LF_TO] == '\0') {
-		error(_("blank TO field on Link line"));
-		return;
-	}
+	if (! namecheck(fields[LF_TO]))
+	  return;
 	l.l_filename = filename;
 	l.l_linenum = linenum;
 	l.l_from = ecpyalloc(fields[LF_FROM]);
@@ -1596,7 +1603,6 @@ writezone(const char *const name, const 
 	void *typesptr = ats + timecnt;
 	unsigned char *types = typesptr;
 
-	namecheck(name);
 	/*
 	** Sort.
 	*/
@@ -2971,7 +2977,7 @@ mkdirs(char *argname)
 			if (itsdir(name) <= 0) {
 				char const *e = strerror(err);
 				warning(_("%s: Can't create directory"
-					  " %s: %s\n"),
+					  " %s: %s"),
 					progname, name, e);
 				free(name);
 				return false;

Reply via email to