summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/config.guess9
-rwxr-xr-xconfig/install-sh7
-rw-r--r--config/texinfo.tex17
-rw-r--r--doc/getdate.texi74
-rw-r--r--lib/getdate.y667
-rw-r--r--lib/getpagesize.h4
-rw-r--r--lib/mktime.c1
-rw-r--r--m4/getpagesize.m46
8 files changed, 484 insertions, 301 deletions
diff --git a/config/config.guess b/config/config.guess
index 7d0185e01..c28419dd5 100644
--- a/config/config.guess
+++ b/config/config.guess
@@ -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
diff --git a/config/install-sh b/config/install-sh
index dd97db7aa..0b65ee871 100755
--- a/config/install-sh
+++ b/config/install-sh
@@ -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=
diff --git a/config/texinfo.tex b/config/texinfo.tex
index e758cedae..b4b9016f1 100644
--- a/config/texinfo.tex
+++ b/config/texinfo.tex
@@ -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}%
diff --git a/doc/getdate.texi b/doc/getdate.texi
index 1d312a689..9280c5087 100644
--- a/doc/getdate.texi
+++ b/doc/getdate.texi
@@ -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}
diff --git a/lib/getdate.y b/lib/getdate.y
index e8cbfeb6b..ec8c19250 100644
--- a/lib/getdate.y
+++ b/lib/getdate.y
@@ -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;
- }
-
- /* 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;
+ 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;
+
+ 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.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;
+ }
- /* 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;
+ /* 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;
- tm0 = tm;
+ /* 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;
- Start = mktime (&tm);
+ tm0 = tm;
- if (Start == (time_t) -1)
- {
+ Start = mktime (&tm);
- /* 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)
+ if (! mktime_ok (&tm0, &tm, Start))
{
- tm = tm0;
- if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE)
- {
- tm.tm_mday++;
- pc.time_zone += 24 * 60;
- }
+ if (! pc.zones_seen)
+ goto fail;
else
{
- tm.tm_mday--;
- pc.time_zone -= 24 * 60;
+ /* 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;
}
- Start = mktime (&tm);
}
- if (Start == (time_t) -1)
- return false;
- }
-
- 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.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;
+ 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;
-
- 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;
- }
+ goto done;
+
+ 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 */
diff --git a/lib/getpagesize.h b/lib/getpagesize.h
index 80d9eb3be..e63c1c708 100644
--- a/lib/getpagesize.h
+++ b/lib/getpagesize.h
@@ -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
diff --git a/lib/mktime.c b/lib/mktime.c
index a017a51c8..772b4f347 100644
--- a/lib/mktime.c
+++ b/lib/mktime.c
@@ -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));
}
diff --git a/m4/getpagesize.m4 b/m4/getpagesize.m4
index f1f4c42d4..a2f818b62 100644
--- a/m4/getpagesize.m4
+++ b/m4/getpagesize.m4
@@ -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)
])