#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	Makefile
#	settz.3
#	tzfile.5
#	tzcomp.8
#	tzfile.h
#	tzcomp.c
#	scheck.c
#	strchr.c
#	mkdir.c
#	tzdump.c
#	settz.c
#	years.sh
#	asia
#	australasia
#	europe
#	etcetera
#	northamerica
#	pacificnew
# This archive created: Fri Mar  7 17:02:24 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(620 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
@(#)README	2.1

Please send comments or information to seismo!elsie!ado (with, perhaps,
carbon copes to cbosgd!mark, seismo!linus!encore!necis!geo, and
seismo!munnari!kre, who are responsible for any good ideas that show up here).

Historical local time information has been included here not because it should
be part of the standard (or, indeed, anyone's product), but rather to:

*	give people an idea of the variety of local time rules that have
	existed in the past and thus an idea of the variety that may be
	expected in the future;

*	provide a test of the generality of the local time rule description
	system.
SHAR_EOF
if test 620 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 620 characters)'
fi
fi
echo shar: extracting "'Makefile'" '(1713 characters)'
if test -f 'Makefile'
then
	echo shar: will not over-write existing file "'Makefile'"
else
cat << \SHAR_EOF > 'Makefile'
# @(#)Makefile	2.1

# If you want something other than Eastern United States time used on your
# system, change the line below (after finding the zone you want in the
# time zone files, or adding it to a time zone file).
# Alternately, if you discover you've got the wrong time zone, you can just
#	tzcomp -l rightzone

LOCALTIME=	Eastern

# Use an absolute path name for TZDIR unless you're just testing the software.

TZDIR=		/etc/tzdir

# LINTFLAGS is set for 4.1bsd systems.  If you're using System V, you'll want
# to comment out the "LINTFLAGS=" line.

LINTFLAGS=	-phbaaxc

DEBUG=
LFLAGS=
CFLAGS=		$(DEBUG) -O -DOBJECTID -DTZDIR=\"$(TZDIR)\"

TZCSRCS=	tzcomp.c scheck.c strchr.c mkdir.c
TZCOBJS=	tzcomp.o scheck.o strchr.o mkdir.o
TZDSRCS=	tzdump.c settz.c
TZDOBJS=	tzdump.o settz.o
DOCS=		README Makefile settz.3 tzfile.5 tzcomp.8
SOURCES=	tzfile.h $(TZCSRCS) $(TZDSRCS) years.sh
DATA=		asia australasia europe etcetera northamerica pacificnew
ENCHILADA=	$(DOCS) $(SOURCES) $(DATA)

all:	REDID_BINARIES tzdump

REDID_BINARIES:	$(TZDIR) tzcomp $(DATA) years
	tzcomp -l $(LOCALTIME) -d $(TZDIR) $(DATA)
	cp /dev/null $@

tzdump:	$(TZDOBJS)
	$(CC) $(LFLAGS) $(TZDOBJS) -o $@

tzcomp:	$(TZCOBJS)
	$(CC) $(LFLAGS) $(TZCOBJS) -o $@

$(TZDIR):
	mkdir $@

years:	years.sh
	rm -f $@
	cp $? $@
	chmod 555 $@

BUNDLE1:	$(DOCS)
	bundle $(DOCS) > BUNDLE1

BUNDLE2:	$(SOURCES)
	bundle $(SOURCES) > BUNDLE2

BUNDLE3:	$(DATA)
	bundle $(DATA) > BUNDLE3

$(ENCHILADA):
	sccs get $(REL) $(REV) $@

sure:	$(TZCSRCS) $(TZDSRCS)
	lint $(LINTFLAGS) $(TZCSRCS)
	lint $(LINTFLAGS) $(TZDSRCS)

clean:
	rm -f core *.o *.out REDID_BINARIES years tzdump tzcomp BUNDLE \#*

CLEAN:	clean
	sccs clean

tzdump.o tzcomp.o settz.o:	tzfile.h
SHAR_EOF
if test 1713 -ne "`wc -c < 'Makefile'`"
then
	echo shar: error transmitting "'Makefile'" '(should have been 1713 characters)'
fi
fi
echo shar: extracting "'settz.3'" '(1606 characters)'
if test -f 'settz.3'
then
	echo shar: will not over-write existing file "'settz.3'"
else
cat << \SHAR_EOF > 'settz.3'
.TH SETTZ 3 
.SH NAME
settz, newctime, newlocaltime \- convert date and time to ASCII
.SH SYNOPSIS
.nf
.B settz(zonename)
.B char *zonename;
.PP
.B char *newctime(clock)
.B long *clock;
.PP
.B
#include "time.h"
.PP
.B struct tm *newlocaltime(clock)
.B long *clock;
.PP
.B char *tz_abbr;
.SH DESCRIPTION
.I Settz
sets time conversion information used by
.IR newlocaltime .
If
.I zonename
begins with a slash,
it is used as the absolute pathname of the
.IR tzfile (5)-format
file from which to read the time conversion information;
if
.I zonename
begins with some other character,
it is used as a pathname relative to the standard time conversion information
directory.  A call of the form
.ti +.5i
.B
settz("")
.br
causes built-in information about GMT to be used; a call of the form
.ti +.5i
.B
settz((char *) 0)
.br
is treated as if it were a call of the form
.ti +.5i
.B
settz("localtime")
.PP
.I Newlocaltime
has the same argument and return value as
.IR localtime .
If
.I newlocaltime
is called before
.I settz
is called,
.I newlocaltime
calls
.I settz
with the value returned by
.B
getenv("TZ").
.I Newlocaltime
sets
tz_abbr
to a pointer to an 
ASCII string that's the time zone abbreviation to be used with
.IR newlocaltime 's
return value.
.PP
.I Newctime
returns
.IR "asctime(newlocaltime(*clock))" .
.SH DIAGNOSTICS
.I Settz
returns zero if all seems well; it returns negative one otherwise
(and sets things up so that its built-in information about GMT is used).
.SH FILES
/etc/tzdir	standard time conversion information directory
.SH "SEE ALSO"
ctime(3), getenv(3), tzfile(5)
.. @(#)settz.3	2.1
SHAR_EOF
if test 1606 -ne "`wc -c < 'settz.3'`"
then
	echo shar: error transmitting "'settz.3'" '(should have been 1606 characters)'
fi
fi
echo shar: extracting "'tzfile.5'" '(2100 characters)'
if test -f 'tzfile.5'
then
	echo shar: will not over-write existing file "'tzfile.5'"
else
cat << \SHAR_EOF > 'tzfile.5'
.TH TZFILE 5
.SH NAME
tzfile \- time zone information
.SH SYNOPSIS
.B
#include "tzfile.h"
.SH DESCRIPTION
The time zone information files used by
.IR settz (3)
and
.IR newlocaltime (3)
begin with a
.I tzinfo
structure (as defined in the include file
.B 
"tzfile.h"\c
):
.sp
.nf
.in +.5i
.ta .5i +\w'unsigned short  'u
struct tzhead {
	char	tzh_reserved[14];
	unsigned short	tzh_timecnt;
	unsigned short	tzh_typecnt;
	unsigned short	tzh_charcnt;
};
.in -.5i
.fi
.PP
The
.B tzh_reserved
element is currently unused.
The
.B tzh_timecnt
element gives the number of "transition times" for which data is stored
in the file;
the
.B tzh_typecnt
(which must not be zero)
element gives the number of "local time types" for which data is stored
in the file;
and the
.B tzh_charcnt
element gives the number of characters of "time zone abbreviation strings"
stored in the file.
.PP
The above header is followed by
.B tzh_timecnt
values of type
.BR long ,
sorted in ascending order;
each is used as a transition time (as returned by
.IR time (2))
at which the rules for computing local time change.
Next come
.B tzh_timecnt
values of type
.BR "unsigned char" ;
each one tells which of the different types of "local time" described in the
file is associated with the same-indexed transition time.
These values serve as indices into an array of
.B ttinfo
structures that appears next in the file; 
these structures are defined as follows:
.in +.5i
.sp
.nf
.ta .5i +\w'unsigned short  'u
struct ttinfo {	
	long	tt_gmtoff;
	int	tt_isdst;
	unsigned int	tt_abbrind;
};
.in -.5i
.fi
.sp
In each structure,
.B tt_gmtoff
gives the number of seconds to be added to GMT,
.B
tt_isdst
tells whether
.B
tm_isdst
should be set by
.IR newlocaltime (3),
and
.B tt_abbrind
serves as an index into the array of time zone abbreviation chaaracters
that follow the
.B ttinfo
structure(s) in the file.
.PP
.I Newlocaltime
uses the first
.B ttinfo
structure in the file
if either
.B tzh_timecnt
is zero or
.IR newlocaltime 's
argument is less than
the first transition time recorded in the file.
.SH SEE ALSO
settz(3)
.. @(#)tzfile.5	2.1
SHAR_EOF
if test 2100 -ne "`wc -c < 'tzfile.5'`"
then
	echo shar: error transmitting "'tzfile.5'" '(should have been 2100 characters)'
fi
fi
echo shar: extracting "'tzcomp.8'" '(5479 characters)'
if test -f 'tzcomp.8'
then
	echo shar: will not over-write existing file "'tzcomp.8'"
else
cat << \SHAR_EOF > 'tzcomp.8'
.TH TZCOMP 8
.SH NAME
tzcomp \- time zone compiler
.SH SYNOPSIS
.B tzcomp
[
.B \-d
directory ] [
.B \-l
localtime ] [ filename ... ]
.SH DESCRIPTION
.I Tzcomp
reads text from the file(s) named on the command line
and creates the time conversion information files specified in this input.
If a
.I filename
is
.BR ` - ',
the standard input is read.
.PP
These options are available:
.TP
.BI "\-d " directory
Create time conversion information files in the named directory rather than
in the standard directory named below.
.TP
.BI "\-l " localtime
Use the given time zone as local time.
.PP
Input lines are made up of fields.
Fields are separated from one another by any number of white space characters.
Leading and trailing white space on input lines is ignored.
An unquoted sharp character (#) in the input introduces a comment which extends
to the end of the line the sharp character appears on.
White space characters and sharp characters may be enclosed in double quotes
(") if they're to be used as part of a field.
Any line which is blank (after comment stripping) is ignored.
Non-blank lines are expected to be of one of three
types:  rule lines, zone lines, and link lines.
.PP
A rule line has the form
.nf
.B
.ti +.5i
.ta \w'Rule 'u +\w'MostNA 'u +\w'FROM 'u +\w'1973 'u +\w'TYPE 'u +\w'Apr 'u +\w'lastSun 'u +\w'2:00 'u +\w'SAVE 'u
.sp
Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
.sp
For example:
.ti +.5i
.sp
Rule	MostNA	1969	1973	-	Apr	lastSun	2:00	1:00	D
.sp
.fi
The fields that make up a rule line are:
.TP
.B NAME
Gives the (arbitrary) name of the set of rules this rule is part of.
.TP
.B FROM
Gives the first year in which the rule applies.
.TP
.B TO
Gives the last year in which the rule applies.
The word
.RB ` only '
may be used to repeat the value of the
.B
FROM
field.
.TP
.B TYPE
Gives the type of year in which the year applies.  If
.B TYPE
is
.B
"-"
then the rule applies in all years between
.B FROM
and
.B TO
inclusive.
If
.B TYPE
is something else, then the command
.B
.ti +.5i
years from to type
.br
is executed with arguments
.IR from ,
.IR to ,
and
.I type
taken from the rule line; the rule applies only in those years
printed by the
.I years
command.

The distributed
.I years
command is a shell script that handles year types
.B uspres
(United States presidential election years)
and
.B nonpres
(all other years);
other year types may be added by changing the script.
.TP
.B IN
Names the month in which the rule takes effect.  Month names may be
abbreviated.
.TP
.B ON
Gives the day on which the rule takes effect.
Recognized forms include:
.nf
.in +.5i
.sp
.ta \w'lastSun  'u
5	the fifth of the month
lastSun	the last Sunday in the month
lastMon	the last Monday in the month
Sun>=8	first Sunday on or after the eighth
Sun<=25	last Sunday on or before the 25th
.fi
.in -.5i
.sp
Names of days of the week may be abbreviated or spelled out in full.
Note that there must be no spaces within the
.B ON
field.
.TP
.B AT
Gives the time of day at which the rule takes affect.
Recognized forms include:
.nf
.in +.5i
.sp
.ta \w'1:28:13  'u
2	time in hours
2:00	time in hours and minutes
15:00	24-hour format time (for times after noon)
1:28:14	time in hours, minutes, and seconds
.fi
.in -.5i
.sp
Any of these forms may be followed by the letter 'w' if the given time is
local "wall clock" time or 's' if the given time is local "standard" time;
in the absence of 'w' or 's', wall clock time is assumed.
.TP
.B SAVE
Gives the amount of time to be added to local standard time when the rule is in
effect (although, of course, the 'w' and 's' suffixes are not used).
This field has the same format as the
.B AT
field.
.TP
.B LETTER/S
Gives the "variable part" (for example, the 'S' or 'D' in "EST" or "EDT")
of time zone abbreviations to be used when this rule is in effect.
If this field is
.B
"-",
the variable part is null.
.PP
A zone line has the form
.sp
.nf
.ti +.5i
.ta \w'Zone 'u +\w'Eastern 'u +\w'GMTOFF 'u +\w'MostNA 'u
Zone	NAME	GMTOFF	RULES	FORMAT
.sp
For example:
.sp
.ti +.5i
Zone	Eastern	-5:00	MostNA	E%sT
.sp
.fi
The fields that make up a zone line are:
.TP
.B NAME
The name of the time zone.
This is the name used in creating the time conversion information file for the
zone.
.TP
.B GMTOFF
The amount of time to add to GMT to get standard time in this zone.
This field has the same format as the
.B AT
and
.B SAVE
fields of rule lines;
begin the field with a minus sign if time must be subtracted from GMT.
.TP
.B RULES
The name of the rule(s) that apply in the time zone.
If this field is
.B
"-"
then standard time always applies in the time zone.
.TP
.B FORMAT
The format for time zone abbreviations in this time zone.
The pair of characters
.B
"%s"
is used to show where the "variable part" of the time zone abbreviation goes.
.PP
A link line has the form
.sp
.nf
.ti +.5i
.ta \w'Link 'u +\w'LINK-FROM 'u
Link	LINK-FROM	LINK-TO
.sp
For example:
.sp
.ti +.5i
Link	Eastern		EST5EDT
.sp
.fi
The
.B LINK-FROM
field should appear as the
.B NAME
field in some zone line;
the
.B LINK-TO
field is used as an alternate name for that zone.
.PP
Lines may appear in any order in the input.
.SH NOTE
For areas with more than two types of local time,
you may get to use local standard time in "AT" field of the earliest
transition time's rule to ensure that
the earliest transition time recorded in the compiled file is correct.
.SH FILES
/etc/tzdir	standard directory used for created files
.SH "SEE ALSO"
settz(3), tzfile(5)
.. @(#)tzcomp.8	2.1
SHAR_EOF
if test 5479 -ne "`wc -c < 'tzcomp.8'`"
then
	echo shar: error transmitting "'tzcomp.8'" '(should have been 5479 characters)'
fi
fi
echo shar: extracting "'tzfile.h'" '(1409 characters)'
if test -f 'tzfile.h'
then
	echo shar: will not over-write existing file "'tzfile.h'"
else
cat << \SHAR_EOF > 'tzfile.h'
/* @(#)tzfile.h	2.1 */

/*
** Information about time zone files.
*/

#ifndef TZDIR
#define TZDIR		"/etc/tzdir"	/* Time zone object file directory */
#endif

#ifndef TZDEFAULT
#define TZDEFAULT	"localtime"
#endif

struct ttinfo {				/* time type information */
	long		tt_gmtoff;	/* GMT offset in seconds */
	int		tt_isdst;	/* used to set tm_isdst */
	unsigned int	tt_abbrind;	/* abbreviation list index */
};

/*
** Each file begins with. . .
*/

struct tzhead {
	char		tzh_reserved[14];	/* reserved for future use */
	unsigned short	tzh_timecnt;		/* number of transition times */
	unsigned short	tzh_typecnt;		/* number of local time types */
	unsigned short	tzh_charcnt;		/* number of abbr. chars */
};

/*
** . . .followed by. . .
**
**	tzh_timecnt (long)s		transition times as returned by time(2)
**	tzh_timecnt (unsigned char)s	types of local time starting at above
**	tzh_typecnt (struct ttinfo)s	information for each time type
**	tzh_charcnt (char)s		'\0'-terminated zone abbreviaton strings
*/

/*
** In the current implementation, "settz()" refuses to deal with files that
** exceed any of the limits below.
*/

#ifndef TZ_MAX_TIMES
#define TZ_MAX_TIMES	170	/* Maximum number of transition times */
#endif

#ifndef TZ_MAX_TYPES
#define TZ_MAX_TYPES	10	/* Maximum number of local time types */
#endif

#ifndef TZ_MAX_CHARS
#define TZ_MAX_CHARS	50	/* Maximum number of abbreviation characters */
#endif
SHAR_EOF
if test 1409 -ne "`wc -c < 'tzfile.h'`"
then
	echo shar: error transmitting "'tzfile.h'" '(should have been 1409 characters)'
fi
fi
echo shar: extracting "'tzcomp.c'" '(24558 characters)'
if test -f 'tzcomp.c'
then
	echo shar: will not over-write existing file "'tzcomp.c'"
else
cat << \SHAR_EOF > 'tzcomp.c'
#

#include "stdio.h"

#ifdef OBJECTID
static char	sccsid[] = "@(#)tzcomp.c	2.1";
#endif

#include "tzfile.h"
#include "ctype.h"

#ifndef alloc_t
#define alloc_t	unsigned
#endif

#ifndef MAL
#define MAL	NULL
#endif

#ifndef BUFSIZ
#define BUFSIZ	1024
#endif

#ifndef TRUE
#define TRUE	1
#define FALSE	0
#endif

#ifdef lint
#define scheck(string, format)	(format)
#endif
#ifndef lint
extern char *	scheck();
#endif

extern char *	calloc();
extern char *	malloc();
extern char *	optarg;
extern int	optind;
extern FILE *	popen();
extern char *	realloc();
extern char *	sprintf();
extern char *	strcat();
extern char *	strchr();
extern char *	strcpy();

static int	errors;
static char *	filename;
static char **	getfields();
static int	linenum;
static char *	progname;
static long	rpytime();
static long	tadd();

#define	SECS_PER_MIN	60L
#define MINS_PER_HOUR	60L
#define HOURS_PER_DAY	24L
#define DAYS_PER_YEAR	365L	/* Except in leap years */
#define	SECS_PER_HOUR	(SECS_PER_MIN * MINS_PER_HOUR)
#define SECS_PER_DAY	(SECS_PER_HOUR * HOURS_PER_DAY)
#define SECS_PER_YEAR	(SECS_PER_DAY * DAYS_PER_YEAR)

#define EPOCH_YEAR	1970
#define EPOCH_WDAY	TM_THURSDAY

/*
** Values a la localtime(3)
*/

#define TM_JANUARY	0
#define TM_FEBRUARY	1
#define TM_MARCH	2
#define TM_APRIL	3
#define TM_MAY		4
#define TM_JUNE		5
#define TM_JULY		6
#define TM_AUGUST	7
#define TM_SEPTEMBER	8
#define TM_OCTOBER	9
#define TM_NOVEMBER	10
#define TM_DECEMBER	11

#define TM_SUNDAY	0
#define TM_MONDAY	1
#define TM_TUESDAY	2
#define TM_WEDNESDAY	3
#define TM_THURSDAY	4
#define TM_FRIDAY	5
#define TM_SATURDAY	6

/*
** Line codes.
*/

#define LC_RULE		0
#define LC_ZONE		1
#define LC_LINK		2

/*
** Which fields are which on a Zone line.
*/

#define ZF_NAME		1
#define ZF_GMTOFF	2
#define ZF_RULE		3
#define ZF_FORMAT	4
#define ZONE_FIELDS	5

/*
** Which files are which on a Rule line.
*/

#define	RF_NAME		1
#define RF_LOYEAR	2
#define RF_HIYEAR	3
#define RF_COMMAND	4
#define RF_MONTH	5
#define RF_DAY		6
#define RF_TOD		7
#define RF_STDOFF	8
#define RF_ABBRVAR	9
#define RULE_FIELDS	10

/*
** Which fields are which on a Link line.
*/

#define LF_FROM		1
#define LF_TO		2
#define LINK_FIELDS	3

struct rule {
	char *	r_filename;
	int	r_linenum;
	char *	r_name;

	long	r_loyear;	/* for example, 1986 */
	long	r_hiyear;	/* for example, 1986 */
	char *	r_yrtype;

	long	r_month;	/* 0..11 */

	int	r_dycode;	/* see below */
	long	r_dayofmonth;
	long	r_wday;

	long	r_tod;		/* time from midnight */
	int	r_todisstd;	/* above is standard time if TRUE */
				/* above is wall clock time if FALSE */
	long	r_stdoff;	/* offset from standard time */
	char *	r_abbrvar;	/* variable part of time zone abbreviation */

	int	r_type;	/* used when creating output files */
};

/*
**	r_dycode		r_dayofmonth	r_wday
*/
#define DC_DOM		0	/* 1..31 */	/* unused */
#define DC_DOWGEQ	1	/* 1..31 */	/* 0..6 (Sun..Sat) */
#define DC_DOWLEQ	2	/* 1..31 */	/* 0..6 (Sun..Sat) */

static struct rule *	rules;
static int		nrules;	/* number of rules */

struct zone {
	char *		z_filename;
	int		z_linenum;

	char *		z_name;
	long		z_gmtoff;
	char *		z_rule;
	char *		z_format;

	struct rule *	z_rules;
	int		z_nrules;
};

static struct zone *	zones;
static int		nzones;	/* number of zones */

struct link {
	char *		l_filename;
	int		l_linenum;
	char *		l_from;
	char *		l_to;
};

static struct link *	links;
static int		nlinks;

struct lookup {
	char *		l_word;
	long		l_value;
};

static struct lookup *	byword();

static struct lookup	line_codes[] = {
	"Rule",		LC_RULE,
	"Zone",		LC_ZONE,
	"Link",		LC_LINK,
	NULL,		0
};

static struct lookup	mon_names[] = {
	"January",	TM_JANUARY,
	"February",	TM_FEBRUARY,
	"March",	TM_MARCH,
	"April",	TM_APRIL,
	"May",		TM_MAY,
	"June",		TM_JUNE,
	"July",		TM_JULY,
	"August",	TM_AUGUST,
	"September",	TM_SEPTEMBER,
	"October",	TM_OCTOBER,
	"November",	TM_NOVEMBER,
	"December",	TM_DECEMBER,
	NULL,		0
};

static struct lookup	wday_names[] = {
	"Sunday",	TM_SUNDAY,
	"Monday",	TM_MONDAY,
	"Tuesday",	TM_TUESDAY,
	"Wednesday",	TM_WEDNESDAY,
	"Thursday",	TM_THURSDAY,
	"Friday",	TM_FRIDAY,
	"Saturday",	TM_SATURDAY,
	NULL,		0
};

static struct lookup	lasts[] = {
	"last-Sunday",		TM_SUNDAY,
	"last-Monday",		TM_MONDAY,
	"last-Tuesday",		TM_TUESDAY,
	"last-Wednesday",	TM_WEDNESDAY,
	"last-Thursday",	TM_THURSDAY,
	"last-Friday",		TM_FRIDAY,
	"last-Saturday",	TM_SATURDAY,
	NULL,			0
};

static long	mon_lengths[] = {	/* ". . .knuckles are 31. . ." */
	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};

static struct tzhead	h;
static long		ats[TZ_MAX_TIMES];
static unsigned char	types[TZ_MAX_TIMES];
static struct ttinfo	ttis[TZ_MAX_TYPES];
static char		chars[TZ_MAX_CHARS];

/*
** Exits.
*/

static
tameexit()
{
	exit(0);
}

static
wild2exit(part1, part2)
char *	part1;
char *	part2;
{
	register char *	between;

	if (part1 == NULL)
		part1 = "";
	if (part2 == NULL)
		part2 = "";
	between = (*part1 == '\0' || *part2 == '\0') ? "" : " ";
	(void) fprintf(stderr, "%s: wild %s%s%s\n",
		progname, part1, between, part2);
	exit(1);
}

static
wildexit(string)
char *	string;
{
	wild2exit(string, (char *) NULL);
}

static
wildrexit(string)
char *	string;
{
	wild2exit("result from", string);
}

/*
** Memory allocation.
*/

static char *
emalloc(size)
{
	register char *	cp;

	if ((cp = malloc((alloc_t) size)) == NULL || cp == MAL)
		wildrexit("malloc");
	return cp;
}

static char *
erealloc(ptr, size)
char *	ptr;
{
	register char *	cp;

	if ((cp = realloc(ptr, (alloc_t) size)) == NULL)
		wildrexit("realloc");
	return cp;
}

static char *
eallocpy(old)
char *	old;
{
	register char *	new;

	if (old == NULL)
		old = "";
	new = emalloc(strlen(old) + 1);
	(void) strcpy(new, old);
	return new;
}

static
usage()
{
	(void) fprintf(stderr,
	"%s: usage is %s [ -l localtime ] [ -d directory ] [ filename ... ]\n",
		progname, progname);
	exit(1);
}

static char *	localtime = NULL;
static char *	directory = NULL;

main(argc, argv)
int	argc;
char *	argv[];
{
	register int	i;
	register int	c;

	progname = argv[0];
	while ((c = getopt(argc, argv, "d:l:")) != EOF)
		switch (c) {
			default:
				usage();
			case 'd':
				if (directory == NULL)
					directory = optarg;
				else	wildexit("multiple command line -d's");
				break;
			case 'l':
				if (localtime == NULL)
					localtime = optarg;
				else	wildexit("multiple command line -l's");
		}
	if (directory == NULL)
		directory = TZDIR;
	if (optind == argc - 1 && strcmp(argv[optind], "=") == 0)
		usage();	/* usage message by request */
	zones = (struct zone *) emalloc(0);
	rules = (struct rule *) emalloc(0);
	links = (struct link *) emalloc(0);
	for (i = optind; i < argc; ++i)
		infile(argv[i]);
	if (errors)
		wildexit("input data");
	associate();
	for (i = 0; i < nzones; ++i)
		outzone(&zones[i]);
	/*
	** We'll take the easy way out on this last part.
	*/
	if (chdir(directory) != 0)
		wild2exit("result from chdir to", directory);
	for (i = 0; i < nlinks; ++i) {
		(void) unlink(links[i].l_to);
		if (link(links[i].l_from, links[i].l_to) != 0)
			wild2exit("result creating", links[i].l_to);
	}
	if (localtime != NULL) {
		(void) unlink(TZDEFAULT);
		if (link(localtime, TZDEFAULT) != 0)
			wild2exit("result creating", TZDEFAULT);
	}
	tameexit();
}

/*
** Associate sets of rules with zones.
*/

/*
** Sort by rule name, and by magnitude of standard time offset for rules of
** the same name.  The second sort gets standard time entries to the start
** of the dsinfo table (and we want a standard time entry at the start of
** the table, since the first entry gets used for times not covered by the
** rules).
*/

static
rcomp(cp1, cp2)
char *	cp1;
char *	cp2;
{
	register struct rule *	rp1;
	register struct rule *	rp2;
	register long		l1, l2;
	register int		diff;

	rp1 = (struct rule *) cp1;
	rp2 = (struct rule *) cp2;
	if ((diff = strcmp(rp1->r_name, rp2->r_name)) != 0)
		return diff;
	if ((l1 = rp1->r_stdoff) < 0)
		l1 = -l1;
	if ((l2 = rp2->r_stdoff) < 0)
		l2 = -l2;
	if (l1 > l2)
		return 1;
	else if (l1 < l2)
		return -1;
	else	return 0;
}

static
associate()
{
	register struct zone *	zp;
	register struct rule *	rp;
	register int		base, out;
	register int		i;

	if (nrules != 0)
		(void) qsort((char *) rules, nrules, sizeof *rules, rcomp);
	base = 0;
	for (i = 0; i < nzones; ++i) {
		zp = &zones[i];
		zp->z_rules = NULL;
		zp->z_nrules = 0;
	}
	while (base < nrules) {
		rp = &rules[base];
		for (out = base + 1; out < nrules; ++out)
			if (strcmp(rp->r_name, rules[out].r_name) != 0)
				break;
		for (i = 0; i < nzones; ++i) {
			zp = &zones[i];
			if (strcmp(zp->z_rule, rp->r_name) != 0)
				continue;
			zp->z_rules = rp;
			zp->z_nrules = out - base;
		}
		base = out;
	}
	for (i = 0; i < nzones; ++i) {
		zp = &zones[i];
		if (*zp->z_rule != '\0' && zp->z_nrules == 0) {
			filename = zp->z_filename;
			linenum = zp->z_linenum;
			error("unruly zone");
		}
	}
	if (errors)
		wildexit("unruly zone(s)");
}

static
error(string)
char *	string;
{
	(void) fprintf(stderr, "%s: file \"%s\", line %d: wild %s\n",
		progname, filename, linenum, string);
	++errors;
}

static
infile(name)
char *	name;
{
	register FILE *			fp;
	register char **		fields;
	register char *			cp;
	register struct lookup *	lp;
	register int			nfields;
	char				buf[BUFSIZ];

	if (strcmp(name, "-") == 0) {
		name = "standard input";
		fp = stdin;
	} else if ((fp = fopen(name, "r")) == NULL)
		wild2exit("result opening", name);
	filename = eallocpy(name);
	for (linenum = 1; ; ++linenum) {
		if (fgets(buf, sizeof buf, fp) != buf)
			break;
		cp = strchr(buf, '\n');
		if (cp == NULL) {
			error("long line");
			wildexit("input data");
		}
		*cp = '\0';
		if ((fields = getfields(buf)) == NULL)
			wildrexit("getfields");
		nfields = 0;
		while (fields[nfields] != NULL) {
			if (ciequal(fields[nfields], "-"))
				fields[nfields] = "";
			++nfields;
		}
		if (nfields > 0)	/* non-blank line */
			if ((lp = byword(fields[0], line_codes)) == NULL)
				error("input line of unknown type");
			else switch (lp->l_value) {
				case LC_RULE:
					inrule(fields, nfields);
					break;
				case LC_ZONE:
					inzone(fields, nfields);
					break;
				case LC_LINK:
					inlink(fields, nfields);
					break;
				default:	/* "cannot happen" */
					wildrexit("lookup");
			}
		free((char *) fields);
	}
	if (ferror(fp))
		wild2exit("result reading", filename);
	if (fp != stdin && fclose(fp))
		wild2exit("result closing", filename);
}

/*
** Convert a string of one of the forms
**	h	-h 	hh:mm	-hh:mm	hh:mm:ss	-hh:mm:ss
** into a number of seconds. 
** Call error with errstring and return zero on errors.
*/

static long
getoff(string, errstring)
char *	string;
char *	errstring;
{
	long	hh, mm, ss, sign;

	if (*string == '-') {
		sign = -1;
		++string;
	} else	sign = 1;
	if (sscanf(string, scheck(string, "%ld"), &hh) == 1)
		mm = ss = 0;
	else if (sscanf(string, scheck(string, "%ld:%ld"), &hh, &mm) == 2)
		ss = 0;
	else if (sscanf(string, scheck(string, "%ld:%ld:%ld"),
		&hh, &mm, &ss) != 3) {
			error(errstring);
			return 0;
	}
	if (hh < 0 || hh >= HOURS_PER_DAY ||
		mm < 0 || mm >= MINS_PER_HOUR ||
		ss < 0 || ss >= SECS_PER_MIN) {
			error(errstring);
			return 0;
	}
	return (long) sign * (((hh * MINS_PER_HOUR) + mm) * SECS_PER_MIN + ss);
}

static
inrule(fields, nfields)
char **	fields;
{
	register struct lookup *	lp;
	register char *			cp;
	struct rule			r;

	if (nfields != RULE_FIELDS) {
		error("number of fields on Rule line");
		return;
	}
	r.r_filename = filename;
	r.r_linenum = linenum;
	if ((lp = byword(fields[RF_MONTH], mon_names)) == NULL) {
		error("month name");
		return;
	}
	r.r_month = lp->l_value;
	r.r_todisstd = FALSE;
	cp = fields[RF_TOD];
	if (strlen(cp) > 0) {
		cp += strlen(cp) - 1;
		switch (lowerit(*cp)) {
			case 's':
				r.r_todisstd = TRUE;
				*cp = '\0';
				break;
			case 'w':
				r.r_todisstd = FALSE;
				*cp = '\0';
				break;
		}
	}
	r.r_tod = getoff(fields[RF_TOD], "time of day");
	r.r_stdoff = getoff(fields[RF_STDOFF], "Standard Time offset");
	/*
	** Year work.
	*/
	cp = fields[RF_LOYEAR];
	if (sscanf(cp, scheck(cp, "%ld"), &r.r_loyear) != 1 ||
		r.r_loyear <= 0) {
			error("low year");
			return;
	}
	cp = fields[RF_HIYEAR];
	if (*cp == '\0' || ciequal(cp, "only"))
		r.r_hiyear = r.r_loyear;
	else if (sscanf(cp, scheck(cp, "%ld"), &r.r_hiyear) != 1 ||
		r.r_hiyear <= 0) {
			error("high year");
			return;
	}
	if (r.r_loyear > r.r_hiyear) {
		error("low year (greater than high year)");
		return;
	}
	if (*fields[RF_COMMAND] == '\0')
		r.r_yrtype = NULL;
	else {
		if (r.r_loyear == r.r_hiyear) {
			error("typed single year");
			return;
		}
		r.r_yrtype = eallocpy(fields[RF_COMMAND]);
	}
	/*
	** Day work.
	** Accept things such as:
	**	1
	**	last-Sunday
	**	Sun<=20
	**	Sun>=7
	*/
	cp = fields[RF_DAY];
	if ((lp = byword(cp, lasts)) != NULL) {
		r.r_dycode = DC_DOWLEQ;
		r.r_wday = lp->l_value;
		r.r_dayofmonth = mon_lengths[r.r_month];
		if (r.r_month == TM_FEBRUARY)
			++r.r_dayofmonth;
	} else {
		if ((cp = strchr(fields[RF_DAY], '<')) != 0)
			r.r_dycode = DC_DOWLEQ;
		else if ((cp = strchr(fields[RF_DAY], '>')) != 0)
			r.r_dycode = DC_DOWGEQ;
		else {
			cp = fields[RF_DAY];
			r.r_dycode = DC_DOM;
		}
		if (r.r_dycode != DC_DOM) {
			*cp++ = 0;
			if (*cp++ != '=') {
				error("day of month");
				return;
			}
			if ((lp = byword(fields[RF_DAY], wday_names)) == NULL) {
				error("weekday name");
				return;
			}
			r.r_wday = lp->l_value;
		}
		if (sscanf(cp, scheck(cp, "%ld"), &r.r_dayofmonth) != 1 ||
			r.r_dayofmonth <= 0 ||
			(r.r_dayofmonth > mon_lengths[r.r_month] &&
			r.r_month != TM_FEBRUARY && r.r_dayofmonth != 29)) {
				error("day of month");
				return;
		}
	}
	if (*fields[RF_NAME] == '\0') {
		error("nameless rule");
		return;
	}
	r.r_name = eallocpy(fields[RF_NAME]);
	r.r_abbrvar = eallocpy(fields[RF_ABBRVAR]);
	rules = (struct rule *) erealloc((char *) rules,
		(nrules + 1) * sizeof *rules);
	rules[nrules++] = r;
}

static
inzone(fields, nfields)
char **	fields;
{
	register char *	cp;
	register int	i;
	struct zone	z;
	char		buf[132];

	if (nfields != ZONE_FIELDS) {
		error("number of fields on Zone line");
		return;
	}
	z.z_filename = filename;
	z.z_linenum = linenum;
	for (i = 0; i < nzones; ++i)
		if (strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
			(void) sprintf(buf,
				"duplicate zone name %s (file \"%s\", line %d)",
				fields[ZF_NAME],
				zones[i].z_filename,
				zones[i].z_linenum);
			error(buf);
			return;
		}
	z.z_gmtoff = getoff(fields[ZF_GMTOFF], "GMT offset");
	if ((cp = strchr(fields[ZF_FORMAT], '%')) != 0) {
		if (*++cp != 's' || strchr(cp, '%') != 0) {
			error("format");
			return;
		}
	}
	z.z_name = eallocpy(fields[ZF_NAME]);
	z.z_rule = eallocpy(fields[ZF_RULE]);
	z.z_format = eallocpy(fields[ZF_FORMAT]);
	zones = (struct zone *) erealloc((char *) zones,
		(nzones + 1) * sizeof *zones);
	zones[nzones++] = z;
}

static
inlink(fields, nfields)
char **	fields;
{
	struct link	l;

	if (nfields != LINK_FIELDS) {
		error("number of fields on Link line");
		return;
	}
	if (*fields[LF_FROM] == '\0') {
		error("blank FROM field on Link line");
		return;
	}
	if (*fields[LF_TO] == '\0') {
		error("blank TO field on Link line");
		return;
	}
	l.l_filename = filename;
	l.l_linenum = linenum;
	l.l_from = eallocpy(fields[LF_FROM]);
	l.l_to = eallocpy(fields[LF_TO]);
	links = (struct link *) erealloc((char *) links,
		(nlinks + 1) * sizeof *links);
	links[nlinks++] = l;
}

static
writezone(name)
char *	name;
{
	register FILE *	fp;
	register int	i;
	char		fullname[BUFSIZ];

	if (strlen(directory) + 1 + strlen(name) >= BUFSIZ)
		wild2exit("long directory/file", filename);
	(void) sprintf(fullname, "%s/%s", directory, name);
	if ((fp = fopen(fullname, "w")) == NULL) {
		mkdirs(fullname);
		if ((fp = fopen(fullname, "w")) == NULL)
			wild2exit("result creating", fullname);
	}
	if (fwrite((char *) &h, sizeof h, 1, fp) != 1)
		goto wreck;
	if ((i = h.tzh_timecnt) != 0) {
		if (fwrite((char *) ats, sizeof ats[0], i, fp) != i)
			goto wreck;
		if (fwrite((char *) types, sizeof types[0], i, fp) != i)
			goto wreck;
	}
	if ((i = h.tzh_typecnt) != 0)
		if (fwrite((char *) ttis, sizeof ttis[0], i, fp) != i)
			goto wreck;
	if ((i = h.tzh_charcnt) != 0)
		if (fwrite(chars, sizeof chars[0], i, fp) != i)
			goto wreck;
	if (fclose(fp))
		wild2exit("result closing", fullname);
	return;
wreck:
	wild2exit("result writing", fullname);
}

struct temp {
	long		t_time;
	struct rule *	t_rp;
};

static struct temp	temps[TZ_MAX_TIMES];
static int		ntemps;

static
tcomp(cp1, cp2)
char *	cp1;
char *	cp2;
{
	register struct temp *	tp1;
	register struct temp *	tp2;
	register char *		cp;
	register long		diff;

	tp1 = (struct temp *) cp1;
	tp2 = (struct temp *) cp2;
	if (tp1->t_time > 0 && tp2->t_time <= 0)
		return 1;
	if (tp1->t_time <= 0 && tp2->t_time > 0)
		return -1;
	if ((diff = tp1->t_time - tp2->t_time) > 0)
		return 1;
	else if (diff < 0)
		return -1;
	/*
	** Oops!
	*/
	if (tp1->t_rp->r_type == tp2->t_rp->r_type)
		cp = "duplicate rule?!";
	else	cp = "inconsistent rules?!";
	filename = tp1->t_rp->r_filename;
	linenum = tp1->t_rp->r_linenum;
	error(cp);
	filename = tp2->t_rp->r_filename;
	linenum = tp2->t_rp->r_linenum;
	error(cp);
	wildexit(cp);
	/*NOTREACHED*/
}

static
addrule(rp, y)
register struct rule *	rp;
long			y;
{
	if (ntemps >= TZ_MAX_TIMES) {
		error("too many transitions?!");
		wildexit("large number of transitions");
	}
	temps[ntemps].t_time = rpytime(rp, y);
	temps[ntemps].t_rp = rp;
	++ntemps;
}

static
outzone(zp)
register struct zone *	zp;
{
	register struct rule *		rp;
	register int			i, j;
	register long			y;
	register long			gmtoff;
	char				buf[BUFSIZ];

	h.tzh_timecnt = 0;
	h.tzh_typecnt = 0;
	h.tzh_charcnt = 0;
	if (zp->z_nrules == 0) {	/* Piece of cake! */
		h.tzh_timecnt = 0;
		h.tzh_typecnt = 1;
		ttis[0].tt_gmtoff = zp->z_gmtoff;
		ttis[0].tt_isdst = 0;
		ttis[0].tt_abbrind = 0;
		newabbr(zp->z_format);
		writezone(zp->z_name);
		return;
	}
	/*
	** See what the different local time types are.
	** Plug the indices into the rules.
	*/
	for (i = 0; i < zp->z_nrules; ++i) {
		rp = &zp->z_rules[i];
		(void) sprintf(buf, zp->z_format, rp->r_abbrvar);
		gmtoff = tadd(zp->z_gmtoff, rp->r_stdoff);
		for (j = 0; j < h.tzh_typecnt; ++j) {
			if (gmtoff == ttis[j].tt_gmtoff &&
				strcmp(buf, &chars[ttis[j].tt_abbrind]) == 0)
					break;
		}
		if (j >= h.tzh_typecnt) {
			if (h.tzh_typecnt >= TZ_MAX_TYPES) {
				filename = zp->z_filename;
				linenum = zp->z_linenum;
				error("large number of local time types");
				wildexit("input data");
			}
			ttis[j].tt_gmtoff = gmtoff;
			ttis[j].tt_isdst = rp->r_stdoff != 0;
			ttis[j].tt_abbrind = h.tzh_charcnt;
			newabbr(buf);
			++h.tzh_typecnt;
		}
		rp->r_type = j;
	}
	/*
	** Now. . .finally. . .generate some useable data!
	*/
	ntemps = 0;
	for (i = 0; i < zp->z_nrules; ++i) {
		rp = &zp->z_rules[i];
		filename = rp->r_filename;
		linenum = rp->r_linenum;
		if (rp->r_yrtype != NULL && *rp->r_yrtype != '\0')
			hard(rp);
		else for (y = rp->r_loyear; y <= rp->r_hiyear; ++y)
			addrule(rp, y);
	}
	h.tzh_timecnt = ntemps;
	(void) qsort((char *) temps, ntemps, sizeof *temps, tcomp);
	for (i = 0; i < ntemps; ++i) {
		rp = temps[i].t_rp;
		filename = rp->r_filename;
		linenum = rp->r_linenum;
		types[i] = rp->r_type;
		ats[i] = tadd(temps[i].t_time, -zp->z_gmtoff);
		if (!rp->r_todisstd) {
			/*
			** Credit to munnari!kre for pointing out the need for
			** the following.  (This can still mess up on the
			** earliest rule; who's got the solution?  It can also
			** mess up if a time switch results in a day switch;
			** this is left as an exercise for the reader.)
			*/
			if (i == 0) {
				/*
				** Kludge--not guaranteed to work.
				*/
				if (ntemps > 1)
					ats[0] = tadd(ats[0],
						-temps[1].t_rp->r_stdoff);
			} else	ats[i] = tadd(ats[i],
				-temps[i - 1].t_rp->r_stdoff);
		}
	}
	writezone(zp->z_name);
	return;
}

static
hard(rp)
register struct rule *	rp;
{
	register FILE *	fp;
	register int	n;
	long		y;
	char		buf[BUFSIZ];
	char		command[BUFSIZ];

	(void) sprintf(command, "years %ld %ld %s",
		rp->r_loyear, rp->r_hiyear, rp->r_yrtype);
	if ((fp = popen(command, "r")) == NULL)
		wild2exit("result opening pipe to", command);
	for (n = 0; fgets(buf, sizeof buf, fp) == buf; ++n) {
		if (strchr(buf, '\n') == 0)
			wildrexit(command);
		*strchr(buf, '\n') = '\0';
		if (sscanf(buf, scheck(buf, "%ld"), &y) != 1)
			wildrexit(command);
		if (y < rp->r_loyear || y > rp->r_hiyear)
			wildrexit(command);
		addrule(rp, y);
	}
	if (ferror(fp))
		wild2exit("result reading from", command);
	if (pclose(fp))
		wild2exit("result closing pipe to", command);
	if (n == 0) {
		error("no year in range matches type");
		wildexit("input data");
	}
}

static
lowerit(a)
{
	return (isascii(a) && isupper(a)) ? tolower(a) : a;
}

static
ciequal(ap, bp)		/* case-insensitive equality */
register char *	ap;
register char *	bp;
{
	while (lowerit(*ap) == lowerit(*bp++))
		if (*ap++ == '\0')
			return TRUE;
	return FALSE;
}

static
isabbr(abbr, word)
register char *		abbr;
register char *		word;
{
	if (lowerit(*abbr) != lowerit(*word))
		return FALSE;
	++word;
	while (*++abbr != '\0')
		do if (*word == '\0')
			return FALSE;
				while (lowerit(*word++) != lowerit(*abbr));
	return TRUE;
}

static struct lookup *
byword(word, table)
register char *			word;
register struct lookup *	table;
{
	register struct lookup *	foundlp;
	register struct lookup *	lp;

	if (word == NULL || table == NULL)
		return NULL;
	foundlp = NULL;
	for (lp = table; lp->l_word != NULL; ++lp)
		if (ciequal(word, lp->l_word))		/* "exact" match */
			return lp;
		else if (!isabbr(word, lp->l_word))
			continue;
		else if (foundlp == NULL)
			foundlp = lp;
		else	return NULL;		/* two inexact matches */
	return foundlp;
}

static char **
getfields(cp)
register char *	cp;
{
	register char *		dp;
	register char **	array;
	register int		nsubs;

	if (cp == NULL)
		return NULL;
	array = (char **) emalloc((strlen(cp) + 1) * sizeof *array);
	nsubs = 0;
	for ( ; ; ) {
		while (isascii(*cp) && isspace(*cp))
			++cp;
		if (*cp == '\0' || *cp == '#')
			break;
		array[nsubs++] = dp = cp;
		do {
			if ((*dp = *cp++) != '"')
				++dp;
			else while ((*dp = *cp++) != '"')
				if (*dp != '\0')
					++dp;
				else	error("Odd number of quotation marks");
		} while (*cp != '\0' && *cp != '#' &&
			(!isascii(*cp) || !isspace(*cp)));
		if (isascii(*cp) && isspace(*cp))
			++cp;
		*dp++ = '\0';
	}
	array[nsubs] = NULL;
	return array;
}

static long
tadd(t1, t2)
long	t1;
long	t2;
{
	register long	t;

	t = t1 + t2;
	if (t1 > 0 && t2 > 0 && t <= 0 || t1 < 0 && t2 < 0 && t >= 0) {
		error("time overflow");
		wildexit("time overflow");
	}
	return t;
}

static
isleap(y)
long	y;
{
	return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
}

static long
rpytime(rp, wantedy)
register struct rule *	rp;
register long		wantedy;
{
	register long	i, y, wday, t, m;
	register long	dayoff;			/* with a nod to Margaret O. */

	dayoff = 0;
	m = TM_JANUARY;
	y = EPOCH_YEAR;
	while (wantedy != y) {
		if (wantedy > y) {
			i = DAYS_PER_YEAR;
			if (isleap(y))
				++i;
			++y;
		} else {
			--y;
			i = -DAYS_PER_YEAR;
			if (isleap(y))
				--i;
		}
		dayoff = tadd(dayoff, i);
	}
	while (m != rp->r_month) {
		i = mon_lengths[m];
		if (m == TM_FEBRUARY && isleap(y))
			++i;
		dayoff = tadd(dayoff, i);
		++m;
	}
	i = rp->r_dayofmonth;
	if (m == TM_FEBRUARY && i == 29 && !isleap(y)) {
		if (rp->r_dycode == DC_DOWLEQ)
			--i;
		else {
			error("use of 2/29 in non leap-year");
			for ( ; ; )
				wildexit("data");
		}
	}
	--i;
	dayoff = tadd(dayoff, i);
	if (rp->r_dycode == DC_DOWGEQ || rp->r_dycode == DC_DOWLEQ) {
		wday = EPOCH_WDAY;
		/*
		** Don't trust mod of negative numbers.
		*/
		if (dayoff >= 0)
			wday = (wday + dayoff) % 7;
		else {
			wday -= ((-dayoff) % 7);
			if (wday < 0)
				wday += 7;
		}
		while (wday != rp->r_wday) {
			if (rp->r_dycode == DC_DOWGEQ)
				i = 1;
			else	i = -1;
			dayoff = tadd(dayoff, i);
			wday = (wday + i + 7) % 7;
		}
	}
	t = dayoff * SECS_PER_DAY;
	/*
	** Cheap overflow check.
	*/
	if (t / SECS_PER_DAY != dayoff)
		error("time overflow");
	return tadd(t, rp->r_tod);
}

static
newabbr(string)
char *	string;
{
	register int	i;

	i = strlen(string);
	if (h.tzh_charcnt + i >= TZ_MAX_CHARS)
		error("long time zone abbreviations");
	(void) strcpy(&chars[h.tzh_charcnt], string);
	h.tzh_charcnt += i + 1;
}

static
mkdirs(name)
char *	name;
{
	register char *	cp;

	if ((cp = name) == NULL || *cp == '\0')
		return;
	while ((cp = strchr(cp + 1, '/')) != 0) {
		*cp = '\0';
		(void) mkdir(name);
		*cp = '/';
	}
}
SHAR_EOF
if test 24558 -ne "`wc -c < 'tzcomp.c'`"
then
	echo shar: error transmitting "'tzcomp.c'" '(should have been 24558 characters)'
fi
fi
echo shar: extracting "'scheck.c'" '(1141 characters)'
if test -f 'scheck.c'
then
	echo shar: will not over-write existing file "'scheck.c'"
else
cat << \SHAR_EOF > 'scheck.c'
#

/*LINTLIBRARY*/

#include "stdio.h"

#ifdef OBJECTID
static char	sccsid[] = "@(#)scheck.c	7.9";
#endif

#include "ctype.h"

#ifndef alloc_t
#define alloc_t	unsigned
#endif

#ifndef MAL
#define MAL	NULL
#endif

extern char *	malloc();

char *
scheck(string, format)
char *	string;
char *	format;
{
	register char *	fbuf;
	register char *	fp;
	register char *	tp;
	register int	c;
	register char *	result;
	char		dummy;

	result = "";
	if (string == NULL || format == NULL)
		return result;
	fbuf = malloc((alloc_t) (2 * strlen(format) + 4));
	if (fbuf == MAL)
		return result;
	fp = format;
	tp = fbuf;
	while ((*tp++ = c = *fp++) != '\0') {
		if (c != '%')
			continue;
		if (*fp == '%') {
			*tp++ = *fp++;
			continue;
		}
		*tp++ = '*';
		if (*fp == '*')
			++fp;
		while (isascii(*fp) && isdigit(*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';
	if (sscanf(string, fbuf, &dummy) != 1)
		result = format;
	free(fbuf);
	return result;
}
SHAR_EOF
if test 1141 -ne "`wc -c < 'scheck.c'`"
then
	echo shar: error transmitting "'scheck.c'" '(should have been 1141 characters)'
fi
fi
echo shar: extracting "'strchr.c'" '(419 characters)'
if test -f 'strchr.c'
then
	echo shar: will not over-write existing file "'strchr.c'"
else
cat << \SHAR_EOF > 'strchr.c'
#

/*LINTLIBRARY*/

#include "stdio.h"

#ifdef OBJECTID
static char	sccsid[] = "@(#)strchr.c	7.3";
#endif

/*
** For the benefit of BSD folks.
** This is written from the manual description,
** so there's no guarantee that it works the same as the "real thing."
*/

char *	
strchr(string, c)
register char *	string;
register int	c;
{
	do if (*string == c)
		return string;
			while (*string++ != '\0');
	return NULL;
}
SHAR_EOF
if test 419 -ne "`wc -c < 'strchr.c'`"
then
	echo shar: error transmitting "'strchr.c'" '(should have been 419 characters)'
fi
fi
echo shar: extracting "'mkdir.c'" '(524 characters)'
if test -f 'mkdir.c'
then
	echo shar: will not over-write existing file "'mkdir.c'"
else
cat << \SHAR_EOF > 'mkdir.c'
#

/*LINTLIBRARY*/

#include "stdio.h"

#ifdef OJBECTID
static char	sccsid[] = "@(#)mkdir.c	7.2";
#endif

extern FILE *	popen();

mkdir(name)
char *	name;
{
	register FILE *	fp;
	register int	c;
	register int	oops;

	if ((fp = popen("sh", "w")) == NULL)
		return -1;
	(void) fputs("mkdir 2>&- '", fp);
	if (name != NULL)
		while ((c = *name++) != '\0')
			if (c == '\'')
				(void) fputs("'\\''", fp);
			else	(void) fputc(c, fp);
	(void) fputs("'\n", fp);
	oops = ferror(fp);
	return (pclose(fp) == 0 && !oops) ? 0 : -1;
}
SHAR_EOF
if test 524 -ne "`wc -c < 'mkdir.c'`"
then
	echo shar: error transmitting "'mkdir.c'" '(should have been 524 characters)'
fi
fi
echo shar: extracting "'tzdump.c'" '(2783 characters)'
if test -f 'tzdump.c'
then
	echo shar: will not over-write existing file "'tzdump.c'"
else
cat << \SHAR_EOF > 'tzdump.c'
#

#include "stdio.h"

#ifdef OBJECTID
static char	sccsid[] = "@(#)tzdump.c	2.1";
#endif

#include "time.h"
#include "tzfile.h"

#ifndef alloc_t
#define alloc_t		unsigned
#endif

#ifndef TRUE
#define TRUE		1
#define FALSE		0
#endif

extern char *		asctime();
extern char *		calloc();
extern struct tm *	gmtime();
extern char *		newctime();
extern int		optind;
extern char *		sprintf();
extern long		time();
extern char *		tz_abbr;

static int		longest;

main(argc, argv)
int	argc;
char *	argv[];
{
	register FILE *	fp;
	register long *	tp;
	register int	i, j, c;
	register int	vflag;
	long		now;
	struct tzhead	h;
	char		buf[BUFSIZ];

	vflag = 0;
	while ((c = getopt(argc, argv, "v")) == 'v')
		vflag = 1;
	if (c != EOF || optind == argc - 1 && strcmp(argv[optind], "=") == 0) {
		(void) fprintf(stderr, "%s: usage is %s [ -v ] zonename ...\n",
			argv[0], argv[0]);
		exit(1);
	}
	(void) time(&now);
	longest = 0;
	for (i = optind; i < argc; ++i)
		if (strlen(argv[i]) > longest)
			longest = strlen(argv[i]);
	for (i = optind; i < argc; ++i) {
		if (settz(argv[i]) != 0) {
			(void) fprintf(stderr,
				"%s: wild result from settz(\"%s\")\n",
				argv[0], argv[i]);
			exit(1);
		}
		show(argv[i], now, FALSE);
		if (!vflag)
			continue;
		if (argv[i][0] == '/')
			fp = fopen(argv[i], "r");
		else {
			j = strlen(TZDIR) + 1 + strlen(argv[i]) + 1;
			if (j > sizeof buf) {
				(void) fprintf(stderr,
					"%s: wild long timezone name %s\n",
					argv[0], argv[i]);
				exit(1);
			}
			(void) sprintf(buf, "%s/%s", TZDIR, argv[i]);
			fp = fopen(buf, "r");
		}
		if (fp == NULL) {
			(void) fprintf(stderr,
				"%s: wild result opening %s file\n",
				argv[0], argv[i]);
			exit(1);
		}
		if (fread((char *) &h, sizeof h, 1, fp) != 1) {
			(void) fprintf(stderr,
				"%s: wild result reading %s file\n",
				argv[0], argv[i]);
			exit(1);
		}
		tp = (long *) calloc((alloc_t) h.tzh_timecnt, sizeof *tp);
		if (tp == NULL) {
			(void) fprintf(stderr,
				"%s: wild result from calloc\n", argv[0]);
			exit(1);
		}
		if (h.tzh_timecnt != 0)
			if (fread((char *) tp, sizeof *tp, (int) h.tzh_timecnt,
				fp) != h.tzh_timecnt) {
				(void) fprintf(stderr,
					"%s: wild result reading %s file\n",
					argv[0], argv[i]);
				exit(1);
			}
		if (fclose(fp)) {
			(void) fprintf(stderr,
				"%s: wild result closing %s file\n",
				argv[0], argv[i]);
			exit(1);
		}
		for (j = 0; j < h.tzh_timecnt; ++j) {
			show(argv[i], tp[j] - 1, TRUE);
			show(argv[i], tp[j], TRUE);
		}
		free((char *) tp);
	}
	return 0;
}

static
show(zone, t, v)
char *	zone;
long	t;
{
	(void) printf("%-*s  ", longest, zone);
	if (v)
		(void) printf("%.24s GMT = ", asctime(gmtime(&t)));
	(void) printf("%.24s", newctime(&t));
	if (*tz_abbr != '\0')
		(void) printf(" %s", tz_abbr);
	(void) printf("\n");
}
SHAR_EOF
if test 2783 -ne "`wc -c < 'tzdump.c'`"
then
	echo shar: error transmitting "'tzdump.c'" '(should have been 2783 characters)'
fi
fi
echo shar: extracting "'settz.c'" '(4052 characters)'
if test -f 'settz.c'
then
	echo shar: will not over-write existing file "'settz.c'"
else
cat << \SHAR_EOF > 'settz.c'
#

/*LINTLIBRARY*/

/*
** Should there be any built-in rules other than GMT?
** In particular, should zones such as "EST5" (abbreviation is always "EST",
** GMT offset is always 5 hours) be built in?
*/

#include "tzfile.h"
#include "time.h"

#ifdef OBJECTID
static char	sccsid[] = "@(#)settz.c	2.1";
#endif

#ifndef TRUE
#define TRUE		1
#define FALSE		0
#endif

#ifndef MAXPATHLEN
#define MAXPATHLEN	1024
#endif

extern char *		asctime();
extern struct tm *	gmtime();
extern char *		strcpy();
extern char *		strcat();
extern char *		getenv();

static struct tzhead	h;
static long		ats[TZ_MAX_TIMES];
static unsigned char	types[TZ_MAX_TIMES];
static struct ttinfo	ttis[TZ_MAX_TYPES];
static char		chars[TZ_MAX_CHARS + 1];

#define TZ_MAX_TOTAL	(sizeof h + sizeof ats + sizeof types + \
				sizeof ttis + sizeof chars)

static char		isset;

char *			tz_abbr;	/* set by localtime; available to all */

/*
** Not available west of the Rockies. . .
*/

static char *
memcpy(to, from, n)
char *	to;
char *	from;
{
	register int	i;

	for (i = 0; i < n; ++i)
		to[i] = from[i];
	return to;
}

static
tzload(tzname)
register char *	tzname;
{
	register char *	p;
	register int	fid;
	register int	i;
	register int	doaccess;
	char		buf[(TZ_MAX_TOTAL>MAXPATHLEN)?TZ_MAX_TOTAL:MAXPATHLEN];

	if (tzname == 0 && (tzname = TZDEFAULT) == 0)
		return -1;
	doaccess = tzname[0] == '/';
	if (!doaccess) {
		if ((p = TZDIR) == 0)
			return -1;
		if ((strlen(p) + strlen(tzname) + 1) >= sizeof buf)
			return -1;
		(void) strcpy(buf, p);
		(void) strcat(buf, "/");
		(void) strcat(buf, tzname);
		/*
		** Set doaccess if '.' (as in "../") shows up in name.
		*/
		while (*tzname != '\0')
			if (*tzname++ == '.')
				doaccess = TRUE;
		tzname = buf;
	}
	if (doaccess && access(tzname, 4) != 0)
		return -1;
	if ((fid = open(tzname, 0)) == -1)
		return -1;
	p = buf;
	i = read(fid, p, sizeof buf);
	if (close(fid) != 0 || i < sizeof h)
		return -1;
	(void) memcpy((char *) &h, p, sizeof h);
	if (h.tzh_timecnt > TZ_MAX_TIMES ||
		h.tzh_typecnt == 0 || h.tzh_typecnt > TZ_MAX_TYPES ||
		h.tzh_charcnt > TZ_MAX_CHARS)
			return -1;
	if (i < sizeof h +
		h.tzh_timecnt * (sizeof ats[0] + sizeof types[0]) +
		h.tzh_typecnt * sizeof ttis[0] +
		h.tzh_charcnt * sizeof chars[0])
			return -1;
	p += sizeof h;
	if ((i = h.tzh_timecnt) > 0) {
		(void) memcpy((char *) ats, p, i * sizeof ats[0]);
		p += i * sizeof ats[0];
		(void) memcpy((char *) types, p, i * sizeof types[0]);
		p += i * sizeof types[0];
	}
	if ((i = h.tzh_typecnt) > 0) {
		(void) memcpy((char *) ttis, p, i * sizeof ttis[0]);
		p += i * sizeof ttis[0];
	}
	if ((i = h.tzh_charcnt) > 0)
		(void) memcpy((char *) chars, p, i * sizeof chars[0]);
	chars[h.tzh_charcnt] = '\0';	/* ensure '\0'-termination */
	for (i = 0; i < h.tzh_timecnt; ++i)
		if (types[i] >= h.tzh_typecnt)
			return -1;
	for (i = 0; i < h.tzh_typecnt; ++i)
		if (ttis[i].tt_abbrind >= h.tzh_charcnt)
			return -1;
	return 0;
}

/*
** settz("")		Use built-in GMT.
** settz((char *) 0)	Use TZDEFAULT.
** settz(otherwise)	Use otherwise.
*/

settz(tzname)
char *	tzname;
{
	register int	answer;

	isset = TRUE;
	if (tzname != 0 && *tzname == '\0')
		answer = 0;			/* Use built-in GMT */
	else {
		if (tzload(tzname) == 0)
			return 0;
		/*
		** If we want to try for local time on errors. . .
		if (tzload((char *) 0) == 0)
			return -1;
		*/
		answer = -1;
	}
	h.tzh_timecnt = 0;
	ttis[0].tt_gmtoff = 0;
	ttis[0].tt_abbrind = 0;
	(void) strcpy(chars, "GMT");
	return answer;
}

struct tm *
newlocaltime(timep)
long *	timep;
{
	register struct ttinfo *	ttip;
	register struct tm *		tmp;
	register int			i;
	long				t;

	t = *timep;
	if (!isset)
		(void) settz(getenv("TZ"));
	if (h.tzh_timecnt == 0 || t < ats[0])
		i = 0;
	else {
		for (i = 1; i < h.tzh_timecnt; ++i)
			if (t < ats[i])
				break;
		i = types[i - 1];
	}
	ttip = &ttis[i];
	t += ttip->tt_gmtoff;
	tmp = gmtime(&t);
	tmp->tm_isdst = ttip->tt_isdst;
	tz_abbr = &chars[ttip->tt_abbrind];
	return tmp;
}

char *
newctime(timep)
long *	timep;
{
	return asctime(newlocaltime(timep));
}
SHAR_EOF
if test 4052 -ne "`wc -c < 'settz.c'`"
then
	echo shar: error transmitting "'settz.c'" '(should have been 4052 characters)'
fi
fi
echo shar: extracting "'years.sh'" '(382 characters)'
if test -f 'years.sh'
then
	echo shar: will not over-write existing file "'years.sh'"
else
cat << \SHAR_EOF > 'years.sh'
: '@(#)years.sh	2.1'

: years lo hi type

case $# in
	3)		;;
	*)		echo "$0: usage is $0 lo hi type" 1>&2
			exit 1 ;;
esac

lo="$1"
hi="$2"
type="$3"

case $type in
	uspres)		check='(y % 4) == 0' ;;
	nonpres)	check='(y % 4) != 0' ;;	
	*)		echo "$0: wild year type ($type)" 1>&2
			exit 1 ;;
esac

exec awk "
BEGIN {
	for (y = $lo; y <= $hi; ++y)
		if ($check)
			print y;
	exit
}
"
SHAR_EOF
if test 382 -ne "`wc -c < 'years.sh'`"
then
	echo shar: error transmitting "'years.sh'" '(should have been 382 characters)'
fi
fi
echo shar: extracting "'asia'" '(71 characters)'
if test -f 'asia'
then
	echo shar: will not over-write existing file "'asia'"
else
cat << \SHAR_EOF > 'asia'
# @(#)asia	2.1
# Zone	NAME		GMTOFF	RULES	FORMAT
Zone	Japan		9:00	-	JST
SHAR_EOF
if test 71 -ne "`wc -c < 'asia'`"
then
	echo shar: error transmitting "'asia'" '(should have been 71 characters)'
fi
fi
echo shar: extracting "'australasia'" '(942 characters)'
if test -f 'australasia'
then
	echo shar: will not over-write existing file "'australasia'"
else
cat << \SHAR_EOF > 'australasia'
# @(#)australasia	2.1

# Australian Data (for states with DST), standard rules

# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
Rule	Aus	1971	2037	-	Oct	lastSun	2:00	1:00	-
Rule	Aus	1972	only	-	Feb	27	3:00	0	-
Rule	Aus	1973	2037	-	Mar	Sun>=1	3:00	0	-

#Australian Data, Vic (and NSW except for a variation in 83? that I[kre] forget)

Rule	Aus-Vic	1971	2037	-	Oct	lastSun	2:00	1:00	-
Rule	Aus-Vic	1972	only	-	Feb	27	3:00	0	-
Rule	Aus-Vic	1973	1985	-	Mar	Sun>=1	3:00	0	-
# is this really forever, or just 86??
Rule	Aus-Vic	1986	2037	-	Mar	Sun<=21	3:00	0	-

# Australia - something of a turmoil here
# Zone	NAME		GMTOFF	RULES	FORMAT
Zone	EST		10:00	Aus-Vic	EST	# rule change, 1986
Zone	Tasmania	10:00	Aus	EST	# still the standard rules?
Zone	Queensland	10:00	-	EST	# Queensland - no DST
Zone	CST		9:30	Aus	CST	# still the standard rules?
Zone	North		9:30	-	CST	# Northern Territory - no DST
Zone	WST		8:00	-	WST	# No DST ever, this is simple...
SHAR_EOF
if test 942 -ne "`wc -c < 'australasia'`"
then
	echo shar: error transmitting "'australasia'" '(should have been 942 characters)'
fi
fi
echo shar: extracting "'europe'" '(930 characters)'
if test -f 'europe'
then
	echo shar: will not over-write existing file "'europe'"
else
cat << \SHAR_EOF > 'europe'
# @(#)europe	2.1

# European data is hearsay...

# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
Rule	W-Eur	1969	2037	-	Mar	lastSun	2:00	1:00	" DST"
Rule	W-Eur	1969	1982	-	Oct	lastSun	2:00	0	-
Rule	W-Eur	1983	only	-	Oct	23	2:00	0	-
Rule	W-Eur	1984	2037	-	Oct	lastSun	2:00	0	-

Rule	M-Eur	1969	2037	-	Mar	lastSun	2:00	1:00	" DST"
Rule	M-Eur	1969	1982	-	Sep	lastSun	2:00	0	-
Rule	M-Eur	1983	only	-	Oct	23	2:00	0	-
Rule	M-Eur	1984	2037	-	Sep	lastSun	2:00	0	-

# Zone	NAME		GMTOFF	RULES	FORMAT
Zone	WET		0	W-Eur	WET%s
Zone	MET		1 	M-Eur	MET%s

# One source shows that Bulgaria, Cyprus, Finland, and Greece observe DST from
# the last Sunday in March to the last Sunday in September in 1986.
# Did any/all of them have Middle Europe's 1983 wobble?
#
# The source shows Romania changing a day later than everybody else;
# since I don't think they're allowed to have UNIX(tm) systems, we'll skip
# them for now.

Zone	EET		2	M-Eur	EET%s
SHAR_EOF
if test 930 -ne "`wc -c < 'europe'`"
then
	echo shar: error transmitting "'europe'" '(should have been 930 characters)'
fi
fi
echo shar: extracting "'etcetera'" '(1208 characters)'
if test -f 'etcetera'
then
	echo shar: will not over-write existing file "'etcetera'"
else
cat << \SHAR_EOF > 'etcetera'
# @(#)etcetera	2.1

#
# A settz("") uses the code's built-in GMT without going to disk to get
# the information.  Still, we want things to work if somebody does a
# settz("GMT"), so. . .
#

Zone	GMT		0	-	GMT

#
# Names for zones that might exist, just so people can set a timezone
# that's right for their area, even if it doesn't have a name or dst rules
# (half hour zones are too much to bother with -- when someone asks!)
#

Zone	GMT-12		-12	-	GMT-1200
Zone	GMT-11		-11	-	GMT-1100
Zone	GMT-10		-10	-	GMT-1000
Zone	GMT-9		-9	-	GMT-0900
Zone	GMT-8		-8	-	GMT-0800
Zone	GMT-7		-7	-	GMT-0700
Zone	GMT-6		-6	-	GMT-0600
Zone	GMT-5		-5	-	GMT-0500
Zone	GMT-4		-4	-	GMT-0400
Zone	GMT-3		-3	-	GMT-0300
Zone	GMT-2		-2	-	GMT-0200
Zone	GMT-1		-1	-	GMT-0100
Zone	GMT+1		1	-	GMT+0100
Zone	GMT+2		2	-	GMT+0200
Zone	GMT+3		3	-	GMT+0300
Zone	GMT+4		4	-	GMT+0400
Zone	GMT+5		5	-	GMT+0500
Zone	GMT+6		6	-	GMT+0600
Zone	GMT+7		7	-	GMT+0700
Zone	GMT+8		8	-	GMT+0800
Zone	GMT+9		9	-	GMT+0900
Zone	GMT+10		10	-	GMT+1000
Zone	GMT+11		11	-	GMT+1100
Zone	GMT+12		12	-	GMT+1200
Zone	GMT+13		13	-	GMT+1300	# GMT+12 with DST

Link	GMT		UTC		# one of these two is right, but which?
Link	GMT		UCT
Link	GMT		Universal
Link	GMT		Greenwich
SHAR_EOF
if test 1208 -ne "`wc -c < 'etcetera'`"
then
	echo shar: error transmitting "'etcetera'" '(should have been 1208 characters)'
fi
fi
echo shar: extracting "'northamerica'" '(3139 characters)'
if test -f 'northamerica'
then
	echo shar: will not over-write existing file "'northamerica'"
else
cat << \SHAR_EOF > 'northamerica'
# @(#)northamerica	2.1

# Bob Devine has written that ". . .your table is wrong for MostNA in 1974.
# The correct ending date is 10/27 not 11/24."  Yet on a 4.1bsd VAX/11-750
# system, compiling and executing the program
#
#	#include "time.h"
#
#	long l = 152592000;
#
#	main() {
#		struct tm *	tmp;
#
#		tmp = localtime(&l);
#		printf("%s", asctime(tmp));
#		printf("isdst: %d\n", tmp->tm_isdst);
#	}
#
# results in the output
#
#	Fri Nov  1 22:40:00 1974
#	isdst: 1
#
# For now we'll stay with 4.1bsd's version.
#
# Note also this from munnari!kre:
# "I recall also being told by someone once that Canada didn't have
# the DST variations in 74/75 that the US did, but I am not nearly
# sure enough of this to add anything."

# Before the Uniform Time Act of 1966 took effect in 1967, observance of
# Daylight Saving Time in the US was by local option, except during wartime.

# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
Rule	MostNA	1918	1919	-	Mar	lastSun	2:00	1:00	D
Rule	MostNA	1918	1919	-	Oct	lastSun	2:00	0	S
Rule	MostNA	1942	only	-	Feb	9	2:00	1:00	W # War
Rule	MostNA	1945	only	-	Sep	30	2:00	0	S
Rule	MostNA	1967	1973	-	Apr	lastSun	2:00	1:00	D
Rule	MostNA	1967	1973	-	Oct	lastSun	2:00	0	S
Rule	MostNA	1974	only	-	Jan	6	2:00	1:00	D
Rule	MostNA	1974	only	-	Nov	24	2:00	0	S
Rule	MostNA	1975	only	-	Feb	23	2:00	1:00	D
Rule	MostNA	1975	only	-	Oct	26	2:00	0	S
Rule	MostNA	1976	2037	-	Apr	lastSun	2:00	1:00	D
Rule	MostNA	1976	2037	-	Oct	lastSun	2:00	0	S

###############################################################################

# New names

# Zone	NAME		GMTOFF	RULES	FORMAT
Zone	Atlantic	-4:00	MostNA	A%sT
Zone	Eastern		-5:00	MostNA	E%sT
Zone	Central		-6:00	MostNA	C%sT
Zone	Mountain	-7:00	MostNA	M%sT
Zone	Pacific		-8:00	MostNA	P%sT
Zone	Yukon		-9:00	MostNA	Y%sT
Zone	Aleutian	-10:00	MostNA	A%sT
Zone	Newfoundland	-3:30	-	NST	# Is DST now observed here?
						# If so, when did it start?

# Old names

# Link	LINK-FROM	LINK-TO
Link	Eastern		EST5EDT
Link	Central		CST6CDT
Link	Mountain	MST7MDT
Link	Pacific		PST8PDT

# Nonstandard mainland areas:

Rule	SomeUS	1918	1919	-	Mar	lastSun	2:00	1:00	D
Rule	SomeUS	1918	1919	-	Oct	lastSun	2:00	0	S
Rule	SomeUS	1942	only	-	Feb	9	2:00	1:00	W # War
Rule	SomeUS	1945	only	-	Sep	30	2:00	0	S

Zone	East-Indiana	-5:00	SomeUS	E%sT # Usually standard near South Bend
Zone	Arizona		-7:00	SomeUS	M%sT # Usually standard in Arizona

# And then there's Hawaii.
# DST was observed for one day in 1933.
# Standard time was change by half an hour in 1947; this accounts for
# the half-hour offsets before then, and the peculiar first rule.
# (An alternative is to have "Zone Hawaiian -10:30..." with a
# current standard offset of 0:30; this seems a bit more obscure.)
#
# Things have been calm since 1947.

Rule	Hawaii	1901	only	-	Dec	14	0:00	-0:30	S
Rule	Hawaii	1918	1919	-	Mar	lastSun	2:00	0:30	D
Rule	Hawaii	1918	1919	-	Oct	lastSun	2:00	-0:30	S
Rule	Hawaii	1933	only	-	Apr	30	2:00	0:30	D
Rule	Hawaii	1933	only	-	May	1	2:00	-0:30	S
Rule	Hawaii	1942	only	-	Feb	9	2:00	0:30	W # War
Rule	Hawaii	1945	only	-	Sep	30	2:00	-0:30	S
Rule	Hawaii	1947	only	-	Jun	8	2:00	0	S

Zone	Hawaiian	-10:00	Hawaii	H%sT
SHAR_EOF
if test 3139 -ne "`wc -c < 'northamerica'`"
then
	echo shar: error transmitting "'northamerica'" '(should have been 3139 characters)'
fi
fi
echo shar: extracting "'pacificnew'" '(922 characters)'
if test -f 'pacificnew'
then
	echo shar: will not over-write existing file "'pacificnew'"
else
cat << \SHAR_EOF > 'pacificnew'
# @(#)pacificnew	2.1

# "Pacific Presidential Election Time" is being contemplated by the US Congress

# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
Rule	Twilite	1918	1919	-	Mar	lastSun	2:00	1:00	D
Rule	Twilite	1918	1919	-	Oct	lastSun	2:00	0	S
Rule	Twilite	1942	only	-	Feb	9	2:00	1:00	W # War
Rule	Twilite	1945	only	-	Sep	30	2:00	0	S
Rule	Twilite	1967	1973	-	Apr	lastSun	2:00	1:00	D
Rule	Twilite	1967	1973	-	Oct	lastSun	2:00	0	S
Rule	Twilite	1974	only	-	Jan	6	2:00	1:00	D
Rule	Twilite	1974	only	-	Nov	24	2:00	0	S
Rule	Twilite	1975	only	-	Feb	23	2:00	1:00	D
Rule	Twilite	1975	only	-	Oct	26	2:00	0	S
Rule	Twilite	1976	2037	-	Apr	lastSun	2:00	1:00	D
Rule	Twilite	1976	1987	-	Oct	lastSun	2:00	0	S
Rule	Twilite	1988	2037	uspres	Oct	lastSun	2:00	1:00	PE
Rule	Twilite	1988	2037	uspres	Nov	Sun>=7	2:00	0	S
Rule	Twilite	1988	2037	nonpres	Oct	lastSun	2:00	0	S

# Zone	NAME		GMTOFF	RULES	FORMAT
Zone	Pacific-New	-8:00	Twilite	P%sT
SHAR_EOF
if test 922 -ne "`wc -c < 'pacificnew'`"
then
	echo shar: error transmitting "'pacificnew'" '(should have been 922 characters)'
fi
fi
exit 0
#	End of shell archive