aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2013-12-20 13:10:07 +0000
committerJoseph Myers <joseph@codesourcery.com>2013-12-20 13:10:07 +0000
commit85bff96ad652b463f83d4cf19239eff1535e186a (patch)
treed651b5e72fe828f47613e6813ac5d54b0b7aaf66
parentb7867a3bfb9d7e00204c088feb227abddfc7bb43 (diff)
downloadglibc-85bff96ad652b463f83d4cf19239eff1535e186a.tar.xz
glibc-85bff96ad652b463f83d4cf19239eff1535e186a.zip
Update timezone code from tzcode 2013i.
Now we have Paul's support for version-3 tz files checked in, this patch updates all the code we take (unmodified) from tzcode to version 2013i (which includes the support for generating version-3 tz files where necessary). Tested x86_64. * timezone/checktab.awk: Update from tzcode 2013i. * timezone/private.h: Likewise. * timezone/scheck.c: Likewise. * timezone/tzfile.h: Likewise. * timezone/tzselect.ksh: Likewise. * timezone/zdump.c: Likewise. * timezone/zic.c: Likewise.
-rw-r--r--ChangeLog8
-rw-r--r--timezone/checktab.awk29
-rw-r--r--timezone/private.h148
-rw-r--r--timezone/scheck.c29
-rw-r--r--timezone/tzfile.h25
-rw-r--r--timezone/tzselect.ksh366
-rw-r--r--timezone/zdump.c327
-rw-r--r--timezone/zic.c620
8 files changed, 1072 insertions, 480 deletions
diff --git a/ChangeLog b/ChangeLog
index 1a1b93237e..80fab8e00e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2013-12-20 Joseph Myers <joseph@codesourcery.com>
+ * timezone/checktab.awk: Update from tzcode 2013i.
+ * timezone/private.h: Likewise.
+ * timezone/scheck.c: Likewise.
+ * timezone/tzfile.h: Likewise.
+ * timezone/tzselect.ksh: Likewise.
+ * timezone/zdump.c: Likewise.
+ * timezone/zic.c: Likewise.
+
* math/auto-libm-test-in: Add tests of cpow.
* math/auto-libm-test-out: Regenerated.
* math/libm-test.inc (cpow_test_data): Use AUTO_TESTS_cc_c.
diff --git a/timezone/checktab.awk b/timezone/checktab.awk
index c88b12f1ba..fec4f628e5 100644
--- a/timezone/checktab.awk
+++ b/timezone/checktab.awk
@@ -9,6 +9,9 @@ BEGIN {
if (!zone_table) zone_table = "zone.tab"
if (!want_warnings) want_warnings = -1
+ # A special (and we hope temporary) case.
+ tztab["America/Montreal"] = 1
+
while (getline <iso_table) {
iso_NR++
if ($0 ~ /^#/) continue
@@ -69,13 +72,10 @@ BEGIN {
status = 1
}
cc0 = cc
- if (tz2cc[tz]) {
- printf "%s:%d: %s: duplicate TZ column\n", \
- zone_table, zone_NR, tz >>"/dev/stderr"
- status = 1
- }
- tz2cc[tz] = cc
- tz2comments[tz] = comments
+ cctz = cc tz
+ cctztab[cctz] = 1
+ tztab[tz] = 1
+ tz2comments[cctz] = comments
tz2NR[tz] = zone_NR
if (cc2name[cc]) {
cc_used[cc]++
@@ -92,16 +92,19 @@ BEGIN {
}
}
- for (tz in tz2cc) {
- if (cc_used[tz2cc[tz]] == 1) {
- if (tz2comments[tz]) {
+ for (cctz in cctztab) {
+ cc = substr (cctz, 1, 2)
+ tz = substr (cctz, 3)
+ if (cc_used[cc] == 1) {
+ if (tz2comments[cctz]) {
printf "%s:%d: unnecessary comment `%s'\n", \
- zone_table, tz2NR[tz], tz2comments[tz] \
+ zone_table, tz2NR[tz], \
+ tz2comments[cctz] \
>>"/dev/stderr"
status = 1
}
} else {
- if (!tz2comments[tz]) {
+ if (!tz2comments[cctz]) {
printf "%s:%d: missing comment\n", \
zone_table, tz2NR[tz] >>"/dev/stderr"
status = 1
@@ -125,7 +128,7 @@ BEGIN {
if (src != dst) tz = $3
}
if (tz && tz ~ /\//) {
- if (!tz2cc[tz]) {
+ if (!tztab[tz]) {
printf "%s: no data for `%s'\n", zone_table, tz \
>>"/dev/stderr"
status = 1
diff --git a/timezone/private.h b/timezone/private.h
index 1d1d391f56..4eb0ab6221 100644
--- a/timezone/private.h
+++ b/timezone/private.h
@@ -34,6 +34,10 @@
#define HAVE_INCOMPATIBLE_CTIME_R 0
#endif /* !defined INCOMPATIBLE_CTIME_R */
+#ifndef HAVE_LINK
+#define HAVE_LINK 1
+#endif /* !defined HAVE_LINK */
+
#ifndef HAVE_SETTIMEOFDAY
#define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */
@@ -124,19 +128,76 @@
#include "stdint.h"
#endif /* !HAVE_STDINT_H */
+#ifndef HAVE_INTTYPES_H
+# define HAVE_INTTYPES_H HAVE_STDINT_H
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
#ifndef INT_FAST64_MAX
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
#if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long int_fast64_t;
+# ifdef LLONG_MAX
+# define INT_FAST64_MIN LLONG_MIN
+# define INT_FAST64_MAX LLONG_MAX
+# else
+# define INT_FAST64_MIN __LONG_LONG_MIN__
+# define INT_FAST64_MAX __LONG_LONG_MAX__
+# endif
+# define SCNdFAST64 "lld"
#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#if (LONG_MAX >> 31) < 0xffffffff
Please use a compiler that supports a 64-bit integer type (or wider);
you may need to compile with "-DHAVE_STDINT_H".
#endif /* (LONG_MAX >> 31) < 0xffffffff */
typedef long int_fast64_t;
+# define INT_FAST64_MIN LONG_MIN
+# define INT_FAST64_MAX LONG_MAX
+# define SCNdFAST64 "ld"
#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#endif /* !defined INT_FAST64_MAX */
+#ifndef INT_FAST32_MAX
+# if INT_MAX >> 31 == 0
+typedef long int_fast32_t;
+# else
+typedef int int_fast32_t;
+# endif
+#endif
+
+#ifndef INTMAX_MAX
+# if defined LLONG_MAX || defined __LONG_LONG_MAX__
+typedef long long intmax_t;
+# define strtoimax strtoll
+# define PRIdMAX "lld"
+# ifdef LLONG_MAX
+# define INTMAX_MAX LLONG_MAX
+# define INTMAX_MIN LLONG_MIN
+# else
+# define INTMAX_MAX __LONG_LONG_MAX__
+# define INTMAX_MIN __LONG_LONG_MIN__
+# endif
+# else
+typedef long intmax_t;
+# define strtoimax strtol
+# define PRIdMAX "ld"
+# define INTMAX_MAX LONG_MAX
+# define INTMAX_MIN LONG_MIN
+# endif
+#endif
+
+#ifndef UINTMAX_MAX
+# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
+typedef unsigned long long uintmax_t;
+# define PRIuMAX "llu"
+# else
+typedef unsigned long uintmax_t;
+# define PRIuMAX "lu"
+# endif
+#endif
+
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif /* !defined INT32_MAX */
@@ -144,10 +205,26 @@ typedef long int_fast64_t;
#define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */
-#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
+#if 2 < __GNUC__ + (96 <= __GNUC_MINOR__)
+# define ATTRIBUTE_CONST __attribute__ ((const))
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
+# define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
#else
+# define ATTRIBUTE_CONST /* empty */
# define ATTRIBUTE_PURE /* empty */
+# define ATTRIBUTE_FORMAT(spec) /* empty */
+#endif
+
+#if !defined _Noreturn && __STDC_VERSION__ < 201112
+# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
+# define _Noreturn __attribute__ ((__noreturn__))
+# else
+# define _Noreturn
+# endif
+#endif
+
+#if __STDC_VERSION__ < 199901 && !defined restrict
+# define restrict /* empty */
#endif
/*
@@ -165,6 +242,58 @@ extern char * asctime_r(struct tm const *, char *);
#endif
/*
+** Compile with -Dtime_tz=T to build the tz package with a private
+** time_t type equivalent to T rather than the system-supplied time_t.
+** This debugging feature can test unusual design decisions
+** (e.g., time_t wider than 'long', or unsigned time_t) even on
+** typical platforms.
+*/
+#ifdef time_tz
+static time_t sys_time(time_t *x) { return time(x); }
+
+# undef ctime
+# define ctime tz_ctime
+# undef ctime_r
+# define ctime_r tz_ctime_r
+# undef difftime
+# define difftime tz_difftime
+# undef gmtime
+# define gmtime tz_gmtime
+# undef gmtime_r
+# define gmtime_r tz_gmtime_r
+# undef localtime
+# define localtime tz_localtime
+# undef localtime_r
+# define localtime_r tz_localtime_r
+# undef mktime
+# define mktime tz_mktime
+# undef time
+# define time tz_time
+# undef time_t
+# define time_t tz_time_t
+
+typedef time_tz time_t;
+
+char *ctime(time_t const *);
+char *ctime_r(time_t const *, char *);
+double difftime(time_t, time_t);
+struct tm *gmtime(time_t const *);
+struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
+struct tm *localtime(time_t const *);
+struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
+time_t mktime(struct tm *);
+
+static time_t
+time(time_t *p)
+{
+ time_t r = sys_time(0);
+ if (p)
+ *p = r;
+ return r;
+}
+#endif
+
+/*
** Private function declarations.
*/
@@ -192,14 +321,15 @@ const char * scheck(const char * string, const char * format);
#define TYPE_SIGNED(type) (((type) -1) < 0)
#endif /* !defined TYPE_SIGNED */
-/*
-** Since the definition of TYPE_INTEGRAL contains floating point numbers,
-** it cannot be used in preprocessor directives.
-*/
-
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
+/* The minimum and maximum finite time values. */
+static time_t const time_t_min =
+ (TYPE_SIGNED(time_t)
+ ? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
+ : 0);
+static time_t const time_t_max =
+ (TYPE_SIGNED(time_t)
+ ? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
+ : -1);
#ifndef INT_STRLEN_MAXIMUM
/*
diff --git a/timezone/scheck.c b/timezone/scheck.c
index ed60980d83..8bd01a858f 100644
--- a/timezone/scheck.c
+++ b/timezone/scheck.c
@@ -25,26 +25,35 @@ scheck(const char *const string, const char *const format)
return result;
fp = format;
tp = fbuf;
+
+ /*
+ ** Copy directives, suppressing each conversion that is not
+ ** already suppressed. Scansets containing '%' are not
+ ** supported; e.g., the conversion specification "%[%]" is not
+ ** supported. Also, multibyte characters containing a
+ ** non-leading '%' byte are not supported.
+ */
while ((*tp++ = c = *fp++) != '\0') {
if (c != '%')
continue;
- if (*fp == '%') {
- *tp++ = *fp++;
- continue;
+ if (is_digit(*fp)) {
+ char const *f = fp;
+ char *t = tp;
+ do {
+ *t++ = c = *f++;
+ } while (is_digit(c));
+ if (c == '$') {
+ fp = f;
+ tp = t;
+ }
}
*tp++ = '*';
if (*fp == '*')
++fp;
- while (is_digit(*fp))
- *tp++ = *fp++;
- if (*fp == 'l' || *fp == 'h')
- *tp++ = *fp++;
- else if (*fp == '[')
- do *tp++ = *fp++;
- while (*fp != '\0' && *fp != ']');
if ((*tp++ = *fp++) == '\0')
break;
}
+
*(tp - 1) = '%';
*tp++ = 'c';
*tp = '\0';
diff --git a/timezone/tzfile.h b/timezone/tzfile.h
index 0f6c687f16..529650dd8a 100644
--- a/timezone/tzfile.h
+++ b/timezone/tzfile.h
@@ -39,7 +39,7 @@
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2' as of 2005 */
+ char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
char tzh_reserved[15]; /* reserved--must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
@@ -55,7 +55,7 @@ struct tzhead {
** tzh_timecnt (char [4])s coded transition times a la time(2)
** tzh_timecnt (unsigned char)s types of local time starting at above
** tzh_typecnt repetitions of
-** one (char [4]) coded UTC offset in seconds
+** one (char [4]) coded UT offset in seconds
** one (unsigned char) used to set tm_isdst
** one (unsigned char) that's an abbreviation list index
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
@@ -68,7 +68,7 @@ struct tzhead {
** if absent, transition times are
** assumed to be wall clock time
** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
-** time is UTC, if FALSE,
+** time is UT, if FALSE,
** transition time is local time
** if absent, transition times are
** assumed to be local time
@@ -82,6 +82,13 @@ struct tzhead {
** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for
** such instants).
+**
+** If tz_version is '3' or greater, the above is extended as follows.
+** First, the POSIX TZ string's hour offset may range from -167
+** through 167 as compared to the POSIX-required 0 through 24.
+** Second, its DST start time may be January 1 at 00:00 and its stop
+** time December 31 at 24:00 plus the difference between DST and
+** standard time, indicating DST all year.
*/
/*
@@ -94,16 +101,8 @@ struct tzhead {
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
-#ifndef NOSOLAR
+/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined NOSOLAR */
-#ifdef NOSOLAR
-/*
-** Must be at least 14 for Europe/Riga as of Jan 12 1995,
-** as noted by Earl Chew.
-*/
-#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
-#endif /* !defined NOSOLAR */
#endif /* !defined TZ_MAX_TYPES */
#ifndef TZ_MAX_CHARS
@@ -122,7 +121,7 @@ struct tzhead {
#define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
+#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
#define MONSPERYEAR 12
#define TM_SUNDAY 0
diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh
index 8e66b44273..9d7069116a 100644
--- a/timezone/tzselect.ksh
+++ b/timezone/tzselect.ksh
@@ -11,7 +11,7 @@ REPORT_BUGS_TO=tz@iana.org
# Porting notes:
#
-# This script requires a Posix-like shell with the extension of a
+# This script requires a Posix-like shell and prefers the extension of a
# 'select' statement. The 'select' statement was introduced in the
# Korn shell and is available in Bash and other shell implementations.
# If your host lacks both Bash and the Korn shell, you can get their
@@ -21,6 +21,10 @@ REPORT_BUGS_TO=tz@iana.org
# Korn Shell <http://www.kornshell.com/>
# Public Domain Korn Shell <http://www.cs.mun.ca/~michael/pdksh/>
#
+# For portability to Solaris 9 /bin/sh this script avoids some POSIX
+# features and common extensions, such as $(...) (which works sometimes
+# but not others), $((...)), and $10.
+#
# This script also uses several features of modern awk programs.
# If your host lacks awk, or has an old awk that does not conform to Posix,
# you can use either of the following free programs instead:
@@ -31,7 +35,7 @@ REPORT_BUGS_TO=tz@iana.org
# Specify default values for environment variables if they are unset.
: ${AWK=awk}
-: ${TZDIR=$(pwd)}
+: ${TZDIR=`pwd`}
# Check for awk Posix compliance.
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
@@ -40,21 +44,125 @@ REPORT_BUGS_TO=tz@iana.org
exit 1
}
-if [ "$1" = "--help" ]; then
- cat <<EOF
-Usage: tzselect
+coord=
+location_limit=10
+
+usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
Select a time zone interactively.
-Report bugs to $REPORT_BUGS_TO.
-EOF
- exit
-elif [ "$1" = "--version" ]; then
- cat <<EOF
-tzselect $PKGVERSION$TZVERSION
-EOF
- exit
+Options:
+
+ -c COORD
+ Instead of asking for continent and then country and then city,
+ ask for selection from time zones whose largest cities
+ are closest to the location with geographical coordinates COORD.
+ COORD should use ISO 6709 notation, for example, '-c +4852+00220'
+ for Paris (in degrees and minutes, North and East), or
+ '-c -35-058' for Buenos Aires (in degrees, South and West).
+
+ -n LIMIT
+ Display at most LIMIT locations when -c is used (default $location_limit).
+
+ --version
+ Output version information.
+
+ --help
+ Output this help.
+
+Report bugs to $REPORT_BUGS_TO."
+
+# Ask the user to select from the function's arguments,
+# and assign the selected argument to the variable 'select_result'.
+# Exit on EOF or I/O error. Use the shell's 'select' builtin if available,
+# falling back on a less-nice but portable substitute otherwise.
+if
+ case $BASH_VERSION in
+ ?*) : ;;
+ '')
+ # '; exit' should be redundant, but Dash doesn't properly fail without it.
+ (eval 'set --; select x; do break; done; exit') 2>/dev/null
+ esac
+then
+ # Do this inside 'eval', as otherwise the shell might exit when parsing it
+ # even though it is never executed.
+ eval '
+ doselect() {
+ select select_result
+ do
+ case $select_result in
+ "") echo >&2 "Please enter a number in range." ;;
+ ?*) break
+ esac
+ done || exit
+ }
+
+ # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
+ case $BASH_VERSION in
+ [01].*)
+ case `echo 1 | (select x in x; do break; done) 2>/dev/null` in
+ ?*) PS3=
+ esac
+ esac
+ '
+else
+ doselect() {
+ # Field width of the prompt numbers.
+ select_width=`expr $# : '.*'`
+
+ select_i=
+
+ while :
+ do
+ case $select_i in
+ '')
+ select_i=0
+ for select_word
+ do
+ select_i=`expr $select_i + 1`
+ printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word"
+ done ;;
+ *[!0-9]*)
+ echo >&2 'Please enter a number in range.' ;;
+ *)
+ if test 1 -le $select_i && test $select_i -le $#; then
+ shift `expr $select_i - 1`
+ select_result=$1
+ break
+ fi
+ echo >&2 'Please enter a number in range.'
+ esac
+
+ # Prompt and read input.
+ printf >&2 %s "${PS3-#? }"
+ read select_i || exit
+ done
+ }
fi
+while getopts c:n:-: opt
+do
+ case $opt$OPTARG in
+ c*)
+ coord=$OPTARG ;;
+ n*)
+ location_limit=$OPTARG ;;
+ -help)
+ exec echo "$usage" ;;
+ -version)
+ exec echo "tzselect $PKGVERSION$TZVERSION" ;;
+ -*)
+ echo >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
+ *)
+ echo >&2 "$0: try '$0 --help'"; exit 1 ;;
+ esac
+done
+
+shift `expr $OPTIND - 1`
+case $# in
+0) ;;
+*) echo >&2 "$0: $1: unknown argument"; exit 1 ;;
+esac
+
# Make sure the tables are readable.
TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
TZ_ZONE_TABLE=$TZDIR/zone.tab
@@ -71,11 +179,65 @@ newline='
IFS=$newline
-# Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout.
-case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in
-?*) PS3=
-esac
-
+# Awk script to read a time zone table and output the same table,
+# with each column preceded by its distance from 'here'.
+output_distances='
+ BEGIN {
+ FS = "\t"
+ while (getline <TZ_COUNTRY_TABLE)
+ if ($0 ~ /^[^#]/)
+ country[$1] = $2
+ country["US"] = "US" # Otherwise the strings get too long.
+ }
+ function convert_coord(coord, deg, min, ilen, sign, sec) {
+ if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) {
+ degminsec = coord
+ intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000)
+ minsec = degminsec - intdeg * 10000
+ intmin = minsec < 0 ? -int(-minsec / 100) : int(minsec / 100)
+ sec = minsec - intmin * 100
+ deg = (intdeg * 3600 + intmin * 60 + sec) / 3600
+ } else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) {
+ degmin = coord
+ intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100)
+ min = degmin - intdeg * 100
+ deg = (intdeg * 60 + min) / 60
+ } else
+ deg = coord
+ return deg * 0.017453292519943296
+ }
+ function convert_latitude(coord) {
+ match(coord, /..*[-+]/)
+ return convert_coord(substr(coord, 1, RLENGTH - 1))
+ }
+ function convert_longitude(coord) {
+ match(coord, /..*[-+]/)
+ return convert_coord(substr(coord, RLENGTH))
+ }
+ # Great-circle distance between points with given latitude and longitude.
+ # Inputs and output are in radians. This uses the great-circle special
+ # case of the Vicenty formula for distances on ellipsoids.
+ function dist(lat1, long1, lat2, long2, dlong, x, y, num, denom) {
+ dlong = long2 - long1
+ x = cos (lat2) * sin (dlong)
+ y = cos (lat1) * sin (lat2) - sin (lat1) * cos (lat2) * cos (dlong)
+ num = sqrt (x * x + y * y)
+ denom = sin (lat1) * sin (lat2) + cos (lat1) * cos (lat2) * cos (dlong)
+ return atan2(num, denom)
+ }
+ BEGIN {
+ coord_lat = convert_latitude(coord)
+ coord_long = convert_longitude(coord)
+ }
+ /^[^#]/ {
+ here_lat = convert_latitude($2)
+ here_long = convert_longitude($2)
+ line = $1 "\t" $2 "\t" $3 "\t" country[$1]
+ if (NF == 4)
+ line = line " - " $4
+ printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), line
+ }
+'
# Begin the main loop. We come back here if the user wants to retry.
while
@@ -87,39 +249,46 @@ while
country=
region=
+ case $coord in
+ ?*)
+ continent=coord;;
+ '')
# Ask the user for continent or ocean.
- echo >&2 'Please select a continent or ocean.'
-
- select continent in \
- Africa \
- Americas \
- Antarctica \
- 'Arctic Ocean' \
- Asia \
- 'Atlantic Ocean' \
- Australia \
- Europe \
- 'Indian Ocean' \
- 'Pacific Ocean' \
- 'none - I want to specify the time zone using the Posix TZ format.'
- do
+ echo >&2 'Please select a continent, ocean, "coord", or "TZ".'
+
+ quoted_continents=`
+ $AWK '
+ BEGIN { FS = "\t" }
+ /^[^#]/ {
+ entry = substr($3, 1, index($3, "/") - 1)
+ if (entry == "America")
+ entry = entry "s"
+ if (entry ~ /^(Arctic|Atlantic|Indian|Pacific)$/)
+ entry = entry " Ocean"
+ printf "'\''%s'\''\n", entry
+ }
+ ' $TZ_ZONE_TABLE |
+ sort -u |
+ tr '\n' ' '
+ echo ''
+ `
+