1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-18 01:40:06 +02:00

Sync from gnulib.

This commit is contained in:
Paul Eggert
2004-10-29 23:43:34 +00:00
parent df8ea7a4e8
commit a4a87ad5bb
8 changed files with 488 additions and 305 deletions

9
config/config.guess vendored
View File

@@ -3,7 +3,7 @@
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
timestamp='2004-09-07'
timestamp='2004-10-25'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -342,7 +342,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
DRS?6000:unix:4.0:6*)
echo sparc-icl-nx6
exit 0 ;;
DRS?6000:UNIX_SV:4.2*:7*)
DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7 && exit 0 ;;
esac ;;
@@ -1247,7 +1247,10 @@ EOF
A*) echo alpha-dec-vms && exit 0 ;;
I*) echo ia64-dec-vms && exit 0 ;;
V*) echo vax-dec-vms && exit 0 ;;
esac
esac ;;
*:XENIX:*:SysV)
echo i386-pc-xenix
exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2004-09-10.20
scriptversion=2004-10-22.00
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
@@ -213,7 +213,7 @@ do
fi
# This sed command emulates the dirname command.
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'`
# Make sure that the destination directory exists.
@@ -226,7 +226,8 @@ do
oIFS=$IFS
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
shift
IFS=$oIFS
pathcomp=

View File

@@ -2314,15 +2314,26 @@ where each line of input produces a line of output.}
% @table, @ftable, @vtable.
\envdef\table{%
\let\itemindex\gobble
\tablex
\tablecheck{table}%
}
\envdef\ftable{%
\def\itemindex ##1{\doind {fn}{\code{##1}}}%
\tablex
\tablecheck{ftable}%
}
\envdef\vtable{%
\def\itemindex ##1{\doind {vr}{\code{##1}}}%
\tablex
\tablecheck{vtable}%
}
\def\tablecheck#1{%
\ifnum \the\catcode`\^^M=\active
\endgroup
\errmessage{This command won't work in this context; perhaps the problem is
that we are \inenvironment\thisenv}%
\def\next{\doignore{#1}}%
\else
\let\next\tablex
\fi
\next
}
\def\tablex#1{%
\def\itemindicate{#1}%

View File

@@ -51,11 +51,12 @@ arguments to the various programs. The C interface (via the
* General date syntax:: Common rules.
* Calendar date items:: 19 Dec 1994.
* Time of day items:: 9:20pm.
* Time zone items:: @sc{est}, @sc{pdt}, @sc{gmt}, ...
* Time zone items:: @sc{est}, @sc{pdt}, @sc{gmt}.
* Day of week items:: Monday and others.
* Relative items in date strings:: next tuesday, 2 years ago.
* Pure numbers in date strings:: 19931219, 1440.
* Seconds since the Epoch:: @@1078100502.
* Specifying time zone rules:: TZ="America/New_York", TZ="UTC0".
* Authors of get_date:: Bellovin, Eggert, Salz, Berets, et al.
@end menu
@@ -74,7 +75,7 @@ many flavors of items:
@itemize @bullet
@item calendar date items
@item time of the day items
@item time of day items
@item time zone items
@item day of the week items
@item relative items
@@ -108,7 +109,8 @@ abbreviations like @samp{AM}, @samp{DST}, @samp{EST}, @samp{first},
@cindex language, in dates
@cindex time zone item
The output of @command{date} is not always acceptable as a date string,
The output of the @command{date} command
is not always acceptable as a date string,
not only because of the language problem, but also because there is no
standard meaning for time zone items like @samp{IST}. When using
@command{date} to generate a date string intended to be parsed later,
@@ -225,7 +227,7 @@ day. Here are some examples, all of which represent the same time:
20:02-0500 # In @sc{est} (U.S. Eastern Standard Time).
@end example
More generally, the time of the day may be given as
More generally, the time of day may be given as
@samp{@var{hour}:@var{minute}:@var{second}}, where @var{hour} is
a number between 0 and 23, @var{minute} is a number between 0 and
59, and @var{second} is a number between 0 and 59 possibly followed by
@@ -257,7 +259,7 @@ of zone minutes. When a time zone correction is given this way, it
forces interpretation of the time relative to
Coordinated Universal Time (@sc{utc}), overriding any previous
specification for the time zone or the local time zone. The @var{minute}
part of the time of the day may not be elided when a time zone correction
part of the time of day may not be elided when a time zone correction
is used. This is the best way to specify a time zone correction by
fractional parts of an hour.
@@ -285,6 +287,10 @@ Australia than in the United States. Instead, it's better to use
unambiguous numeric time zone corrections like @samp{-0500}, as
described in the previous section.
If neither a time zone item nor a time zone correction is supplied,
time stamps are interpreted using the rules of the default time zone
(@pxref{Specifying time zone rules}).
@node Day of week items
@section Day of week items
@@ -372,7 +378,7 @@ the meaning of a zero-valued time displacement, but is preferred in
date strings like @samp{this thursday}.
When a relative item causes the resulting date to cross a boundary
where the clocks were adjusted, typically for daylight-saving time,
where the clocks were adjusted, typically for daylight saving time,
the resulting date and time are adjusted accordingly.
The fuzz in units can cause problems with relative items. For
@@ -413,7 +419,7 @@ calendar date.
If the decimal number is of the form @var{hh}@var{mm} and no other time
of day item appears before it in the date string, then @var{hh} is read
as the hour of the day and @var{mm} as the minute of the hour, for the
specified time of the day. @var{mm} can also be omitted.
specified time of day. @var{mm} can also be omitted.
If both a calendar date and a time of day appear to the left of a number
in the date string, but no relative item, then the number overrides the
@@ -427,7 +433,8 @@ If you precede a number with @samp{@@}, it represents an internal time
stamp as a count of seconds. The number can contain an internal
decimal point (either @samp{.} or @samp{,}); any excess precision not
supported by the internal representation is truncated toward minus
infinity.
infinity. Such a number cannot be combined with any other date
item, as it specifies a complete time stamp.
@cindex beginning of time, for @acronym{POSIX}
@cindex epoch, for @acronym{POSIX}
@@ -452,6 +459,57 @@ For example, on most systems @samp{@@915148799} represents 1998-12-31
@sc{utc}, and there is no way to represent the intervening leap second
1998-12-31 23:59:60 @sc{utc}.
@node Specifying time zone rules
@section Specifying time zone rules
@vindex TZ
Normally, dates are interpreted using the rules of the current time
zone, which in turn are specified by the @env{TZ} environment
variable, or by a system default if @env{TZ} is not set. To specify a
different set of default time zone rules that apply just to one date,
start the date with a string of the form @samp{TZ="@var{rule}"}. The
two quote characters (@samp{"}) must be present in the date, and any
quotes or backslashes within @var{rule} must be escaped by a
backslash.
For example, with the @acronym{GNU} @command{date} command you can
answer the question ``What time is it in New York when a Paris clock
shows 6:30am on October 31, 2004?'' by using a date beginning with
@samp{TZ="Europe/Paris"} as shown in the following shell transcript:
@example
$ export TZ="America/New_York"
$ date --date='TZ="Europe/Paris" 2004-10-31 06:30'
Sun Oct 31 01:30:00 EDT 2004
@end example
In this example, the @option{--date} operand begins with its own
@env{TZ} setting, so the rest of that operand is processed according
to @samp{Europe/Paris} rules, treating the string @samp{2004-10-31
06:30} as if it were in Paris. However, since the output of the
@command{date} command is processed according to the overall time zone
rules, it uses New York time. (Paris was normally six hours ahead of
New York in 2004, but this example refers to a brief Halloween period
when the gap was five hours.)
A @env{TZ} value is a rule that typically names a location in the
@uref{http://www.twinsun.com/tz/tz-link.htm, @samp{tz} database}.
A recent catalog of location names appears in the
@uref{http://twiki.org/cgi-bin/xtra/tzdate, TWiki Date and Time
Gateway}. A few non-@acronym{GNU} hosts require a colon before a
location name in a @env{TZ} setting, e.g.,
@samp{TZ=":America/New_York"}.
The @samp{tz} database includes a wide variety of locations ranging
from @samp{Arctic/Longyearbyen} to @samp{Antarctica/South_Pole}, but
if you are at sea and have your own private time zone, or if you are
using a non-@acronym{GNU} host that does not support the @samp{tz}
database, you may need to use a @acronym{POSIX} rule instead. Simple
@acronym{POSIX} rules like @samp{UTC0} specify a time zone without
daylight saving time; other rules can specify simple daylight saving
regimes. @xref{TZ Variable,, Specifying the Time Zone with @code{TZ},
libc, The GNU C Library}.
@node Authors of get_date
@section Authors of @code{get_date}

View File

@@ -22,16 +22,13 @@
<rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
Modified by Paul Eggert <eggert@twinsun.com> in August 1999 to do
the right thing about local DST, and in February 2004 to support
nanosecond-resolution time stamps. Unlike previous versions, this
version is reentrant. */
the right thing about local DST. Also modified by Paul Eggert
<eggert@cs.ucla.edu> in February 2004 to support
nanosecond-resolution time stamps, and in October 2004 to support
TZ strings in dates. */
/* FIXME: Check for arithmetic overflow in all cases, not just
some of them.
FIXME: The current code uses 'int' to count seconds; it should use
something like 'intmax_t' to support time stamps that don't fit in
32 bits. */
some of them. */
#ifdef HAVE_CONFIG_H
# include <config.h>
@@ -53,7 +50,11 @@
#include <ctype.h>
#include <limits.h>
#include <stdlib.h> /* for `free'; used by Bison 1.27 */
#include <stdlib.h>
#include <string.h>
#include "setenv.h"
#include "xalloc.h"
#if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII)
# define IN_CTYPE_DOMAIN(c) 1
@@ -64,23 +65,16 @@
#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c))
#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c))
#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c))
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
/* ISDIGIT differs from ISDIGIT_LOCALE, as follows:
/* ISDIGIT differs from isdigit, as follows:
- Its arg may be any int or unsigned int; it need not be an unsigned char.
- It's guaranteed to evaluate its argument exactly once.
- It's typically faster.
POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
ISDIGIT_LOCALE unless it's important to use the locale's definition
isdigit unless it's important to use the locale's definition
of `digit' even when the host does not conform to POSIX. */
#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
#include <string.h>
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__
# define __attribute__(x)
#endif
@@ -166,17 +160,17 @@ typedef struct
table local_time_zone_table[3];
} parser_control;
#define PC (* (parser_control *) parm)
#define YYLEX_PARAM parm
#define YYPARSE_PARAM parm
static int yyerror ();
static int yylex ();
union YYSTYPE;
static int yylex (union YYSTYPE *, parser_control *);
static int yyerror (parser_control *, char *);
%}
/* We want a reentrant parser. */
%pure_parser
/* We want a reentrant parser, even if the TZ manipulation and the calls to
localtime and gmtime are not reentrant. */
%pure-parser
%parse-param { parser_control *pc }
%lex-param { parser_control *pc }
/* This grammar has 13 shift/reduce conflicts. */
%expect 13
@@ -209,8 +203,8 @@ spec:
timespec:
'@' seconds
{
PC.seconds = $2;
PC.timespec_seen = true;
pc->seconds = $2;
pc->timespec_seen = true;
}
;
@@ -221,104 +215,104 @@ items:
item:
time
{ PC.times_seen++; }
{ pc->times_seen++; }
| local_zone
{ PC.local_zones_seen++; }
{ pc->local_zones_seen++; }
| zone
{ PC.zones_seen++; }
{ pc->zones_seen++; }
| date
{ PC.dates_seen++; }
{ pc->dates_seen++; }
| day
{ PC.days_seen++; }
{ pc->days_seen++; }
| rel
{ PC.rels_seen++; }
{ pc->rels_seen++; }
| number
;
time:
tUNUMBER tMERIDIAN
{
PC.hour = $1.value;
PC.minutes = 0;
PC.seconds.tv_sec = 0;
PC.seconds.tv_nsec = 0;
PC.meridian = $2;
pc->hour = $1.value;
pc->minutes = 0;
pc->seconds.tv_sec = 0;
pc->seconds.tv_nsec = 0;
pc->meridian = $2;
}
| tUNUMBER ':' tUNUMBER o_merid
{
PC.hour = $1.value;
PC.minutes = $3.value;
PC.seconds.tv_sec = 0;
PC.seconds.tv_nsec = 0;
PC.meridian = $4;
pc->hour = $1.value;
pc->minutes = $3.value;
pc->seconds.tv_sec = 0;
pc->seconds.tv_nsec = 0;
pc->meridian = $4;
}
| tUNUMBER ':' tUNUMBER tSNUMBER
{
PC.hour = $1.value;
PC.minutes = $3.value;
PC.seconds.tv_sec = 0;
PC.seconds.tv_nsec = 0;
PC.meridian = MER24;
PC.zones_seen++;
PC.time_zone = $4.value % 100 + ($4.value / 100) * 60;
pc->hour = $1.value;
pc->minutes = $3.value;
pc->seconds.tv_sec = 0;
pc->seconds.tv_nsec = 0;
pc->meridian = MER24;
pc->zones_seen++;
pc->time_zone = $4.value % 100 + ($4.value / 100) * 60;
}
| tUNUMBER ':' tUNUMBER ':' unsigned_seconds o_merid
{
PC.hour = $1.value;
PC.minutes = $3.value;
PC.seconds = $5;
PC.meridian = $6;
pc->hour = $1.value;
pc->minutes = $3.value;
pc->seconds = $5;
pc->meridian = $6;
}
| tUNUMBER ':' tUNUMBER ':' unsigned_seconds tSNUMBER
{
PC.hour = $1.value;
PC.minutes = $3.value;
PC.seconds = $5;
PC.meridian = MER24;
PC.zones_seen++;
PC.time_zone = $6.value % 100 + ($6.value / 100) * 60;
pc->hour = $1.value;
pc->minutes = $3.value;
pc->seconds = $5;
pc->meridian = MER24;
pc->zones_seen++;
pc->time_zone = $6.value % 100 + ($6.value / 100) * 60;
}
;
local_zone:
tLOCAL_ZONE
{ PC.local_isdst = $1; }
{ pc->local_isdst = $1; }
| tLOCAL_ZONE tDST
{ PC.local_isdst = $1 < 0 ? 1 : $1 + 1; }
{ pc->local_isdst = $1 < 0 ? 1 : $1 + 1; }
;
zone:
tZONE
{ PC.time_zone = $1; }
{ pc->time_zone = $1; }
| tDAYZONE
{ PC.time_zone = $1 + 60; }
{ pc->time_zone = $1 + 60; }
| tZONE tDST
{ PC.time_zone = $1 + 60; }
{ pc->time_zone = $1 + 60; }
;
day:
tDAY
{
PC.day_ordinal = 1;
PC.day_number = $1;
pc->day_ordinal = 1;
pc->day_number = $1;
}
| tDAY ','
{
PC.day_ordinal = 1;
PC.day_number = $1;
pc->day_ordinal = 1;
pc->day_number = $1;
}
| tUNUMBER tDAY
{
PC.day_ordinal = $1.value;
PC.day_number = $2;
pc->day_ordinal = $1.value;
pc->day_number = $2;
}
;
date:
tUNUMBER '/' tUNUMBER
{
PC.month = $1.value;
PC.day = $3.value;
pc->month = $1.value;
pc->day = $3.value;
}
| tUNUMBER '/' tUNUMBER '/' tUNUMBER
{
@@ -329,119 +323,119 @@ date:
you want portability, use the ISO 8601 format. */
if (4 <= $1.digits)
{
PC.year = $1;
PC.month = $3.value;
PC.day = $5.value;
pc->year = $1;
pc->month = $3.value;
pc->day = $5.value;
}
else
{
PC.month = $1.value;
PC.day = $3.value;
PC.year = $5;
pc->month = $1.value;
pc->day = $3.value;
pc->year = $5;
}
}
| tUNUMBER tSNUMBER tSNUMBER
{
/* ISO 8601 format. YYYY-MM-DD. */
PC.year = $1;
PC.month = -$2.value;
PC.day = -$3.value;
pc->year = $1;
pc->month = -$2.value;
pc->day = -$3.value;
}
| tUNUMBER tMONTH tSNUMBER
{
/* e.g. 17-JUN-1992. */
PC.day = $1.value;
PC.month = $2;
PC.year.value = -$3.value;
PC.year.digits = $3.digits;
pc->day = $1.value;
pc->month = $2;
pc->year.value = -$3.value;
pc->year.digits = $3.digits;
}
| tMONTH tSNUMBER tSNUMBER
{
/* e.g. JUN-17-1992. */
PC.month = $1;
PC.day = -$2.value;
PC.year.value = -$3.value;
PC.year.digits = $3.digits;
pc->month = $1;
pc->day = -$2.value;
pc->year.value = -$3.value;
pc->year.digits = $3.digits;
}
| tMONTH tUNUMBER
{
PC.month = $1;
PC.day = $2.value;
pc->month = $1;
pc->day = $2.value;
}
| tMONTH tUNUMBER ',' tUNUMBER
{
PC.month = $1;
PC.day = $2.value;
PC.year = $4;
pc->month = $1;
pc->day = $2.value;
pc->year = $4;
}
| tUNUMBER tMONTH
{
PC.day = $1.value;
PC.month = $2;
pc->day = $1.value;
pc->month = $2;
}
| tUNUMBER tMONTH tUNUMBER
{
PC.day = $1.value;
PC.month = $2;
PC.year = $3;
pc->day = $1.value;
pc->month = $2;
pc->year = $3;
}
;
rel:
relunit tAGO
{
PC.rel_ns = -PC.rel_ns;
PC.rel_seconds = -PC.rel_seconds;
PC.rel_minutes = -PC.rel_minutes;
PC.rel_hour = -PC.rel_hour;
PC.rel_day = -PC.rel_day;
PC.rel_month = -PC.rel_month;
PC.rel_year = -PC.rel_year;
pc->rel_ns = -pc->rel_ns;
pc->rel_seconds = -pc->rel_seconds;
pc->rel_minutes = -pc->rel_minutes;
pc->rel_hour = -pc->rel_hour;
pc->rel_day = -pc->rel_day;
pc->rel_month = -pc->rel_month;
pc->rel_year = -pc->rel_year;
}
| relunit
;
relunit:
tUNUMBER tYEAR_UNIT
{ PC.rel_year += $1.value * $2; }
{ pc->rel_year += $1.value * $2; }
| tSNUMBER tYEAR_UNIT
{ PC.rel_year += $1.value * $2; }
{ pc->rel_year += $1.value * $2; }
| tYEAR_UNIT
{ PC.rel_year += $1; }
{ pc->rel_year += $1; }
| tUNUMBER tMONTH_UNIT
{ PC.rel_month += $1.value * $2; }
{ pc->rel_month += $1.value * $2; }
| tSNUMBER tMONTH_UNIT
{ PC.rel_month += $1.value * $2; }
{ pc->rel_month += $1.value * $2; }
| tMONTH_UNIT
{ PC.rel_month += $1; }
{ pc->rel_month += $1; }
| tUNUMBER tDAY_UNIT
{ PC.rel_day += $1.value * $2; }
{ pc->rel_day += $1.value * $2; }
| tSNUMBER tDAY_UNIT
{ PC.rel_day += $1.value * $2; }
{ pc->rel_day += $1.value * $2; }
| tDAY_UNIT
{ PC.rel_day += $1; }
{ pc->rel_day += $1; }
| tUNUMBER tHOUR_UNIT
{ PC.rel_hour += $1.value * $2; }
{ pc->rel_hour += $1.value * $2; }
| tSNUMBER tHOUR_UNIT
{ PC.rel_hour += $1.value * $2; }
{ pc->rel_hour += $1.value * $2; }
| tHOUR_UNIT
{ PC.rel_hour += $1; }
{ pc->rel_hour += $1; }
| tUNUMBER tMINUTE_UNIT
{ PC.rel_minutes += $1.value * $2; }
{ pc->rel_minutes += $1.value * $2; }
| tSNUMBER tMINUTE_UNIT
{ PC.rel_minutes += $1.value * $2; }
{ pc->rel_minutes += $1.value * $2; }
| tMINUTE_UNIT
{ PC.rel_minutes += $1; }
{ pc->rel_minutes += $1; }
| tUNUMBER tSEC_UNIT
{ PC.rel_seconds += $1.value * $2; }
{ pc->rel_seconds += $1.value * $2; }
| tSNUMBER tSEC_UNIT
{ PC.rel_seconds += $1.value * $2; }
{ pc->rel_seconds += $1.value * $2; }
| tSDECIMAL_NUMBER tSEC_UNIT
{ PC.rel_seconds += $1.tv_sec * $2; PC.rel_ns += $1.tv_nsec * $2; }
{ pc->rel_seconds += $1.tv_sec * $2; pc->rel_ns += $1.tv_nsec * $2; }
| tUDECIMAL_NUMBER tSEC_UNIT
{ PC.rel_seconds += $1.tv_sec * $2; PC.rel_ns += $1.tv_nsec * $2; }
{ pc->rel_seconds += $1.tv_sec * $2; pc->rel_ns += $1.tv_nsec * $2; }
| tSEC_UNIT
{ PC.rel_seconds += $1; }
{ pc->rel_seconds += $1; }
;
seconds: signed_seconds | unsigned_seconds;
@@ -461,35 +455,35 @@ unsigned_seconds:
number:
tUNUMBER
{
if (PC.dates_seen
&& ! PC.rels_seen && (PC.times_seen || 2 < $1.digits))
PC.year = $1;
if (pc->dates_seen
&& ! pc->rels_seen && (pc->times_seen || 2 < $1.digits))
pc->year = $1;
else
{
if (4 < $1.digits)
{
PC.dates_seen++;
PC.day = $1.value % 100;
PC.month = ($1.value / 100) % 100;
PC.year.value = $1.value / 10000;
PC.year.digits = $1.digits - 4;
pc->dates_seen++;
pc->day = $1.value % 100;
pc->month = ($1.value / 100) % 100;
pc->year.value = $1.value / 10000;
pc->year.digits = $1.digits - 4;
}
else
{
PC.times_seen++;
pc->times_seen++;
if ($1.digits <= 2)
{
PC.hour = $1.value;
PC.minutes = 0;
pc->hour = $1.value;
pc->minutes = 0;
}
else
{
PC.hour = $1.value / 100;
PC.minutes = $1.value % 100;
pc->hour = $1.value / 100;
pc->minutes = $1.value % 100;
}
PC.seconds.tv_sec = 0;
PC.seconds.tv_nsec = 0;
PC.meridian = MER24;
pc->seconds.tv_sec = 0;
pc->seconds.tv_nsec = 0;
pc->meridian = MER24;
}
}
}
@@ -510,7 +504,7 @@ static table const meridian_table[] =
{ "A.M.", tMERIDIAN, MERam },
{ "PM", tMERIDIAN, MERpm },
{ "P.M.", tMERIDIAN, MERpm },
{ 0, 0, 0 }
{ NULL, 0, 0 }
};
static table const dst_table[] =
@@ -544,7 +538,7 @@ static table const month_and_day_table[] =
{ "THURS", tDAY, 4 },
{ "FRIDAY", tDAY, 5 },
{ "SATURDAY", tDAY, 6 },
{ 0, 0, 0 }
{ NULL, 0, 0 }
};
static table const time_units_table[] =
@@ -559,7 +553,7 @@ static table const time_units_table[] =
{ "MIN", tMINUTE_UNIT, 1 },
{ "SECOND", tSEC_UNIT, 1 },
{ "SEC", tSEC_UNIT, 1 },
{ 0, 0, 0 }
{ NULL, 0, 0 }
};
/* Assorted relative-time words. */
@@ -585,7 +579,7 @@ static table const relative_time_table[] =
{ "ELEVENTH", tUNUMBER, 11 },
{ "TWELFTH", tUNUMBER, 12 },
{ "AGO", tAGO, 1 },
{ 0, 0, 0 }
{ NULL, 0, 0 }
};
/* The time zone table. This table is necessarily incomplete, as time
@@ -645,7 +639,7 @@ static table const time_zone_table[] =
{ "GST", tZONE, HOUR (10) }, /* Guam Standard */
{ "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */
{ "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */
{ 0, 0, 0 }
{ NULL, 0, 0 }
};
/* Military time zone table. */
@@ -676,7 +670,7 @@ static table const military_table[] =
{ "X", tZONE, HOUR (11) },
{ "Y", tZONE, HOUR (12) },
{ "Z", tZONE, HOUR ( 0) },
{ 0, 0, 0 }
{ NULL, 0, 0 }
};
@@ -686,16 +680,14 @@ to_hour (long int hours, int meridian)
{
switch (meridian)
{
default: /* Pacify GCC. */
case MER24:
return 0 <= hours && hours < 24 ? hours : -1;
case MERam:
return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1;
case MERpm:
return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1;
default:
abort ();
}
/* NOTREACHED */
}
static long int
@@ -728,7 +720,7 @@ lookup_zone (parser_control const *pc, char const *name)
if (strcmp (name, tp->name) == 0)
return tp;
return 0;
return NULL;
}
#if ! HAVE_TM_GMTOFF
@@ -827,7 +819,7 @@ lookup_word (parser_control const *pc, char *word)
if (period_found && (tp = lookup_zone (pc, word)))
return tp;
return 0;
return NULL;
}
static int
@@ -993,11 +985,56 @@ yylex (YYSTYPE *lvalp, parser_control *pc)
/* Do nothing if the parser reports an error. */
static int
yyerror (char *s ATTRIBUTE_UNUSED)
yyerror (parser_control *pc ATTRIBUTE_UNUSED, char *s ATTRIBUTE_UNUSED)
{
return 0;
}
/* If *TM0 is the old and *TM1 is the new value of a struct tm after
passing it to mktime, return true if it's OK that mktime returned T.
It's not OK if *TM0 has out-of-range members. */
static bool
mktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t)
{
if (t == (time_t) -1)
{
/* Guard against falsely reporting an error when parsing a time
stamp that happens to equal (time_t) -1, on a host that
supports such a time stamp. */
tm1 = localtime (&t);
if (!tm1)
return false;
}
return ! ((tm0->tm_sec ^ tm1->tm_sec)
| (tm0->tm_min ^ tm1->tm_min)
| (tm0->tm_hour ^ tm1->tm_hour)
| (tm0->tm_mday ^ tm1->tm_mday)
| (tm0->tm_mon ^ tm1->tm_mon)
| (tm0->tm_year ^ tm1->tm_year));
}
/* A reasonable upper bound for the size of ordinary TZ strings.
Use heap allocation if TZ's length exceeds this. */
enum { TZBUFSIZE = 100 };
/* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated
otherwise. */
static char *
get_tz (char tzbuf[TZBUFSIZE])
{
char *tz = getenv ("TZ");
if (tz)
{
size_t tzsize = strlen (tz) + 1;
tz = (tzsize <= TZBUFSIZE
? memcpy (tzbuf, tz, tzsize)
: xmemdup (tz, tzsize));
}
return tz;
}
/* Parse a date/time string, storing the resulting time value into *RESULT.
The string itself is pointed to by P. Return true if successful.
P can be an incomplete or relative time specification; if so, use
@@ -1012,6 +1049,11 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
struct tm tm0;
parser_control pc;
struct timespec gettime_buffer;
unsigned char c;
bool tz_was_altered = false;
char *tz0 = NULL;
char tz0buf[TZBUFSIZE];
bool ok = true;
if (! now)
{
@@ -1027,6 +1069,44 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
if (! tmp)
return false;
while (c = *p, ISSPACE (c))
p++;
if (strncmp (p, "TZ=\"", 4) == 0)
{
char const *tzbase = p + 4;
size_t tzsize = 1;
char const *s;
for (s = tzbase; *s; s++, tzsize++)
if (*s == '\\')
{
s++;
if (! (*s == '\\' || *s == '"'))
break;
}
else if (*s == '"')
{
char *z;
char *tz1;
char tz1buf[TZBUFSIZE];
bool large_tz = TZBUFSIZE < tzsize;
bool setenv_ok;
tz0 = get_tz (tz0buf);
z = tz1 = large_tz ? xmalloc (tzsize) : tz1buf;
for (s = tzbase; *s != '"'; s++)
*z++ = *(s += *s == '\\');
*z = '\0';
setenv_ok = setenv ("TZ", tz1, 1) == 0;
if (large_tz)
free (tz1);
if (!setenv_ok)
goto fail;
tz_was_altered = true;
p = s + 1;
}
}
pc.input = p;
pc.year.value = tmp->tm_year;
pc.year.value += TM_YEAR_BASE;
@@ -1059,7 +1139,7 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
pc.local_time_zone_table[0].name = tmp->tm_zone;
pc.local_time_zone_table[0].type = tLOCAL_ZONE;
pc.local_time_zone_table[0].value = tmp->tm_isdst;
pc.local_time_zone_table[1].name = 0;
pc.local_time_zone_table[1].name = NULL;
/* Probe the names used in the next three calendar quarters, looking
for a tm_isdst different from the one we already have. */
@@ -1076,7 +1156,7 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
pc.local_time_zone_table[1].name = probe_tm->tm_zone;
pc.local_time_zone_table[1].type = tLOCAL_ZONE;
pc.local_time_zone_table[1].value = probe_tm->tm_isdst;
pc.local_time_zone_table[2].name = 0;
pc.local_time_zone_table[2].name = NULL;
}
break;
}
@@ -1095,10 +1175,10 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
pc.local_time_zone_table[i].type = tLOCAL_ZONE;
pc.local_time_zone_table[i].value = i;
}
pc.local_time_zone_table[i].name = 0;
pc.local_time_zone_table[i].name = NULL;
}
#else
pc.local_time_zone_table[0].name = 0;
pc.local_time_zone_table[0].name = NULL;
#endif
#endif
@@ -1110,146 +1190,177 @@ get_date (struct timespec *result, char const *p, struct timespec const *now)
daylight times. So if we see that abbreviation, we don't
know whether it's daylight time. */
pc.local_time_zone_table[0].value = -1;
pc.local_time_zone_table[1].name = 0;
pc.local_time_zone_table[1].name = NULL;
}
if (yyparse (&pc) != 0)
return false;
goto fail;
if (pc.timespec_seen)
{
*result = pc.seconds;
return true;
}
if (1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen
|| 1 < (pc.local_zones_seen + pc.zones_seen)
|| (pc.local_zones_seen && 1 < pc.local_isdst))
return false;
tm.tm_year = to_year (pc.year) - TM_YEAR_BASE + pc.rel_year;
tm.tm_mon = pc.month - 1 + pc.rel_month;
tm.tm_mday = pc.day + pc.rel_day;
if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
{
tm.tm_hour = to_hour (pc.hour, pc.meridian);
if (tm.tm_hour < 0)
return false;
tm.tm_min = pc.minutes;
tm.tm_sec = pc.seconds.tv_sec;
}
*result = pc.seconds;
else
{
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
pc.seconds.tv_nsec = 0;
}
if (1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen
|| 1 < (pc.local_zones_seen + pc.zones_seen)
|| (pc.local_zones_seen && 1 < pc.local_isdst))
goto fail;
/* Let mktime deduce tm_isdst if we have an absolute time stamp,
or if the relative time stamp mentions days, months, or years. */
if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day
| pc.rel_month | pc.rel_year)
tm.tm_isdst = -1;
/* But if the input explicitly specifies local time with or without
DST, give mktime that information. */
if (pc.local_zones_seen)
tm.tm_isdst = pc.local_isdst;
tm0 = tm;
Start = mktime (&tm);
if (Start == (time_t) -1)
{
/* Guard against falsely reporting errors near the time_t boundaries
when parsing times in other time zones. For example, if the min
time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
of UTC, then the min localtime value is 1970-01-01 08:00:00; if
we apply mktime to 1970-01-01 00:00:00 we will get an error, so
we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
zone by 24 hours to compensate. This algorithm assumes that
there is no DST transition within a day of the time_t boundaries. */
if (pc.zones_seen)
tm.tm_year = to_year (pc.year) - TM_YEAR_BASE;
tm.tm_mon = pc.month - 1;
tm.tm_mday = pc.day;
if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
{
tm = tm0;
if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE)
{
tm.tm_mday++;
pc.time_zone += 24 * 60;
}
else
{
tm.tm_mday--;
pc.time_zone -= 24 * 60;
}
Start = mktime (&tm);
tm.tm_hour = to_hour (pc.hour, pc.meridian);
if (tm.tm_hour < 0)
goto fail;
tm.tm_min = pc.minutes;
tm.tm_sec = pc.seconds.tv_sec;
}
else
{
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
pc.seconds.tv_nsec = 0;
}
if (Start == (time_t) -1)
return false;
}
/* Let mktime deduce tm_isdst if we have an absolute time stamp. */
if (pc.dates_seen | pc.days_seen | pc.times_seen)
tm.tm_isdst = -1;
/* But if the input explicitly specifies local time with or without
DST, give mktime that information. */
if (pc.local_zones_seen)
tm.tm_isdst = pc.local_isdst;
tm0 = tm;
if (pc.days_seen && ! pc.dates_seen)
{
tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
+ 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));
tm.tm_isdst = -1;
Start = mktime (&tm);
if (Start == (time_t) -1)
return false;
}
if (pc.zones_seen)
{
long int delta = pc.time_zone * 60;
time_t t1;
if (! mktime_ok (&tm0, &tm, Start))
{
if (! pc.zones_seen)
goto fail;
else
{
/* Guard against falsely reporting errors near the time_t
boundaries when parsing times in other time zones. For
example, suppose the input string "1969-12-31 23:00:00 -0100",
the current time zone is 8 hours ahead of UTC, and the min
time_t value is 1970-01-01 00:00:00 UTC. Then the min
localtime value is 1970-01-01 08:00:00, and mktime will
therefore fail on 1969-12-31 23:00:00. To work around the
problem, set the time zone to 1 hour behind UTC temporarily
by setting TZ="XXX1:00" and try mktime again. */
long int time_zone = pc.time_zone;
long int abs_time_zone = time_zone < 0 ? - time_zone : time_zone;
long int abs_time_zone_hour = abs_time_zone / 60;
int abs_time_zone_min = abs_time_zone % 60;
char tz1buf[sizeof "XXX+0:00"
+ sizeof pc.time_zone * CHAR_BIT / 3];
if (!tz_was_altered)
tz0 = get_tz (tz0buf);
sprintf (tz1buf, "XXX%s%ld:%02d", "-" + (time_zone < 0),
abs_time_zone_hour, abs_time_zone_min);
if (setenv ("TZ", tz1buf, 1) != 0)
goto fail;
tz_was_altered = true;
tm = tm0;
Start = mktime (&tm);
if (! mktime_ok (&tm0, &tm, Start))
goto fail;
}
}
if (pc.days_seen && ! pc.dates_seen)
{
tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7
+ 7 * (pc.day_ordinal - (0 < pc.day_ordinal)));
tm.tm_isdst = -1;
Start = mktime (&tm);
if (Start == (time_t) -1)
goto fail;
}
if (pc.zones_seen)
{
long int delta = pc.time_zone * 60;
time_t t1;
#ifdef HAVE_TM_GMTOFF
delta -= tm.tm_gmtoff;
delta -= tm.tm_gmtoff;
#else
time_t t = Start;
struct tm const *gmt = gmtime (&t);
if (! gmt)
return false;
delta -= tm_diff (&tm, gmt);
time_t t = Start;
struct tm const *gmt = gmtime (&t);
if (! gmt)
goto fail;
delta -= tm_diff (&tm, gmt);
#endif
t1 = Start - delta;
if ((Start < t1) != (delta < 0))
return false; /* time_t overflow */
Start = t1;
t1 = Start - delta;
if ((Start < t1) != (delta < 0))
goto fail; /* time_t overflow */
Start = t1;
}
/* Add relative date. */
if (pc.rel_year | pc.rel_month | pc.rel_day)
{
int year = tm.tm_year + pc.rel_year;
int month = tm.tm_mon + pc.rel_month;
int day = tm.tm_mday + pc.rel_day;
if (((year < tm.tm_year) ^ (pc.rel_year < 0))
| (month < tm.tm_mon) ^ (pc.rel_month < 0)
| (day < tm.tm_mday) ^ (pc.rel_day < 0))
goto fail;
tm.tm_year = year;
tm.tm_mon = month;
tm.tm_mday = day;
Start = mktime (&tm);
if (Start == (time_t) -1)
goto fail;
}
/* Add relative hours, minutes, and seconds. On hosts that support
leap seconds, ignore the possibility of leap seconds; e.g.,
"+ 10 minutes" adds 600 seconds, even if one of them is a
leap second. Typically this is not what the user wants, but it's
too hard to do it the other way, because the time zone indicator
must be applied before relative times, and if mktime is applied
again the time zone will be lost. */
{
long int sum_ns = pc.seconds.tv_nsec + pc.rel_ns;
long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
time_t t0 = Start;
long int d1 = 60 * 60 * pc.rel_hour;
time_t t1 = t0 + d1;
long int d2 = 60 * pc.rel_minutes;
time_t t2 = t1 + d2;
long int d3 = pc.rel_seconds;
time_t t3 = t2 + d3;
long int d4 = (sum_ns - normalized_ns) / BILLION;
time_t t4 = t3 + d4;
if ((d1 / (60 * 60) ^ pc.rel_hour)
| (d2 / 60 ^ pc.rel_minutes)
| ((t1 < t0) ^ (d1 < 0))
| ((t2 < t1) ^ (d2 < 0))
| ((t3 < t2) ^ (d3 < 0))
| ((t4 < t3) ^ (d4 < 0)))
goto fail;
result->tv_sec = t4;
result->tv_nsec = normalized_ns;
}
}
/* Add relative hours, minutes, and seconds. Ignore leap seconds;
i.e. "+ 10 minutes" means 600 seconds, even if one of them is a
leap second. Typically this is not what the user wants, but it's
too hard to do it the other way, because the time zone indicator
must be applied before relative times, and if mktime is applied
again the time zone will be lost. */
{
long int sum_ns = pc.seconds.tv_nsec + pc.rel_ns;
long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION;
time_t t0 = Start;
long int d1 = 60 * 60 * pc.rel_hour;
time_t t1 = t0 + d1;
long int d2 = 60 * pc.rel_minutes;
time_t t2 = t1 + d2;
long int d3 = pc.rel_seconds;
time_t t3 = t2 + d3;
long int d4 = (sum_ns - normalized_ns) / BILLION;
time_t t4 = t3 + d4;
goto done;
if ((d1 / (60 * 60) ^ pc.rel_hour)
| (d2 / 60 ^ pc.rel_minutes)
| ((t1 < t0) ^ (d1 < 0))
| ((t2 < t1) ^ (d2 < 0))
| ((t3 < t2) ^ (d3 < 0))
| ((t4 < t3) ^ (d4 < 0)))
return false;
result->tv_sec = t4;
result->tv_nsec = normalized_ns;
return true;
}
fail:
ok = false;
done:
if (tz_was_altered)
ok &= (tz0 ? setenv ("TZ", tz0, 1) : unsetenv ("TZ")) == 0;
if (tz0 != tz0buf)
free (tz0);
return ok;
}
#if TEST
@@ -1264,7 +1375,7 @@ main (int ac, char **av)
printf ("Enter date, or blank line to exit.\n\t> ");
fflush (stdout);
buff[BUFSIZ - 1] = 0;
buff[BUFSIZ - 1] = '\0';
while (fgets (buff, BUFSIZ - 1, stdin) && buff[0])
{
struct timespec d;
@@ -1288,4 +1399,4 @@ main (int ac, char **av)
}
return 0;
}
#endif /* defined TEST */
#endif /* TEST */

View File

@@ -1,5 +1,5 @@
/* Emulate getpagesize on systems that lack it.
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@
# endif
#endif
#ifndef getpagesize
#if !defined getpagesize && HAVE_SYS_PARAM_H
# include <sys/param.h>
# ifdef EXEC_PAGESIZE
# define getpagesize() EXEC_PAGESIZE

View File

@@ -495,7 +495,6 @@ not_equal_tm (const struct tm *a, const struct tm *b)
| (a->tm_mday ^ b->tm_mday)
| (a->tm_mon ^ b->tm_mon)
| (a->tm_year ^ b->tm_year)
| (a->tm_mday ^ b->tm_mday)
| (a->tm_yday ^ b->tm_yday)
| (a->tm_isdst ^ b->tm_isdst));
}

View File

@@ -1,5 +1,5 @@
# getpagesize.m4 serial 1
dnl Copyright (C) 2002 Free Software Foundation, Inc.
# getpagesize.m4 serial 2
dnl Copyright (C) 2002, 2004 Free Software Foundation, Inc.
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
dnl Public License, this file may be distributed as part of a program
@@ -9,7 +9,7 @@ dnl the same distribution terms as the rest of that program.
AC_DEFUN([gl_GETPAGESIZE],
[
dnl Prerequisites of lib/getpagesize.h.
AC_CHECK_HEADERS_ONCE(unistd.h)
AC_CHECK_HEADERS_ONCE(sys/param.h unistd.h)
AC_CHECK_HEADERS(OS.h)
AC_CHECK_FUNCS(getpagesize)
])