Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
0a19fb42
Commit
0a19fb42
authored
May 21, 2004
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Pgindent timezone file, per request from Tom.
parent
63bd0db1
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
2243 additions
and
1771 deletions
+2243
-1771
src/timezone/ialloc.c
src/timezone/ialloc.c
+19
-10
src/timezone/localtime.c
src/timezone/localtime.c
+563
-428
src/timezone/pgtz.c
src/timezone/pgtz.c
+77
-55
src/timezone/pgtz.h
src/timezone/pgtz.h
+3
-3
src/timezone/private.h
src/timezone/private.h
+26
-25
src/timezone/scheck.c
src/timezone/scheck.c
+16
-12
src/timezone/strftime.c
src/timezone/strftime.c
+370
-359
src/timezone/tzfile.h
src/timezone/tzfile.h
+34
-28
src/timezone/zic.c
src/timezone/zic.c
+1135
-851
No files found.
src/timezone/ialloc.c
View file @
0a19fb42
...
@@ -5,54 +5,63 @@
...
@@ -5,54 +5,63 @@
#define nonzero(n) (((n) == 0) ? 1 : (n))
#define nonzero(n) (((n) == 0) ? 1 : (n))
char
*
imalloc
(
const
int
n
)
char
*
imalloc
(
const
int
n
)
{
{
return
malloc
((
size_t
)
nonzero
(
n
));
return
malloc
((
size_t
)
nonzero
(
n
));
}
}
char
*
icalloc
(
int
nelem
,
int
elsize
)
char
*
icalloc
(
int
nelem
,
int
elsize
)
{
{
if
(
nelem
==
0
||
elsize
==
0
)
if
(
nelem
==
0
||
elsize
==
0
)
nelem
=
elsize
=
1
;
nelem
=
elsize
=
1
;
return
calloc
((
size_t
)
nelem
,
(
size_t
)
elsize
);
return
calloc
((
size_t
)
nelem
,
(
size_t
)
elsize
);
}
}
void
*
irealloc
(
void
*
pointer
,
const
int
size
)
void
*
irealloc
(
void
*
pointer
,
const
int
size
)
{
{
if
(
pointer
==
NULL
)
if
(
pointer
==
NULL
)
return
imalloc
(
size
);
return
imalloc
(
size
);
return
realloc
((
void
*
)
pointer
,
(
size_t
)
nonzero
(
size
));
return
realloc
((
void
*
)
pointer
,
(
size_t
)
nonzero
(
size
));
}
}
char
*
icatalloc
(
char
*
old
,
const
char
*
new
)
char
*
icatalloc
(
char
*
old
,
const
char
*
new
)
{
{
register
char
*
result
;
register
char
*
result
;
register
int
oldsize
,
newsize
;
register
int
oldsize
,
newsize
;
newsize
=
(
new
==
NULL
)
?
0
:
strlen
(
new
);
newsize
=
(
new
==
NULL
)
?
0
:
strlen
(
new
);
if
(
old
==
NULL
)
if
(
old
==
NULL
)
oldsize
=
0
;
oldsize
=
0
;
else
if
(
newsize
==
0
)
else
if
(
newsize
==
0
)
return
old
;
return
old
;
else
oldsize
=
strlen
(
old
);
else
oldsize
=
strlen
(
old
);
if
((
result
=
irealloc
(
old
,
oldsize
+
newsize
+
1
))
!=
NULL
)
if
((
result
=
irealloc
(
old
,
oldsize
+
newsize
+
1
))
!=
NULL
)
if
(
new
!=
NULL
)
if
(
new
!=
NULL
)
(
void
)
strcpy
(
result
+
oldsize
,
new
);
(
void
)
strcpy
(
result
+
oldsize
,
new
);
return
result
;
return
result
;
}
}
char
*
icpyalloc
(
const
char
*
string
)
char
*
icpyalloc
(
const
char
*
string
)
{
{
return
icatalloc
((
char
*
)
NULL
,
string
);
return
icatalloc
((
char
*
)
NULL
,
string
);
}
}
void
ifree
(
char
*
p
)
void
ifree
(
char
*
p
)
{
{
if
(
p
!=
NULL
)
if
(
p
!=
NULL
)
(
void
)
free
(
p
);
(
void
)
free
(
p
);
}
}
void
icfree
(
char
*
p
)
void
icfree
(
char
*
p
)
{
{
if
(
p
!=
NULL
)
if
(
p
!=
NULL
)
(
void
)
free
(
p
);
(
void
)
free
(
p
);
...
...
src/timezone/localtime.c
View file @
0a19fb42
...
@@ -32,18 +32,18 @@
...
@@ -32,18 +32,18 @@
** 5. They might reference tm.TM_ZONE after calling offtime.
** 5. They might reference tm.TM_ZONE after calling offtime.
** What's best to do in the above cases is open to debate;
** What's best to do in the above cases is open to debate;
** for now, we just set things up so that in any of the five cases
** for now, we just set things up so that in any of the five cases
** WILDABBR is used. Another possibility:
initialize tzname[0] to the
** WILDABBR is used. Another possibility:
initialize tzname[0] to the
** string "tzname[0] used before set", and similarly for the other cases.
** string "tzname[0] used before set", and similarly for the other cases.
** And another: initialize tzname[0] to "ERA", with an explanation in the
** And another: initialize tzname[0] to "ERA", with an explanation in the
** manual page of what this "time zone abbreviation" means (doing this so
** manual page of what this "time zone abbreviation" means (doing this so
** that tzname[0] has the "normal" length of three characters).
** that tzname[0] has the "normal" length of three characters).
*/
*/
#define WILDABBR " "
#define WILDABBR " "
#endif
/* !defined WILDABBR */
#endif
/* !defined WILDABBR */
static
char
wildabbr
[]
=
"WILDABBR"
;
static
char
wildabbr
[]
=
"WILDABBR"
;
static
const
char
gmt
[]
=
"GMT"
;
static
const
char
gmt
[]
=
"GMT"
;
/*
/*
** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
...
@@ -54,45 +54,50 @@ static const char gmt[] = "GMT";
...
@@ -54,45 +54,50 @@ static const char gmt[] = "GMT";
*/
*/
#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
struct
ttinfo
{
/* time type information */
struct
ttinfo
long
tt_gmtoff
;
/* UTC offset in seconds */
{
/* time type information */
int
tt_isdst
;
/* used to set tm_isdst */
long
tt_gmtoff
;
/* UTC offset in seconds */
int
tt_abbrind
;
/* abbreviation list index */
int
tt_isdst
;
/* used to set tm_isdst */
int
tt_ttisstd
;
/* TRUE if transition is std time */
int
tt_abbrind
;
/* abbreviation list index */
int
tt_ttisgmt
;
/* TRUE if transition is UTC */
int
tt_ttisstd
;
/* TRUE if transition is std time */
int
tt_ttisgmt
;
/* TRUE if transition is UTC */
};
};
struct
lsinfo
{
/* leap second information */
struct
lsinfo
time_t
ls_trans
;
/* transition time */
{
/* leap second information */
long
ls_corr
;
/* correction to apply */
time_t
ls_trans
;
/* transition time */
long
ls_corr
;
/* correction to apply */
};
};
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
struct
state
{
struct
state
int
leapcnt
;
{
int
timecnt
;
int
leapcnt
;
int
typecnt
;
int
timecnt
;
int
charcnt
;
int
typecnt
;
int
charcnt
;
time_t
ats
[
TZ_MAX_TIMES
];
time_t
ats
[
TZ_MAX_TIMES
];
unsigned
char
types
[
TZ_MAX_TIMES
];
unsigned
char
types
[
TZ_MAX_TIMES
];
struct
ttinfo
ttis
[
TZ_MAX_TYPES
];
struct
ttinfo
ttis
[
TZ_MAX_TYPES
];
char
chars
[
BIGGEST
(
BIGGEST
(
TZ_MAX_CHARS
+
1
,
sizeof
gmt
),
char
chars
[
BIGGEST
(
BIGGEST
(
TZ_MAX_CHARS
+
1
,
sizeof
gmt
),
(
2
*
(
TZ_STRLEN_MAX
+
1
)))];
(
2
*
(
TZ_STRLEN_MAX
+
1
)))];
struct
lsinfo
lsis
[
TZ_MAX_LEAPS
];
struct
lsinfo
lsis
[
TZ_MAX_LEAPS
];
};
};
struct
rule
{
struct
rule
int
r_type
;
/* type of rule--see below */
{
int
r_day
;
/* day number of rule */
int
r_type
;
/* type of rule--see below */
int
r_week
;
/* week number of rule */
int
r_day
;
/* day number of rule */
int
r_mon
;
/* month number of rule */
int
r_week
;
/* week number of rule */
long
r_time
;
/* transition time of rule */
int
r_mon
;
/* month number of rule */
long
r_time
;
/* transition time of rule */
};
};
#define JULIAN_DAY 0
/* Jn - Julian day */
#define JULIAN_DAY 0
/* Jn - Julian day */
#define DAY_OF_YEAR 1
/* n - day of year */
#define DAY_OF_YEAR 1
/* n - day of year */
#define MONTH_NTH_DAY_OF_WEEK 2
/* Mm.n.d - month, week, day of week */
#define MONTH_NTH_DAY_OF_WEEK 2
/* Mm.n.d - month, week, day of
* week */
/*
/*
** Prototypes for static functions.
** Prototypes for static functions.
...
@@ -103,29 +108,30 @@ static const char *getzname(const char *strp);
...
@@ -103,29 +108,30 @@ static const char *getzname(const char *strp);
static
const
char
*
getnum
(
const
char
*
strp
,
int
*
nump
,
int
min
,
int
max
);
static
const
char
*
getnum
(
const
char
*
strp
,
int
*
nump
,
int
min
,
int
max
);
static
const
char
*
getsecs
(
const
char
*
strp
,
long
*
secsp
);
static
const
char
*
getsecs
(
const
char
*
strp
,
long
*
secsp
);
static
const
char
*
getoffset
(
const
char
*
strp
,
long
*
offsetp
);
static
const
char
*
getoffset
(
const
char
*
strp
,
long
*
offsetp
);
static
const
char
*
getrule
(
const
char
*
strp
,
struct
rule
*
rulep
);
static
const
char
*
getrule
(
const
char
*
strp
,
struct
rule
*
rulep
);
static
void
gmtload
(
struct
state
*
sp
);
static
void
gmtload
(
struct
state
*
sp
);
static
void
gmtsub
(
const
time_t
*
timep
,
long
offset
,
struct
pg_tm
*
tmp
);
static
void
gmtsub
(
const
time_t
*
timep
,
long
offset
,
struct
pg_tm
*
tmp
);
static
void
localsub
(
const
time_t
*
timep
,
long
offset
,
struct
pg_tm
*
tmp
);
static
void
localsub
(
const
time_t
*
timep
,
long
offset
,
struct
pg_tm
*
tmp
);
static
int
increment_overflow
(
int
*
number
,
int
delta
);
static
int
increment_overflow
(
int
*
number
,
int
delta
);
static
int
normalize_overflow
(
int
*
tensptr
,
int
*
unitsptr
,
int
base
);
static
int
normalize_overflow
(
int
*
tensptr
,
int
*
unitsptr
,
int
base
);
static
time_t
time1
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)(
const
time_t
*
,
long
,
struct
pg_tm
*
),
long
offset
);
static
time_t
time1
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
long
offset
);
static
time_t
time2
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)(
const
time_t
*
,
long
,
struct
pg_tm
*
),
long
offset
,
int
*
okayp
);
static
time_t
time2
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
long
offset
,
int
*
okayp
);
static
time_t
time2sub
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)(
const
time_t
*
,
long
,
struct
pg_tm
*
),
long
offset
,
int
*
okayp
,
int
do_norm_secs
);
static
time_t
time2sub
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
long
offset
,
int
*
okayp
,
int
do_norm_secs
);
static
void
timesub
(
const
time_t
*
timep
,
long
offset
,
const
struct
state
*
sp
,
struct
pg_tm
*
tmp
);
static
void
timesub
(
const
time_t
*
timep
,
long
offset
,
const
struct
state
*
sp
,
struct
pg_tm
*
tmp
);
static
int
tmcomp
(
const
struct
pg_tm
*
atmp
,
const
struct
pg_tm
*
btmp
);
static
int
tmcomp
(
const
struct
pg_tm
*
atmp
,
const
struct
pg_tm
*
btmp
);
static
time_t
transtime
(
time_t
janfirst
,
int
year
,
const
struct
rule
*
rulep
,
long
offset
);
static
time_t
transtime
(
time_t
janfirst
,
int
year
,
const
struct
rule
*
rulep
,
long
offset
);
static
int
tzload
(
const
char
*
name
,
struct
state
*
sp
);
static
int
tzload
(
const
char
*
name
,
struct
state
*
sp
);
static
int
tzparse
(
const
char
*
name
,
struct
state
*
sp
,
int
lastditch
);
static
int
tzparse
(
const
char
*
name
,
struct
state
*
sp
,
int
lastditch
);
static
struct
state
lclmem
;
static
struct
state
lclmem
;
static
struct
state
gmtmem
;
static
struct
state
gmtmem
;
#define lclptr (&lclmem)
#define lclptr (&lclmem)
#define gmtptr (&gmtmem)
#define gmtptr (&gmtmem)
static
char
lcl_TZname
[
TZ_STRLEN_MAX
+
1
];
static
char
lcl_TZname
[
TZ_STRLEN_MAX
+
1
];
static
int
lcl_is_set
=
0
;
static
int
lcl_is_set
=
0
;
static
int
gmt_is_set
=
0
;
static
int
gmt_is_set
=
0
;
/*
/*
** Section 4.12.3 of X3.159-1989 requires that
** Section 4.12.3 of X3.159-1989 requires that
...
@@ -135,13 +141,14 @@ static int gmt_is_set=0;
...
@@ -135,13 +141,14 @@ static int gmt_is_set=0;
** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
*/
*/
static
struct
pg_tm
tm
;
static
struct
pg_tm
tm
;
static
long
detzcode
(
const
char
*
codep
)
static
long
detzcode
(
const
char
*
codep
)
{
{
register
long
result
;
register
long
result
;
register
int
i
;
register
int
i
;
result
=
(
codep
[
0
]
&
0x80
)
?
~
0L
:
0L
;
result
=
(
codep
[
0
]
&
0x80
)
?
~
0L
:
0L
;
for
(
i
=
0
;
i
<
4
;
++
i
)
for
(
i
=
0
;
i
<
4
;
++
i
)
...
@@ -149,22 +156,24 @@ static long detzcode(const char *codep)
...
@@ -149,22 +156,24 @@ static long detzcode(const char *codep)
return
result
;
return
result
;
}
}
static
int
tzload
(
register
const
char
*
name
,
register
struct
state
*
sp
)
static
int
tzload
(
register
const
char
*
name
,
register
struct
state
*
sp
)
{
{
register
const
char
*
p
;
register
const
char
*
p
;
register
int
i
;
register
int
i
;
register
int
fid
;
register
int
fid
;
if
(
name
==
NULL
&&
(
name
=
TZDEFAULT
)
==
NULL
)
if
(
name
==
NULL
&&
(
name
=
TZDEFAULT
)
==
NULL
)
return
-
1
;
return
-
1
;
{
{
register
int
doaccess
;
register
int
doaccess
;
char
fullname
[
MAXPGPATH
];
char
fullname
[
MAXPGPATH
];
if
(
name
[
0
]
==
':'
)
if
(
name
[
0
]
==
':'
)
++
name
;
++
name
;
doaccess
=
name
[
0
]
==
'/'
;
doaccess
=
name
[
0
]
==
'/'
;
if
(
!
doaccess
)
{
if
(
!
doaccess
)
{
p
=
pg_TZDIR
();
p
=
pg_TZDIR
();
if
(
p
==
NULL
)
if
(
p
==
NULL
)
return
-
1
;
return
-
1
;
...
@@ -173,9 +182,10 @@ static int tzload(register const char *name, register struct state *sp)
...
@@ -173,9 +182,10 @@ static int tzload(register const char *name, register struct state *sp)
(
void
)
strcpy
(
fullname
,
p
);
(
void
)
strcpy
(
fullname
,
p
);
(
void
)
strcat
(
fullname
,
"/"
);
(
void
)
strcat
(
fullname
,
"/"
);
(
void
)
strcat
(
fullname
,
name
);
(
void
)
strcat
(
fullname
,
name
);
/*
/*
*
* Set doaccess if '.' (as in "../") shows up in name.
*
* Set doaccess if '.' (as in "../") shows up in name.
*/
*/
if
(
strchr
(
name
,
'.'
)
!=
NULL
)
if
(
strchr
(
name
,
'.'
)
!=
NULL
)
doaccess
=
TRUE
;
doaccess
=
TRUE
;
name
=
fullname
;
name
=
fullname
;
...
@@ -186,13 +196,14 @@ static int tzload(register const char *name, register struct state *sp)
...
@@ -186,13 +196,14 @@ static int tzload(register const char *name, register struct state *sp)
return
-
1
;
return
-
1
;
}
}
{
{
struct
tzhead
*
tzhp
;
struct
tzhead
*
tzhp
;
union
{
union
struct
tzhead
tzhead
;
{
struct
tzhead
tzhead
;
char
buf
[
sizeof
*
sp
+
sizeof
*
tzhp
];
char
buf
[
sizeof
*
sp
+
sizeof
*
tzhp
];
}
u
;
}
u
;
int
ttisstdcnt
;
int
ttisstdcnt
;
int
ttisgmtcnt
;
int
ttisgmtcnt
;
i
=
read
(
fid
,
u
.
buf
,
sizeof
u
.
buf
);
i
=
read
(
fid
,
u
.
buf
,
sizeof
u
.
buf
);
if
(
close
(
fid
)
!=
0
)
if
(
close
(
fid
)
!=
0
)
...
@@ -210,26 +221,29 @@ static int tzload(register const char *name, register struct state *sp)
...
@@ -210,26 +221,29 @@ static int tzload(register const char *name, register struct state *sp)
sp
->
charcnt
<
0
||
sp
->
charcnt
>
TZ_MAX_CHARS
||
sp
->
charcnt
<
0
||
sp
->
charcnt
>
TZ_MAX_CHARS
||
(
ttisstdcnt
!=
sp
->
typecnt
&&
ttisstdcnt
!=
0
)
||
(
ttisstdcnt
!=
sp
->
typecnt
&&
ttisstdcnt
!=
0
)
||
(
ttisgmtcnt
!=
sp
->
typecnt
&&
ttisgmtcnt
!=
0
))
(
ttisgmtcnt
!=
sp
->
typecnt
&&
ttisgmtcnt
!=
0
))
return
-
1
;
return
-
1
;
if
(
i
-
(
p
-
u
.
buf
)
<
sp
->
timecnt
*
4
+
/* ats */
if
(
i
-
(
p
-
u
.
buf
)
<
sp
->
timecnt
*
4
+
/* ats */
sp
->
timecnt
+
/* types */
sp
->
timecnt
+
/* types */
sp
->
typecnt
*
(
4
+
2
)
+
/* ttinfos */
sp
->
typecnt
*
(
4
+
2
)
+
/* ttinfos */
sp
->
charcnt
+
/* chars */
sp
->
charcnt
+
/* chars */
sp
->
leapcnt
*
(
4
+
4
)
+
/* lsinfos */
sp
->
leapcnt
*
(
4
+
4
)
+
/* lsinfos */
ttisstdcnt
+
/* ttisstds */
ttisstdcnt
+
/* ttisstds */
ttisgmtcnt
)
/* ttisgmts */
ttisgmtcnt
)
/* ttisgmts */
return
-
1
;
return
-
1
;
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
sp
->
ats
[
i
]
=
detzcode
(
p
);
sp
->
ats
[
i
]
=
detzcode
(
p
);
p
+=
4
;
p
+=
4
;
}
}
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
sp
->
types
[
i
]
=
(
unsigned
char
)
*
p
++
;
sp
->
types
[
i
]
=
(
unsigned
char
)
*
p
++
;
if
(
sp
->
types
[
i
]
>=
sp
->
typecnt
)
if
(
sp
->
types
[
i
]
>=
sp
->
typecnt
)
return
-
1
;
return
-
1
;
}
}
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
register
struct
ttinfo
*
ttisp
;
{
register
struct
ttinfo
*
ttisp
;
ttisp
=
&
sp
->
ttis
[
i
];
ttisp
=
&
sp
->
ttis
[
i
];
ttisp
->
tt_gmtoff
=
detzcode
(
p
);
ttisp
->
tt_gmtoff
=
detzcode
(
p
);
...
@@ -240,13 +254,14 @@ static int tzload(register const char *name, register struct state *sp)
...
@@ -240,13 +254,14 @@ static int tzload(register const char *name, register struct state *sp)
ttisp
->
tt_abbrind
=
(
unsigned
char
)
*
p
++
;
ttisp
->
tt_abbrind
=
(
unsigned
char
)
*
p
++
;
if
(
ttisp
->
tt_abbrind
<
0
||
if
(
ttisp
->
tt_abbrind
<
0
||
ttisp
->
tt_abbrind
>
sp
->
charcnt
)
ttisp
->
tt_abbrind
>
sp
->
charcnt
)
return
-
1
;
return
-
1
;
}
}
for
(
i
=
0
;
i
<
sp
->
charcnt
;
++
i
)
for
(
i
=
0
;
i
<
sp
->
charcnt
;
++
i
)
sp
->
chars
[
i
]
=
*
p
++
;
sp
->
chars
[
i
]
=
*
p
++
;
sp
->
chars
[
i
]
=
'\0'
;
/* ensure '\0' at end */
sp
->
chars
[
i
]
=
'\0'
;
/* ensure '\0' at end */
for
(
i
=
0
;
i
<
sp
->
leapcnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
leapcnt
;
++
i
)
register
struct
lsinfo
*
lsisp
;
{
register
struct
lsinfo
*
lsisp
;
lsisp
=
&
sp
->
lsis
[
i
];
lsisp
=
&
sp
->
lsis
[
i
];
lsisp
->
ls_trans
=
detzcode
(
p
);
lsisp
->
ls_trans
=
detzcode
(
p
);
...
@@ -254,42 +269,46 @@ static int tzload(register const char *name, register struct state *sp)
...
@@ -254,42 +269,46 @@ static int tzload(register const char *name, register struct state *sp)
lsisp
->
ls_corr
=
detzcode
(
p
);
lsisp
->
ls_corr
=
detzcode
(
p
);
p
+=
4
;
p
+=
4
;
}
}
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
register
struct
ttinfo
*
ttisp
;
{
register
struct
ttinfo
*
ttisp
;
ttisp
=
&
sp
->
ttis
[
i
];
ttisp
=
&
sp
->
ttis
[
i
];
if
(
ttisstdcnt
==
0
)
if
(
ttisstdcnt
==
0
)
ttisp
->
tt_ttisstd
=
FALSE
;
ttisp
->
tt_ttisstd
=
FALSE
;
else
{
else
{
ttisp
->
tt_ttisstd
=
*
p
++
;
ttisp
->
tt_ttisstd
=
*
p
++
;
if
(
ttisp
->
tt_ttisstd
!=
TRUE
&&
if
(
ttisp
->
tt_ttisstd
!=
TRUE
&&
ttisp
->
tt_ttisstd
!=
FALSE
)
ttisp
->
tt_ttisstd
!=
FALSE
)
return
-
1
;
return
-
1
;
}
}
}
}
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
register
struct
ttinfo
*
ttisp
;
{
register
struct
ttinfo
*
ttisp
;
ttisp
=
&
sp
->
ttis
[
i
];
ttisp
=
&
sp
->
ttis
[
i
];
if
(
ttisgmtcnt
==
0
)
if
(
ttisgmtcnt
==
0
)
ttisp
->
tt_ttisgmt
=
FALSE
;
ttisp
->
tt_ttisgmt
=
FALSE
;
else
{
else
{
ttisp
->
tt_ttisgmt
=
*
p
++
;
ttisp
->
tt_ttisgmt
=
*
p
++
;
if
(
ttisp
->
tt_ttisgmt
!=
TRUE
&&
if
(
ttisp
->
tt_ttisgmt
!=
TRUE
&&
ttisp
->
tt_ttisgmt
!=
FALSE
)
ttisp
->
tt_ttisgmt
!=
FALSE
)
return
-
1
;
return
-
1
;
}
}
}
}
}
}
return
0
;
return
0
;
}
}
static
const
int
mon_lengths
[
2
][
MONSPERYEAR
]
=
{
static
const
int
mon_lengths
[
2
][
MONSPERYEAR
]
=
{
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
},
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
},
{
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
{
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
};
};
static
const
int
year_lengths
[
2
]
=
{
static
const
int
year_lengths
[
2
]
=
{
DAYSPERNYEAR
,
DAYSPERLYEAR
DAYSPERNYEAR
,
DAYSPERLYEAR
};
};
...
@@ -299,13 +318,14 @@ static const int year_lengths[2] = {
...
@@ -299,13 +318,14 @@ static const int year_lengths[2] = {
** character.
** character.
*/
*/
static
const
char
*
getzname
(
register
const
char
*
strp
)
static
const
char
*
getzname
(
register
const
char
*
strp
)
{
{
register
char
c
;
register
char
c
;
while
((
c
=
*
strp
)
!=
'\0'
&&
!
is_digit
(
c
)
&&
c
!=
','
&&
c
!=
'-'
&&
while
((
c
=
*
strp
)
!=
'\0'
&&
!
is_digit
(
c
)
&&
c
!=
','
&&
c
!=
'-'
&&
c
!=
'+'
)
c
!=
'+'
)
++
strp
;
++
strp
;
return
strp
;
return
strp
;
}
}
...
@@ -316,22 +336,24 @@ static const char *getzname(register const char *strp)
...
@@ -316,22 +336,24 @@ static const char *getzname(register const char *strp)
** Otherwise, return a pointer to the first character not part of the number.
** Otherwise, return a pointer to the first character not part of the number.
*/
*/
static
const
char
*
getnum
(
register
const
char
*
strp
,
int
*
nump
,
const
int
min
,
const
int
max
)
static
const
char
*
getnum
(
register
const
char
*
strp
,
int
*
nump
,
const
int
min
,
const
int
max
)
{
{
register
char
c
;
register
char
c
;
register
int
num
;
register
int
num
;
if
(
strp
==
NULL
||
!
is_digit
(
c
=
*
strp
))
if
(
strp
==
NULL
||
!
is_digit
(
c
=
*
strp
))
return
NULL
;
return
NULL
;
num
=
0
;
num
=
0
;
do
{
do
{
num
=
num
*
10
+
(
c
-
'0'
);
num
=
num
*
10
+
(
c
-
'0'
);
if
(
num
>
max
)
if
(
num
>
max
)
return
NULL
;
/* illegal value */
return
NULL
;
/* illegal value */
c
=
*++
strp
;
c
=
*++
strp
;
}
while
(
is_digit
(
c
));
}
while
(
is_digit
(
c
));
if
(
num
<
min
)
if
(
num
<
min
)
return
NULL
;
/* illegal value */
return
NULL
;
/* illegal value */
*
nump
=
num
;
*
nump
=
num
;
return
strp
;
return
strp
;
}
}
...
@@ -344,27 +366,30 @@ static const char *getnum(register const char *strp, int *nump, const int min, c
...
@@ -344,27 +366,30 @@ static const char *getnum(register const char *strp, int *nump, const int min, c
** of seconds.
** of seconds.
*/
*/
static
const
char
*
getsecs
(
register
const
char
*
strp
,
long
*
secsp
)
static
const
char
*
getsecs
(
register
const
char
*
strp
,
long
*
secsp
)
{
{
int
num
;
int
num
;
/*
/*
** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
* * `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like *
** "M10.4.6/26", which does not conform to Posix,
* "M10.4.6/26", which does not conform to Posix, * but which
** but which specifies the equivalent of
* specifies the equivalent of * ``02:00 on the first Sunday on or
** ``02:00 on the first Sunday on or
after 23 Oct''.
*
after 23 Oct''.
*/
*/
strp
=
getnum
(
strp
,
&
num
,
0
,
HOURSPERDAY
*
DAYSPERWEEK
-
1
);
strp
=
getnum
(
strp
,
&
num
,
0
,
HOURSPERDAY
*
DAYSPERWEEK
-
1
);
if
(
strp
==
NULL
)
if
(
strp
==
NULL
)
return
NULL
;
return
NULL
;
*
secsp
=
num
*
(
long
)
SECSPERHOUR
;
*
secsp
=
num
*
(
long
)
SECSPERHOUR
;
if
(
*
strp
==
':'
)
{
if
(
*
strp
==
':'
)
{
++
strp
;
++
strp
;
strp
=
getnum
(
strp
,
&
num
,
0
,
MINSPERHOUR
-
1
);
strp
=
getnum
(
strp
,
&
num
,
0
,
MINSPERHOUR
-
1
);
if
(
strp
==
NULL
)
if
(
strp
==
NULL
)
return
NULL
;
return
NULL
;
*
secsp
+=
num
*
SECSPERMIN
;
*
secsp
+=
num
*
SECSPERMIN
;
if
(
*
strp
==
':'
)
{
if
(
*
strp
==
':'
)
{
++
strp
;
++
strp
;
/* `SECSPERMIN' allows for leap seconds. */
/* `SECSPERMIN' allows for leap seconds. */
strp
=
getnum
(
strp
,
&
num
,
0
,
SECSPERMIN
);
strp
=
getnum
(
strp
,
&
num
,
0
,
SECSPERMIN
);
...
@@ -383,18 +408,21 @@ static const char *getsecs(register const char *strp, long *secsp)
...
@@ -383,18 +408,21 @@ static const char *getsecs(register const char *strp, long *secsp)
** Otherwise, return a pointer to the first character not part of the time.
** Otherwise, return a pointer to the first character not part of the time.
*/
*/
static
const
char
*
getoffset
(
register
const
char
*
strp
,
long
*
offsetp
)
static
const
char
*
getoffset
(
register
const
char
*
strp
,
long
*
offsetp
)
{
{
register
int
neg
=
0
;
register
int
neg
=
0
;
if
(
*
strp
==
'-'
)
{
if
(
*
strp
==
'-'
)
{
neg
=
1
;
neg
=
1
;
++
strp
;
++
strp
;
}
else
if
(
*
strp
==
'+'
)
}
else
if
(
*
strp
==
'+'
)
++
strp
;
++
strp
;
strp
=
getsecs
(
strp
,
offsetp
);
strp
=
getsecs
(
strp
,
offsetp
);
if
(
strp
==
NULL
)
if
(
strp
==
NULL
)
return
NULL
;
/* illegal time */
return
NULL
;
/* illegal time */
if
(
neg
)
if
(
neg
)
*
offsetp
=
-*
offsetp
;
*
offsetp
=
-*
offsetp
;
return
strp
;
return
strp
;
...
@@ -407,19 +435,23 @@ static const char *getoffset(register const char *strp, long *offsetp)
...
@@ -407,19 +435,23 @@ static const char *getoffset(register const char *strp, long *offsetp)
** Otherwise, return a pointer to the first character not part of the rule.
** Otherwise, return a pointer to the first character not part of the rule.
*/
*/
static
const
char
*
getrule
(
const
char
*
strp
,
register
struct
rule
*
rulep
)
static
const
char
*
getrule
(
const
char
*
strp
,
register
struct
rule
*
rulep
)
{
{
if
(
*
strp
==
'J'
)
{
if
(
*
strp
==
'J'
)
{
/*
/*
*
* Julian day.
*
* Julian day.
*/
*/
rulep
->
r_type
=
JULIAN_DAY
;
rulep
->
r_type
=
JULIAN_DAY
;
++
strp
;
++
strp
;
strp
=
getnum
(
strp
,
&
rulep
->
r_day
,
1
,
DAYSPERNYEAR
);
strp
=
getnum
(
strp
,
&
rulep
->
r_day
,
1
,
DAYSPERNYEAR
);
}
else
if
(
*
strp
==
'M'
)
{
}
else
if
(
*
strp
==
'M'
)
{
/*
/*
*
* Month, week, day.
*
* Month, week, day.
*/
*/
rulep
->
r_type
=
MONTH_NTH_DAY_OF_WEEK
;
rulep
->
r_type
=
MONTH_NTH_DAY_OF_WEEK
;
++
strp
;
++
strp
;
strp
=
getnum
(
strp
,
&
rulep
->
r_mon
,
1
,
MONSPERYEAR
);
strp
=
getnum
(
strp
,
&
rulep
->
r_mon
,
1
,
MONSPERYEAR
);
...
@@ -433,22 +465,29 @@ static const char *getrule(const char *strp, register struct rule *rulep)
...
@@ -433,22 +465,29 @@ static const char *getrule(const char *strp, register struct rule *rulep)
if
(
*
strp
++
!=
'.'
)
if
(
*
strp
++
!=
'.'
)
return
NULL
;
return
NULL
;
strp
=
getnum
(
strp
,
&
rulep
->
r_day
,
0
,
DAYSPERWEEK
-
1
);
strp
=
getnum
(
strp
,
&
rulep
->
r_day
,
0
,
DAYSPERWEEK
-
1
);
}
else
if
(
is_digit
(
*
strp
))
{
}
else
if
(
is_digit
(
*
strp
))
{
/*
/*
*
* Day of year.
*
* Day of year.
*/
*/
rulep
->
r_type
=
DAY_OF_YEAR
;
rulep
->
r_type
=
DAY_OF_YEAR
;
strp
=
getnum
(
strp
,
&
rulep
->
r_day
,
0
,
DAYSPERLYEAR
-
1
);
strp
=
getnum
(
strp
,
&
rulep
->
r_day
,
0
,
DAYSPERLYEAR
-
1
);
}
else
return
NULL
;
/* invalid format */
}
else
return
NULL
;
/* invalid format */
if
(
strp
==
NULL
)
if
(
strp
==
NULL
)
return
NULL
;
return
NULL
;
if
(
*
strp
==
'/'
)
{
if
(
*
strp
==
'/'
)
{
/*
/*
*
* Time specified.
*
* Time specified.
*/
*/
++
strp
;
++
strp
;
strp
=
getsecs
(
strp
,
&
rulep
->
r_time
);
strp
=
getsecs
(
strp
,
&
rulep
->
r_time
);
}
else
rulep
->
r_time
=
2
*
SECSPERHOUR
;
/* default = 2:00:00 */
}
else
rulep
->
r_time
=
2
*
SECSPERHOUR
;
/* default = 2:00:00 */
return
strp
;
return
strp
;
}
}
...
@@ -458,87 +497,97 @@ static const char *getrule(const char *strp, register struct rule *rulep)
...
@@ -458,87 +497,97 @@ static const char *getrule(const char *strp, register struct rule *rulep)
** calculate the Epoch-relative time that rule takes effect.
** calculate the Epoch-relative time that rule takes effect.
*/
*/
static
time_t
transtime
(
const
time_t
janfirst
,
const
int
year
,
register
const
struct
rule
*
rulep
,
const
long
offset
)
static
time_t
transtime
(
const
time_t
janfirst
,
const
int
year
,
register
const
struct
rule
*
rulep
,
const
long
offset
)
{
{
register
int
leapyear
;
register
int
leapyear
;
register
time_t
value
=
0
;
register
time_t
value
=
0
;
register
int
i
;
register
int
i
;
int
d
,
m1
,
yy0
,
yy1
,
yy2
,
dow
;
int
d
,
m1
,
yy0
,
yy1
,
yy2
,
dow
;
leapyear
=
isleap
(
year
);
leapyear
=
isleap
(
year
);
switch
(
rulep
->
r_type
)
{
switch
(
rulep
->
r_type
)
{
case
JULIAN_DAY
:
case
JULIAN_DAY
:
/*
** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
** years.
** In non-leap years, or if the day number is 59 or less, just
** add SECSPERDAY times the day number-1 to the time of
** January 1, midnight, to get the day.
*/
value
=
janfirst
+
(
rulep
->
r_day
-
1
)
*
SECSPERDAY
;
if
(
leapyear
&&
rulep
->
r_day
>=
60
)
value
+=
SECSPERDAY
;
break
;
case
DAY_OF_YEAR
:
/*
** n - day of year.
** Just add SECSPERDAY times the day number to the time of
** January 1, midnight, to get the day.
*/
value
=
janfirst
+
rulep
->
r_day
*
SECSPERDAY
;
break
;
case
MONTH_NTH_DAY_OF_WEEK
:
/*
** Mm.n.d - nth "dth day" of month m.
*/
value
=
janfirst
;
for
(
i
=
0
;
i
<
rulep
->
r_mon
-
1
;
++
i
)
value
+=
mon_lengths
[
leapyear
][
i
]
*
SECSPERDAY
;
/*
/*
** Use Zeller's Congruence to get day-of-week of first day of
* * Jn - Julian day, 1 == January 1, 60 == March 1 even in
** month.
* leap * years. * In non-leap years, or if the day number is
*/
* 59 or less, just * add SECSPERDAY times the day number-1 to
m1
=
(
rulep
->
r_mon
+
9
)
%
12
+
1
;
* the time of * January 1, midnight, to get the day.
yy0
=
(
rulep
->
r_mon
<=
2
)
?
(
year
-
1
)
:
year
;
*/
yy1
=
yy0
/
100
;
value
=
janfirst
+
(
rulep
->
r_day
-
1
)
*
SECSPERDAY
;
yy2
=
yy0
%
100
;
if
(
leapyear
&&
rulep
->
r_day
>=
60
)
dow
=
((
26
*
m1
-
2
)
/
10
+
value
+=
SECSPERDAY
;
1
+
yy2
+
yy2
/
4
+
yy1
/
4
-
2
*
yy1
)
%
7
;
break
;
if
(
dow
<
0
)
dow
+=
DAYSPERWEEK
;
/*
case
DAY_OF_YEAR
:
** "dow" is the day-of-week of the first day of the month. Get
** the day-of-month (zero-origin) of the first "dow" day of the
/*
** month.
* * n - day of year. * Just add SECSPERDAY times the day
*/
* number to the time of * January 1, midnight, to get the
d
=
rulep
->
r_day
-
dow
;
* day.
if
(
d
<
0
)
*/
d
+=
DAYSPERWEEK
;
value
=
janfirst
+
rulep
->
r_day
*
SECSPERDAY
;
for
(
i
=
1
;
i
<
rulep
->
r_week
;
++
i
)
{
break
;
if
(
d
+
DAYSPERWEEK
>=
mon_lengths
[
leapyear
][
rulep
->
r_mon
-
1
])
case
MONTH_NTH_DAY_OF_WEEK
:
/*
* * Mm.n.d - nth "dth day" of month m.
*/
value
=
janfirst
;
for
(
i
=
0
;
i
<
rulep
->
r_mon
-
1
;
++
i
)
value
+=
mon_lengths
[
leapyear
][
i
]
*
SECSPERDAY
;
/*
* * Use Zeller's Congruence to get day-of-week of first day
* of * month.
*/
m1
=
(
rulep
->
r_mon
+
9
)
%
12
+
1
;
yy0
=
(
rulep
->
r_mon
<=
2
)
?
(
year
-
1
)
:
year
;
yy1
=
yy0
/
100
;
yy2
=
yy0
%
100
;
dow
=
((
26
*
m1
-
2
)
/
10
+
1
+
yy2
+
yy2
/
4
+
yy1
/
4
-
2
*
yy1
)
%
7
;
if
(
dow
<
0
)
dow
+=
DAYSPERWEEK
;
/*
* * "dow" is the day-of-week of the first day of the month.
* Get * the day-of-month (zero-origin) of the first "dow" day
* of the * month.
*/
d
=
rulep
->
r_day
-
dow
;
if
(
d
<
0
)
d
+=
DAYSPERWEEK
;
for
(
i
=
1
;
i
<
rulep
->
r_week
;
++
i
)
{
if
(
d
+
DAYSPERWEEK
>=
mon_lengths
[
leapyear
][
rulep
->
r_mon
-
1
])
break
;
break
;
d
+=
DAYSPERWEEK
;
d
+=
DAYSPERWEEK
;
}
}
/*
/*
*
* "d" is the day-of-month (zero-origin) of the day we want.
*
* "d" is the day-of-month (zero-origin) of the day we want.
*/
*/
value
+=
d
*
SECSPERDAY
;
value
+=
d
*
SECSPERDAY
;
break
;
break
;
}
}
/*
/*
** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
* * "value" is the Epoch-relative time of 00:00:00 UTC on the day in *
** question. To get the Epoch-relative time of the specified local
* question. To get the Epoch-relative time of the specified local *
** time on that day, add the transition time and the current offset
* time on that day, add the transition time and the current offset *
*
* from UTC.
* from UTC.
*/
*/
return
value
+
rulep
->
r_time
+
offset
;
return
value
+
rulep
->
r_time
+
offset
;
}
}
...
@@ -547,27 +596,31 @@ static time_t transtime(const time_t janfirst, const int year, register const st
...
@@ -547,27 +596,31 @@ static time_t transtime(const time_t janfirst, const int year, register const st
** appropriate.
** appropriate.
*/
*/
static
int
tzparse
(
const
char
*
name
,
register
struct
state
*
sp
,
const
int
lastditch
)
static
int
tzparse
(
const
char
*
name
,
register
struct
state
*
sp
,
const
int
lastditch
)
{
{
const
char
*
stdname
;
const
char
*
stdname
;
const
char
*
dstname
=
NULL
;
const
char
*
dstname
=
NULL
;
size_t
stdlen
;
size_t
stdlen
;
size_t
dstlen
;
size_t
dstlen
;
long
stdoffset
;
long
stdoffset
;
long
dstoffset
;
long
dstoffset
;
register
time_t
*
atp
;
register
time_t
*
atp
;
register
unsigned
char
*
typep
;
register
unsigned
char
*
typep
;
register
char
*
cp
;
register
char
*
cp
;
register
int
load_result
;
register
int
load_result
;
stdname
=
name
;
stdname
=
name
;
if
(
lastditch
)
{
if
(
lastditch
)
{
stdlen
=
strlen
(
name
);
/* length of standard zone name */
stdlen
=
strlen
(
name
);
/* length of standard zone name */
name
+=
stdlen
;
name
+=
stdlen
;
if
(
stdlen
>=
sizeof
sp
->
chars
)
if
(
stdlen
>=
sizeof
sp
->
chars
)
stdlen
=
(
sizeof
sp
->
chars
)
-
1
;
stdlen
=
(
sizeof
sp
->
chars
)
-
1
;
stdoffset
=
0
;
stdoffset
=
0
;
}
else
{
}
else
{
name
=
getzname
(
name
);
name
=
getzname
(
name
);
stdlen
=
name
-
stdname
;
stdlen
=
name
-
stdname
;
if
(
stdlen
<
3
)
if
(
stdlen
<
3
)
...
@@ -581,24 +634,29 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
...
@@ -581,24 +634,29 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
load_result
=
tzload
(
TZDEFRULES
,
sp
);
load_result
=
tzload
(
TZDEFRULES
,
sp
);
if
(
load_result
!=
0
)
if
(
load_result
!=
0
)
sp
->
leapcnt
=
0
;
/* so, we're off a little */
sp
->
leapcnt
=
0
;
/* so, we're off a little */
if
(
*
name
!=
'\0'
)
{
if
(
*
name
!=
'\0'
)
{
dstname
=
name
;
dstname
=
name
;
name
=
getzname
(
name
);
name
=
getzname
(
name
);
dstlen
=
name
-
dstname
;
/* length of DST zone name */
dstlen
=
name
-
dstname
;
/* length of DST zone name */
if
(
dstlen
<
3
)
if
(
dstlen
<
3
)
return
-
1
;
return
-
1
;
if
(
*
name
!=
'\0'
&&
*
name
!=
','
&&
*
name
!=
';'
)
{
if
(
*
name
!=
'\0'
&&
*
name
!=
','
&&
*
name
!=
';'
)
{
name
=
getoffset
(
name
,
&
dstoffset
);
name
=
getoffset
(
name
,
&
dstoffset
);
if
(
name
==
NULL
)
if
(
name
==
NULL
)
return
-
1
;
return
-
1
;
}
else
dstoffset
=
stdoffset
-
SECSPERHOUR
;
}
else
dstoffset
=
stdoffset
-
SECSPERHOUR
;
if
(
*
name
==
'\0'
&&
load_result
!=
0
)
if
(
*
name
==
'\0'
&&
load_result
!=
0
)
name
=
TZDEFRULESTRING
;
name
=
TZDEFRULESTRING
;
if
(
*
name
==
','
||
*
name
==
';'
)
{
if
(
*
name
==
','
||
*
name
==
';'
)
struct
rule
start
;
{
struct
rule
end
;
struct
rule
start
;
register
int
year
;
struct
rule
end
;
register
time_t
janfirst
;
register
int
year
;
register
time_t
janfirst
;
time_t
starttime
;
time_t
starttime
;
time_t
endtime
;
time_t
endtime
;
...
@@ -612,9 +670,10 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
...
@@ -612,9 +670,10 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
if
(
*
name
!=
'\0'
)
if
(
*
name
!=
'\0'
)
return
-
1
;
return
-
1
;
sp
->
typecnt
=
2
;
/* standard time and DST */
sp
->
typecnt
=
2
;
/* standard time and DST */
/*
/*
*
* Two transitions per year, from EPOCH_YEAR to 2037.
*
* Two transitions per year, from EPOCH_YEAR to 2037.
*/
*/
sp
->
timecnt
=
2
*
(
2037
-
EPOCH_YEAR
+
1
);
sp
->
timecnt
=
2
*
(
2037
-
EPOCH_YEAR
+
1
);
if
(
sp
->
timecnt
>
TZ_MAX_TIMES
)
if
(
sp
->
timecnt
>
TZ_MAX_TIMES
)
return
-
1
;
return
-
1
;
...
@@ -627,89 +686,108 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
...
@@ -627,89 +686,108 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
atp
=
sp
->
ats
;
atp
=
sp
->
ats
;
typep
=
sp
->
types
;
typep
=
sp
->
types
;
janfirst
=
0
;
janfirst
=
0
;
for
(
year
=
EPOCH_YEAR
;
year
<=
2037
;
++
year
)
{
for
(
year
=
EPOCH_YEAR
;
year
<=
2037
;
++
year
)
{
starttime
=
transtime
(
janfirst
,
year
,
&
start
,
starttime
=
transtime
(
janfirst
,
year
,
&
start
,
stdoffset
);
stdoffset
);
endtime
=
transtime
(
janfirst
,
year
,
&
end
,
endtime
=
transtime
(
janfirst
,
year
,
&
end
,
dstoffset
);
dstoffset
);
if
(
starttime
>
endtime
)
{
if
(
starttime
>
endtime
)
{
*
atp
++
=
endtime
;
*
atp
++
=
endtime
;
*
typep
++
=
1
;
/* DST ends */
*
typep
++
=
1
;
/* DST ends */
*
atp
++
=
starttime
;
*
atp
++
=
starttime
;
*
typep
++
=
0
;
/* DST begins */
*
typep
++
=
0
;
/* DST begins */
}
else
{
}
else
{
*
atp
++
=
starttime
;
*
atp
++
=
starttime
;
*
typep
++
=
0
;
/* DST begins */
*
typep
++
=
0
;
/* DST begins */
*
atp
++
=
endtime
;
*
atp
++
=
endtime
;
*
typep
++
=
1
;
/* DST ends */
*
typep
++
=
1
;
/* DST ends */
}
}
janfirst
+=
year_lengths
[
isleap
(
year
)]
*
janfirst
+=
year_lengths
[
isleap
(
year
)]
*
SECSPERDAY
;
SECSPERDAY
;
}
}
}
else
{
}
register
long
theirstdoffset
;
else
register
long
theirdstoffset
;
{
register
long
theiroffset
;
register
long
theirstdoffset
;
register
int
isdst
;
register
long
theirdstoffset
;
register
int
i
;
register
long
theiroffset
;
register
int
j
;
register
int
isdst
;
register
int
i
;
register
int
j
;
if
(
*
name
!=
'\0'
)
if
(
*
name
!=
'\0'
)
return
-
1
;
return
-
1
;
/*
/*
*
* Initial values of theirstdoffset and theirdstoffset.
*
* Initial values of theirstdoffset and theirdstoffset.
*/
*/
theirstdoffset
=
0
;
theirstdoffset
=
0
;
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
j
=
sp
->
types
[
i
];
j
=
sp
->
types
[
i
];
if
(
!
sp
->
ttis
[
j
].
tt_isdst
)
{
if
(
!
sp
->
ttis
[
j
].
tt_isdst
)
{
theirstdoffset
=
theirstdoffset
=
-
sp
->
ttis
[
j
].
tt_gmtoff
;
-
sp
->
ttis
[
j
].
tt_gmtoff
;
break
;
break
;
}
}
}
}
theirdstoffset
=
0
;
theirdstoffset
=
0
;
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
j
=
sp
->
types
[
i
];
j
=
sp
->
types
[
i
];
if
(
sp
->
ttis
[
j
].
tt_isdst
)
{
if
(
sp
->
ttis
[
j
].
tt_isdst
)
{
theirdstoffset
=
theirdstoffset
=
-
sp
->
ttis
[
j
].
tt_gmtoff
;
-
sp
->
ttis
[
j
].
tt_gmtoff
;
break
;
break
;
}
}
}
}
/*
/*
*
* Initially we're assumed to be in standard time.
*
* Initially we're assumed to be in standard time.
*/
*/
isdst
=
FALSE
;
isdst
=
FALSE
;
theiroffset
=
theirstdoffset
;
theiroffset
=
theirstdoffset
;
/*
/*
** Now juggle transition times and types
* * Now juggle transition times and types * tracking offsets
** tracking offsets as you do.
* as you do.
*/
*/
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
sp
->
timecnt
;
++
i
)
{
j
=
sp
->
types
[
i
];
j
=
sp
->
types
[
i
];
sp
->
types
[
i
]
=
sp
->
ttis
[
j
].
tt_isdst
;
sp
->
types
[
i
]
=
sp
->
ttis
[
j
].
tt_isdst
;
if
(
sp
->
ttis
[
j
].
tt_ttisgmt
)
{
if
(
sp
->
ttis
[
j
].
tt_ttisgmt
)
{
/* No adjustment to transition time */
/* No adjustment to transition time */
}
else
{
}
else
{
/*
/*
** If summer time is in effect, and the
* * If summer time is in effect, and the * transition
** transition time was not specified as
* time was not specified as * standard time, add the
** standard time, add the summer time
* summer time * offset to the transition time; *
** offset to the transition time;
* otherwise, add the standard time * offset to the
** otherwise, add the standard time
* transition time.
** offset to the transition time.
*/
*/
/*
/*
** Transitions from DST to DDST
* * Transitions from DST to DDST * will effectively
** will effectively disappear since
* disappear since * POSIX provides for only one DST *
** POSIX provides for only one DST
* offset.
** offset.
*/
*/
if
(
isdst
&&
!
sp
->
ttis
[
j
].
tt_ttisstd
)
if
(
isdst
&&
!
sp
->
ttis
[
j
].
tt_ttisstd
)
{
{
sp
->
ats
[
i
]
+=
dstoffset
-
sp
->
ats
[
i
]
+=
dstoffset
-
theirdstoffset
;
theirdstoffset
;
}
else
{
}
else
{
sp
->
ats
[
i
]
+=
stdoffset
-
sp
->
ats
[
i
]
+=
stdoffset
-
theirstdoffset
;
theirstdoffset
;
}
}
...
@@ -717,12 +795,14 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
...
@@ -717,12 +795,14 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
theiroffset
=
-
sp
->
ttis
[
j
].
tt_gmtoff
;
theiroffset
=
-
sp
->
ttis
[
j
].
tt_gmtoff
;
if
(
sp
->
ttis
[
j
].
tt_isdst
)
if
(
sp
->
ttis
[
j
].
tt_isdst
)
theirdstoffset
=
theiroffset
;
theirdstoffset
=
theiroffset
;
else
theirstdoffset
=
theiroffset
;
else
theirstdoffset
=
theiroffset
;
}
}
/*
/*
** Finally, fill in ttis.
* * Finally, fill in ttis. * ttisstd and ttisgmt need not be
** ttisstd and ttisgmt need not be
handled.
*
handled.
*/
*/
sp
->
ttis
[
0
].
tt_gmtoff
=
-
stdoffset
;
sp
->
ttis
[
0
].
tt_gmtoff
=
-
stdoffset
;
sp
->
ttis
[
0
].
tt_isdst
=
FALSE
;
sp
->
ttis
[
0
].
tt_isdst
=
FALSE
;
sp
->
ttis
[
0
].
tt_abbrind
=
0
;
sp
->
ttis
[
0
].
tt_abbrind
=
0
;
...
@@ -731,7 +811,9 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
...
@@ -731,7 +811,9 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
sp
->
ttis
[
1
].
tt_abbrind
=
stdlen
+
1
;
sp
->
ttis
[
1
].
tt_abbrind
=
stdlen
+
1
;
sp
->
typecnt
=
2
;
sp
->
typecnt
=
2
;
}
}
}
else
{
}
else
{
dstlen
=
0
;
dstlen
=
0
;
sp
->
typecnt
=
1
;
/* only standard time */
sp
->
typecnt
=
1
;
/* only standard time */
sp
->
timecnt
=
0
;
sp
->
timecnt
=
0
;
...
@@ -748,29 +830,33 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
...
@@ -748,29 +830,33 @@ static int tzparse(const char *name, register struct state *sp, const int lastdi
(
void
)
strncpy
(
cp
,
stdname
,
stdlen
);
(
void
)
strncpy
(
cp
,
stdname
,
stdlen
);
cp
+=
stdlen
;
cp
+=
stdlen
;
*
cp
++
=
'\0'
;
*
cp
++
=
'\0'
;
if
(
dstlen
!=
0
)
{
if
(
dstlen
!=
0
)
{
(
void
)
strncpy
(
cp
,
dstname
,
dstlen
);
(
void
)
strncpy
(
cp
,
dstname
,
dstlen
);
*
(
cp
+
dstlen
)
=
'\0'
;
*
(
cp
+
dstlen
)
=
'\0'
;
}
}
return
0
;
return
0
;
}
}
static
void
gmtload
(
struct
state
*
sp
)
static
void
gmtload
(
struct
state
*
sp
)
{
{
if
(
tzload
(
gmt
,
sp
)
!=
0
)
if
(
tzload
(
gmt
,
sp
)
!=
0
)
(
void
)
tzparse
(
gmt
,
sp
,
TRUE
);
(
void
)
tzparse
(
gmt
,
sp
,
TRUE
);
}
}
bool
pg_tzset
(
const
char
*
name
)
bool
pg_tzset
(
const
char
*
name
)
{
{
if
(
lcl_is_set
&&
strcmp
(
lcl_TZname
,
name
)
==
0
)
if
(
lcl_is_set
&&
strcmp
(
lcl_TZname
,
name
)
==
0
)
return
true
;
/* no change */
return
true
;
/* no change */
if
(
strlen
(
name
)
>=
sizeof
(
lcl_TZname
))
if
(
strlen
(
name
)
>=
sizeof
(
lcl_TZname
))
return
false
;
/* not gonna fit */
return
false
;
/* not gonna fit */
if
(
tzload
(
name
,
lclptr
)
!=
0
)
{
if
(
tzload
(
name
,
lclptr
)
!=
0
)
{
if
(
name
[
0
]
==
':'
||
tzparse
(
name
,
lclptr
,
FALSE
)
!=
0
)
if
(
name
[
0
]
==
':'
||
tzparse
(
name
,
lclptr
,
FALSE
)
!=
0
)
{
{
/* Unknown timezone. Fail our call instead of loading GMT! */
/* Unknown timezone. Fail our call instead of loading GMT! */
...
@@ -793,40 +879,46 @@ bool pg_tzset(const char *name)
...
@@ -793,40 +879,46 @@ bool pg_tzset(const char *name)
** The unused offset argument is for the benefit of mktime variants.
** The unused offset argument is for the benefit of mktime variants.
*/
*/
static
void
localsub
(
const
time_t
*
timep
,
const
long
offset
,
struct
pg_tm
*
tmp
)
static
void
localsub
(
const
time_t
*
timep
,
const
long
offset
,
struct
pg_tm
*
tmp
)
{
{
register
struct
state
*
sp
;
register
struct
state
*
sp
;
register
const
struct
ttinfo
*
ttisp
;
register
const
struct
ttinfo
*
ttisp
;
register
int
i
;
register
int
i
;
const
time_t
t
=
*
timep
;
const
time_t
t
=
*
timep
;
sp
=
lclptr
;
sp
=
lclptr
;
if
(
sp
->
timecnt
==
0
||
t
<
sp
->
ats
[
0
])
{
if
(
sp
->
timecnt
==
0
||
t
<
sp
->
ats
[
0
])
{
i
=
0
;
i
=
0
;
while
(
sp
->
ttis
[
i
].
tt_isdst
)
while
(
sp
->
ttis
[
i
].
tt_isdst
)
if
(
++
i
>=
sp
->
typecnt
)
{
if
(
++
i
>=
sp
->
typecnt
)
{
i
=
0
;
i
=
0
;
break
;
break
;
}
}
}
else
{
}
else
{
for
(
i
=
1
;
i
<
sp
->
timecnt
;
++
i
)
for
(
i
=
1
;
i
<
sp
->
timecnt
;
++
i
)
if
(
t
<
sp
->
ats
[
i
])
if
(
t
<
sp
->
ats
[
i
])
break
;
break
;
i
=
sp
->
types
[
i
-
1
];
i
=
sp
->
types
[
i
-
1
];
}
}
ttisp
=
&
sp
->
ttis
[
i
];
ttisp
=
&
sp
->
ttis
[
i
];
/*
/*
** To get (wrong) behavior that's compatible with System V Release 2.0
* * To get (wrong) behavior that's compatible with System V Release
** you'd replace the statement below with
* 2.0 * you'd replace the statement below with * t +=
** t += ttisp->tt_gmtoff;
* ttisp->tt_gmtoff; * timesub(&t, 0L, sp, tmp);
** timesub(&t, 0L, sp, tmp);
*/
*/
timesub
(
&
t
,
ttisp
->
tt_gmtoff
,
sp
,
tmp
);
timesub
(
&
t
,
ttisp
->
tt_gmtoff
,
sp
,
tmp
);
tmp
->
tm_isdst
=
ttisp
->
tt_isdst
;
tmp
->
tm_isdst
=
ttisp
->
tt_isdst
;
tmp
->
tm_zone
=
&
sp
->
chars
[
ttisp
->
tt_abbrind
];
tmp
->
tm_zone
=
&
sp
->
chars
[
ttisp
->
tt_abbrind
];
}
}
struct
pg_tm
*
pg_localtime
(
const
time_t
*
timep
)
struct
pg_tm
*
pg_localtime
(
const
time_t
*
timep
)
{
{
localsub
(
timep
,
0L
,
&
tm
);
localsub
(
timep
,
0L
,
&
tm
);
return
&
tm
;
return
&
tm
;
...
@@ -837,61 +929,69 @@ struct pg_tm *pg_localtime(const time_t *timep)
...
@@ -837,61 +929,69 @@ struct pg_tm *pg_localtime(const time_t *timep)
** gmtsub is to gmtime as localsub is to localtime.
** gmtsub is to gmtime as localsub is to localtime.
*/
*/
static
void
gmtsub
(
const
time_t
*
timep
,
const
long
offset
,
struct
pg_tm
*
tmp
)
static
void
gmtsub
(
const
time_t
*
timep
,
const
long
offset
,
struct
pg_tm
*
tmp
)
{
{
if
(
!
gmt_is_set
)
{
if
(
!
gmt_is_set
)
{
gmt_is_set
=
TRUE
;
gmt_is_set
=
TRUE
;
gmtload
(
gmtptr
);
gmtload
(
gmtptr
);
}
}
timesub
(
timep
,
offset
,
gmtptr
,
tmp
);
timesub
(
timep
,
offset
,
gmtptr
,
tmp
);
/*
/*
** Could get fancy here and deliver something such as
* * Could get fancy here and deliver something such as * "UTC+xxxx"
** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
* or "UTC-xxxx" if offset is non-zero, * but this is no time for a
** but this is no time for a
treasure hunt.
*
treasure hunt.
*/
*/
if
(
offset
!=
0
)
if
(
offset
!=
0
)
tmp
->
tm_zone
=
wildabbr
;
tmp
->
tm_zone
=
wildabbr
;
else
{
else
tmp
->
tm_zone
=
gmtptr
->
chars
;
tmp
->
tm_zone
=
gmtptr
->
chars
;
}
}
}
struct
pg_tm
*
pg_gmtime
(
const
time_t
*
timep
)
struct
pg_tm
*
pg_gmtime
(
const
time_t
*
timep
)
{
{
gmtsub
(
timep
,
0L
,
&
tm
);
gmtsub
(
timep
,
0L
,
&
tm
);
return
&
tm
;
return
&
tm
;
}
}
static
void
timesub
(
const
time_t
*
timep
,
const
long
offset
,
register
const
struct
state
*
sp
,
register
struct
pg_tm
*
tmp
)
static
void
timesub
(
const
time_t
*
timep
,
const
long
offset
,
register
const
struct
state
*
sp
,
register
struct
pg_tm
*
tmp
)
{
{
register
const
struct
lsinfo
*
lp
;
register
const
struct
lsinfo
*
lp
;
register
long
days
;
register
long
days
;
register
long
rem
;
register
long
rem
;
register
int
y
;
register
int
y
;
register
int
yleap
;
register
int
yleap
;
register
const
int
*
ip
;
register
const
int
*
ip
;
register
long
corr
;
register
long
corr
;
register
int
hit
;
register
int
hit
;
register
int
i
;
register
int
i
;
corr
=
0
;
corr
=
0
;
hit
=
0
;
hit
=
0
;
i
=
sp
->
leapcnt
;
i
=
sp
->
leapcnt
;
while
(
--
i
>=
0
)
{
while
(
--
i
>=
0
)
{
lp
=
&
sp
->
lsis
[
i
];
lp
=
&
sp
->
lsis
[
i
];
if
(
*
timep
>=
lp
->
ls_trans
)
{
if
(
*
timep
>=
lp
->
ls_trans
)
if
(
*
timep
==
lp
->
ls_trans
)
{
{
if
(
*
timep
==
lp
->
ls_trans
)
{
hit
=
((
i
==
0
&&
lp
->
ls_corr
>
0
)
||
hit
=
((
i
==
0
&&
lp
->
ls_corr
>
0
)
||
lp
->
ls_corr
>
sp
->
lsis
[
i
-
1
].
ls_corr
);
lp
->
ls_corr
>
sp
->
lsis
[
i
-
1
].
ls_corr
);
if
(
hit
)
if
(
hit
)
while
(
i
>
0
&&
while
(
i
>
0
&&
sp
->
lsis
[
i
].
ls_trans
==
sp
->
lsis
[
i
].
ls_trans
==
sp
->
lsis
[
i
-
1
].
ls_trans
+
1
&&
sp
->
lsis
[
i
-
1
].
ls_trans
+
1
&&
sp
->
lsis
[
i
].
ls_corr
==
sp
->
lsis
[
i
].
ls_corr
==
sp
->
lsis
[
i
-
1
].
ls_corr
+
1
)
{
sp
->
lsis
[
i
-
1
].
ls_corr
+
1
)
++
hit
;
{
--
i
;
++
hit
;
--
i
;
}
}
}
}
corr
=
lp
->
ls_corr
;
corr
=
lp
->
ls_corr
;
...
@@ -901,38 +1001,43 @@ static void timesub(const time_t *timep, const long offset, register const struc
...
@@ -901,38 +1001,43 @@ static void timesub(const time_t *timep, const long offset, register const struc
days
=
*
timep
/
SECSPERDAY
;
days
=
*
timep
/
SECSPERDAY
;
rem
=
*
timep
%
SECSPERDAY
;
rem
=
*
timep
%
SECSPERDAY
;
#ifdef mc68k
#ifdef mc68k
if
(
*
timep
==
0x80000000
)
{
if
(
*
timep
==
0x80000000
)
{
/*
/*
*
* A 3B1 muffs the division on the most negative number.
*
* A 3B1 muffs the division on the most negative number.
*/
*/
days
=
-
24855
;
days
=
-
24855
;
rem
=
-
11648
;
rem
=
-
11648
;
}
}
#endif
/* defined mc68k */
#endif
/* defined mc68k */
rem
+=
(
offset
-
corr
);
rem
+=
(
offset
-
corr
);
while
(
rem
<
0
)
{
while
(
rem
<
0
)
{
rem
+=
SECSPERDAY
;
rem
+=
SECSPERDAY
;
--
days
;
--
days
;
}
}
while
(
rem
>=
SECSPERDAY
)
{
while
(
rem
>=
SECSPERDAY
)
{
rem
-=
SECSPERDAY
;
rem
-=
SECSPERDAY
;
++
days
;
++
days
;
}
}
tmp
->
tm_hour
=
(
int
)
(
rem
/
SECSPERHOUR
);
tmp
->
tm_hour
=
(
int
)
(
rem
/
SECSPERHOUR
);
rem
=
rem
%
SECSPERHOUR
;
rem
=
rem
%
SECSPERHOUR
;
tmp
->
tm_min
=
(
int
)
(
rem
/
SECSPERMIN
);
tmp
->
tm_min
=
(
int
)
(
rem
/
SECSPERMIN
);
/*
/*
** A positive leap second requires a special
* * A positive leap second requires a special * representation. This
** representation. This
uses "... ??:59:60" et seq.
*
uses "... ??:59:60" et seq.
*/
*/
tmp
->
tm_sec
=
(
int
)
(
rem
%
SECSPERMIN
)
+
hit
;
tmp
->
tm_sec
=
(
int
)
(
rem
%
SECSPERMIN
)
+
hit
;
tmp
->
tm_wday
=
(
int
)
((
EPOCH_WDAY
+
days
)
%
DAYSPERWEEK
);
tmp
->
tm_wday
=
(
int
)
((
EPOCH_WDAY
+
days
)
%
DAYSPERWEEK
);
if
(
tmp
->
tm_wday
<
0
)
if
(
tmp
->
tm_wday
<
0
)
tmp
->
tm_wday
+=
DAYSPERWEEK
;
tmp
->
tm_wday
+=
DAYSPERWEEK
;
y
=
EPOCH_YEAR
;
y
=
EPOCH_YEAR
;
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
while
(
days
<
0
||
days
>=
(
long
)
year_lengths
[
yleap
=
isleap
(
y
)])
{
while
(
days
<
0
||
days
>=
(
long
)
year_lengths
[
yleap
=
isleap
(
y
)])
register
int
newy
;
{
register
int
newy
;
newy
=
y
+
days
/
DAYSPERNYEAR
;
newy
=
y
+
days
/
DAYSPERNYEAR
;
if
(
days
<
0
)
if
(
days
<
0
)
...
@@ -968,18 +1073,20 @@ static void timesub(const time_t *timep, const long offset, register const struc
...
@@ -968,18 +1073,20 @@ static void timesub(const time_t *timep, const long offset, register const struc
** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
*/
*/
static
int
increment_overflow
(
int
*
number
,
int
delta
)
static
int
increment_overflow
(
int
*
number
,
int
delta
)
{
{
int
number0
;
int
number0
;
number0
=
*
number
;
number0
=
*
number
;
*
number
+=
delta
;
*
number
+=
delta
;
return
(
*
number
<
number0
)
!=
(
delta
<
0
);
return
(
*
number
<
number0
)
!=
(
delta
<
0
);
}
}
static
int
normalize_overflow
(
int
*
tensptr
,
int
*
unitsptr
,
const
int
base
)
static
int
normalize_overflow
(
int
*
tensptr
,
int
*
unitsptr
,
const
int
base
)
{
{
register
int
tensdelta
;
register
int
tensdelta
;
tensdelta
=
(
*
unitsptr
>=
0
)
?
tensdelta
=
(
*
unitsptr
>=
0
)
?
(
*
unitsptr
/
base
)
:
(
*
unitsptr
/
base
)
:
...
@@ -988,36 +1095,40 @@ static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
...
@@ -988,36 +1095,40 @@ static int normalize_overflow(int *tensptr, int *unitsptr, const int base)
return
increment_overflow
(
tensptr
,
tensdelta
);
return
increment_overflow
(
tensptr
,
tensdelta
);
}
}
static
int
tmcomp
(
register
const
struct
pg_tm
*
atmp
,
register
const
struct
pg_tm
*
btmp
)
static
int
tmcomp
(
register
const
struct
pg_tm
*
atmp
,
register
const
struct
pg_tm
*
btmp
)
{
{
register
int
result
;
register
int
result
;
if
((
result
=
(
atmp
->
tm_year
-
btmp
->
tm_year
))
==
0
&&
if
((
result
=
(
atmp
->
tm_year
-
btmp
->
tm_year
))
==
0
&&
(
result
=
(
atmp
->
tm_mon
-
btmp
->
tm_mon
))
==
0
&&
(
result
=
(
atmp
->
tm_mon
-
btmp
->
tm_mon
))
==
0
&&
(
result
=
(
atmp
->
tm_mday
-
btmp
->
tm_mday
))
==
0
&&
(
result
=
(
atmp
->
tm_mday
-
btmp
->
tm_mday
))
==
0
&&
(
result
=
(
atmp
->
tm_hour
-
btmp
->
tm_hour
))
==
0
&&
(
result
=
(
atmp
->
tm_hour
-
btmp
->
tm_hour
))
==
0
&&
(
result
=
(
atmp
->
tm_min
-
btmp
->
tm_min
))
==
0
)
(
result
=
(
atmp
->
tm_min
-
btmp
->
tm_min
))
==
0
)
result
=
atmp
->
tm_sec
-
btmp
->
tm_sec
;
result
=
atmp
->
tm_sec
-
btmp
->
tm_sec
;
return
result
;
return
result
;
}
}
static
time_t
time2sub
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
const
long
offset
,
int
*
okayp
,
const
int
do_norm_secs
)
static
time_t
time2sub
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
const
long
offset
,
int
*
okayp
,
const
int
do_norm_secs
)
{
{
register
const
struct
state
*
sp
;
register
const
struct
state
*
sp
;
register
int
dir
;
register
int
dir
;
register
int
bits
;
register
int
bits
;
register
int
i
,
j
;
register
int
i
,
register
int
saved_seconds
;
j
;
time_t
newt
;
register
int
saved_seconds
;
time_t
t
;
time_t
newt
;
struct
pg_tm
yourtm
,
mytm
;
time_t
t
;
struct
pg_tm
yourtm
,
mytm
;
*
okayp
=
FALSE
;
*
okayp
=
FALSE
;
yourtm
=
*
tmp
;
yourtm
=
*
tmp
;
if
(
do_norm_secs
)
{
if
(
do_norm_secs
)
{
if
(
normalize_overflow
(
&
yourtm
.
tm_min
,
&
yourtm
.
tm_sec
,
if
(
normalize_overflow
(
&
yourtm
.
tm_min
,
&
yourtm
.
tm_sec
,
SECSPERMIN
))
SECSPERMIN
))
return
WRONG
;
return
WRONG
;
}
}
if
(
normalize_overflow
(
&
yourtm
.
tm_hour
,
&
yourtm
.
tm_min
,
MINSPERHOUR
))
if
(
normalize_overflow
(
&
yourtm
.
tm_hour
,
&
yourtm
.
tm_min
,
MINSPERHOUR
))
return
WRONG
;
return
WRONG
;
...
@@ -1025,30 +1136,35 @@ static time_t time2sub(struct pg_tm *tmp, void(*funcp)(const time_t *, long, str
...
@@ -1025,30 +1136,35 @@ static time_t time2sub(struct pg_tm *tmp, void(*funcp)(const time_t *, long, str
return
WRONG
;
return
WRONG
;
if
(
normalize_overflow
(
&
yourtm
.
tm_year
,
&
yourtm
.
tm_mon
,
MONSPERYEAR
))
if
(
normalize_overflow
(
&
yourtm
.
tm_year
,
&
yourtm
.
tm_mon
,
MONSPERYEAR
))
return
WRONG
;
return
WRONG
;
/*
/*
** Turn yourtm.tm_year into an actual year number for now.
* * Turn yourtm.tm_year into an actual year number for now. * It is
** It is
converted back to an offset from TM_YEAR_BASE later.
*
converted back to an offset from TM_YEAR_BASE later.
*/
*/
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
TM_YEAR_BASE
))
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
TM_YEAR_BASE
))
return
WRONG
;
return
WRONG
;
while
(
yourtm
.
tm_mday
<=
0
)
{
while
(
yourtm
.
tm_mday
<=
0
)
{
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
-
1
))
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
-
1
))
return
WRONG
;
return
WRONG
;
i
=
yourtm
.
tm_year
+
(
1
<
yourtm
.
tm_mon
);
i
=
yourtm
.
tm_year
+
(
1
<
yourtm
.
tm_mon
);
yourtm
.
tm_mday
+=
year_lengths
[
isleap
(
i
)];
yourtm
.
tm_mday
+=
year_lengths
[
isleap
(
i
)];
}
}
while
(
yourtm
.
tm_mday
>
DAYSPERLYEAR
)
{
while
(
yourtm
.
tm_mday
>
DAYSPERLYEAR
)
{
i
=
yourtm
.
tm_year
+
(
1
<
yourtm
.
tm_mon
);
i
=
yourtm
.
tm_year
+
(
1
<
yourtm
.
tm_mon
);
yourtm
.
tm_mday
-=
year_lengths
[
isleap
(
i
)];
yourtm
.
tm_mday
-=
year_lengths
[
isleap
(
i
)];
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
1
))
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
1
))
return
WRONG
;
return
WRONG
;
}
}
for
(
;
;
)
{
for
(;;)
{
i
=
mon_lengths
[
isleap
(
yourtm
.
tm_year
)][
yourtm
.
tm_mon
];
i
=
mon_lengths
[
isleap
(
yourtm
.
tm_year
)][
yourtm
.
tm_mon
];
if
(
yourtm
.
tm_mday
<=
i
)
if
(
yourtm
.
tm_mday
<=
i
)
break
;
break
;
yourtm
.
tm_mday
-=
i
;
yourtm
.
tm_mday
-=
i
;
if
(
++
yourtm
.
tm_mon
>=
MONSPERYEAR
)
{
if
(
++
yourtm
.
tm_mon
>=
MONSPERYEAR
)
{
yourtm
.
tm_mon
=
0
;
yourtm
.
tm_mon
=
0
;
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
1
))
if
(
increment_overflow
(
&
yourtm
.
tm_year
,
1
))
return
WRONG
;
return
WRONG
;
...
@@ -1058,77 +1174,87 @@ static time_t time2sub(struct pg_tm *tmp, void(*funcp)(const time_t *, long, str
...
@@ -1058,77 +1174,87 @@ static time_t time2sub(struct pg_tm *tmp, void(*funcp)(const time_t *, long, str
return
WRONG
;
return
WRONG
;
if
(
yourtm
.
tm_sec
>=
0
&&
yourtm
.
tm_sec
<
SECSPERMIN
)
if
(
yourtm
.
tm_sec
>=
0
&&
yourtm
.
tm_sec
<
SECSPERMIN
)
saved_seconds
=
0
;
saved_seconds
=
0
;
else
if
(
yourtm
.
tm_year
+
TM_YEAR_BASE
<
EPOCH_YEAR
)
{
else
if
(
yourtm
.
tm_year
+
TM_YEAR_BASE
<
EPOCH_YEAR
)
{
/*
/*
** We can't set tm_sec to 0, because that might push the
* * We can't set tm_sec to 0, because that might push the * time
** time below the minimum representable time.
* below the minimum representable time. * Set tm_sec to 59
** Set tm_sec to 59 instead.
* instead. * This assumes that the minimum representable time is *
** This assumes that the minimum representable time is
* not in the same minute that a leap second was deleted from, *
** not in the same minute that a leap second was deleted from,
* which is a safer assumption than using 58 would be.
** which is a safer assumption than using 58 would be.
*/
*/
if
(
increment_overflow
(
&
yourtm
.
tm_sec
,
1
-
SECSPERMIN
))
if
(
increment_overflow
(
&
yourtm
.
tm_sec
,
1
-
SECSPERMIN
))
return
WRONG
;
return
WRONG
;
saved_seconds
=
yourtm
.
tm_sec
;
saved_seconds
=
yourtm
.
tm_sec
;
yourtm
.
tm_sec
=
SECSPERMIN
-
1
;
yourtm
.
tm_sec
=
SECSPERMIN
-
1
;
}
else
{
}
else
{
saved_seconds
=
yourtm
.
tm_sec
;
saved_seconds
=
yourtm
.
tm_sec
;
yourtm
.
tm_sec
=
0
;
yourtm
.
tm_sec
=
0
;
}
}
/*
/*
** Divide the search space in half
* * Divide the search space in half * (this works whether time_t is
** (this works whether time_t is signed or unsigned).
* signed or unsigned).
*/
*/
bits
=
TYPE_BIT
(
time_t
)
-
1
;
bits
=
TYPE_BIT
(
time_t
)
-
1
;
/*
/*
** If time_t is signed, then 0 is just above the median,
* * If time_t is signed, then 0 is just above the median, * assuming
** assuming two's complement arithmetic.
* two's complement arithmetic. * If time_t is unsigned, then (1 <<
** If time_t is unsigned, then (1 <<
bits) is just above the median.
*
bits) is just above the median.
*/
*/
t
=
TYPE_SIGNED
(
time_t
)
?
0
:
(((
time_t
)
1
)
<<
bits
);
t
=
TYPE_SIGNED
(
time_t
)
?
0
:
(((
time_t
)
1
)
<<
bits
);
for
(
;
;
)
{
for
(;;)
(
*
funcp
)(
&
t
,
offset
,
&
mytm
);
{
(
*
funcp
)
(
&
t
,
offset
,
&
mytm
);
dir
=
tmcomp
(
&
mytm
,
&
yourtm
);
dir
=
tmcomp
(
&
mytm
,
&
yourtm
);
if
(
dir
!=
0
)
{
if
(
dir
!=
0
)
{
if
(
bits
--
<
0
)
if
(
bits
--
<
0
)
return
WRONG
;
return
WRONG
;
if
(
bits
<
0
)
if
(
bits
<
0
)
--
t
;
/* may be needed if new t is minimal */
--
t
;
/* may be needed if new t is minimal */
else
if
(
dir
>
0
)
else
if
(
dir
>
0
)
t
-=
((
time_t
)
1
)
<<
bits
;
t
-=
((
time_t
)
1
)
<<
bits
;
else
t
+=
((
time_t
)
1
)
<<
bits
;
else
t
+=
((
time_t
)
1
)
<<
bits
;
continue
;
continue
;
}
}
if
(
yourtm
.
tm_isdst
<
0
||
mytm
.
tm_isdst
==
yourtm
.
tm_isdst
)
if
(
yourtm
.
tm_isdst
<
0
||
mytm
.
tm_isdst
==
yourtm
.
tm_isdst
)
break
;
break
;
/*
/*
** Right time, wrong type.
* * Right time, wrong type. * Hunt for right time, right type. *
** Hunt for right time, right type.
* It's okay to guess wrong since the guess * gets checked.
** It's okay to guess wrong since the guess
*/
** gets checked.
*/
/*
/*
*
* The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
*
* The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
*/
*/
sp
=
(
const
struct
state
*
)
sp
=
(
const
struct
state
*
)
(((
void
*
)
funcp
==
(
void
*
)
localsub
)
?
(((
void
*
)
funcp
==
(
void
*
)
localsub
)
?
lclptr
:
gmtptr
);
lclptr
:
gmtptr
);
for
(
i
=
sp
->
typecnt
-
1
;
i
>=
0
;
--
i
)
{
for
(
i
=
sp
->
typecnt
-
1
;
i
>=
0
;
--
i
)
{
if
(
sp
->
ttis
[
i
].
tt_isdst
!=
yourtm
.
tm_isdst
)
if
(
sp
->
ttis
[
i
].
tt_isdst
!=
yourtm
.
tm_isdst
)
continue
;
continue
;
for
(
j
=
sp
->
typecnt
-
1
;
j
>=
0
;
--
j
)
{
for
(
j
=
sp
->
typecnt
-
1
;
j
>=
0
;
--
j
)
{
if
(
sp
->
ttis
[
j
].
tt_isdst
==
yourtm
.
tm_isdst
)
if
(
sp
->
ttis
[
j
].
tt_isdst
==
yourtm
.
tm_isdst
)
continue
;
continue
;
newt
=
t
+
sp
->
ttis
[
j
].
tt_gmtoff
-
newt
=
t
+
sp
->
ttis
[
j
].
tt_gmtoff
-
sp
->
ttis
[
i
].
tt_gmtoff
;
sp
->
ttis
[
i
].
tt_gmtoff
;
(
*
funcp
)(
&
newt
,
offset
,
&
mytm
);
(
*
funcp
)
(
&
newt
,
offset
,
&
mytm
);
if
(
tmcomp
(
&
mytm
,
&
yourtm
)
!=
0
)
if
(
tmcomp
(
&
mytm
,
&
yourtm
)
!=
0
)
continue
;
continue
;
if
(
mytm
.
tm_isdst
!=
yourtm
.
tm_isdst
)
if
(
mytm
.
tm_isdst
!=
yourtm
.
tm_isdst
)
continue
;
continue
;
/*
/*
*
* We have a match.
*
* We have a match.
*/
*/
t
=
newt
;
t
=
newt
;
goto
label
;
goto
label
;
}
}
...
@@ -1140,83 +1266,91 @@ label:
...
@@ -1140,83 +1266,91 @@ label:
if
((
newt
<
t
)
!=
(
saved_seconds
<
0
))
if
((
newt
<
t
)
!=
(
saved_seconds
<
0
))
return
WRONG
;
return
WRONG
;
t
=
newt
;
t
=
newt
;
(
*
funcp
)(
&
t
,
offset
,
tmp
);
(
*
funcp
)
(
&
t
,
offset
,
tmp
);
*
okayp
=
TRUE
;
*
okayp
=
TRUE
;
return
t
;
return
t
;
}
}
static
time_t
time2
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)(
const
time_t
*
,
long
,
struct
pg_tm
*
),
const
long
offset
,
int
*
okayp
)
static
time_t
time2
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
const
long
offset
,
int
*
okayp
)
{
{
time_t
t
;
time_t
t
;
/*
/*
** First try without normalization of seconds
* * First try without normalization of seconds * (in case tm_sec
** (in case tm_sec contains a value associated with a leap second).
* contains a value associated with a leap second). * If that fails,
** If that fails,
try with normalization of seconds.
*
try with normalization of seconds.
*/
*/
t
=
time2sub
(
tmp
,
funcp
,
offset
,
okayp
,
FALSE
);
t
=
time2sub
(
tmp
,
funcp
,
offset
,
okayp
,
FALSE
);
return
*
okayp
?
t
:
time2sub
(
tmp
,
funcp
,
offset
,
okayp
,
TRUE
);
return
*
okayp
?
t
:
time2sub
(
tmp
,
funcp
,
offset
,
okayp
,
TRUE
);
}
}
static
time_t
time1
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
const
long
offset
)
static
time_t
time1
(
struct
pg_tm
*
tmp
,
void
(
*
funcp
)
(
const
time_t
*
,
long
,
struct
pg_tm
*
),
const
long
offset
)
{
{
register
time_t
t
;
register
time_t
t
;
register
const
struct
state
*
sp
;
register
const
struct
state
*
sp
;
register
int
samei
,
otheri
;
register
int
samei
,
register
int
sameind
,
otherind
;
otheri
;
register
int
i
;
register
int
sameind
,
register
int
nseen
;
otherind
;
int
seen
[
TZ_MAX_TYPES
];
register
int
i
;
int
types
[
TZ_MAX_TYPES
];
register
int
nseen
;
int
okay
;
int
seen
[
TZ_MAX_TYPES
];
int
types
[
TZ_MAX_TYPES
];
int
okay
;
if
(
tmp
->
tm_isdst
>
1
)
if
(
tmp
->
tm_isdst
>
1
)
tmp
->
tm_isdst
=
1
;
tmp
->
tm_isdst
=
1
;
t
=
time2
(
tmp
,
funcp
,
offset
,
&
okay
);
t
=
time2
(
tmp
,
funcp
,
offset
,
&
okay
);
if
(
okay
||
tmp
->
tm_isdst
<
0
)
if
(
okay
||
tmp
->
tm_isdst
<
0
)
return
t
;
return
t
;
/*
/*
** We're supposed to assume that somebody took a time of one type
* * We're supposed to assume that somebody took a time of one type *
** and did some math on it that yielded a "struct pg_tm" that's bad.
* and did some math on it that yielded a "struct pg_tm" that's bad. *
** We try to divine the type they started from and adjust to the
* We try to divine the type they started from and adjust to the *
** type they need.
* type they need.
*/
*/
/*
/*
*
* The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
*
* The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
*/
*/
sp
=
(
const
struct
state
*
)
(((
void
*
)
funcp
==
(
void
*
)
localsub
)
?
sp
=
(
const
struct
state
*
)
(((
void
*
)
funcp
==
(
void
*
)
localsub
)
?
lclptr
:
gmtptr
);
lclptr
:
gmtptr
);
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
for
(
i
=
0
;
i
<
sp
->
typecnt
;
++
i
)
seen
[
i
]
=
FALSE
;
seen
[
i
]
=
FALSE
;
nseen
=
0
;
nseen
=
0
;
for
(
i
=
sp
->
timecnt
-
1
;
i
>=
0
;
--
i
)
for
(
i
=
sp
->
timecnt
-
1
;
i
>=
0
;
--
i
)
if
(
!
seen
[
sp
->
types
[
i
]])
{
if
(
!
seen
[
sp
->
types
[
i
]])
{
seen
[
sp
->
types
[
i
]]
=
TRUE
;
seen
[
sp
->
types
[
i
]]
=
TRUE
;
types
[
nseen
++
]
=
sp
->
types
[
i
];
types
[
nseen
++
]
=
sp
->
types
[
i
];
}
}
for
(
sameind
=
0
;
sameind
<
nseen
;
++
sameind
)
{
for
(
sameind
=
0
;
sameind
<
nseen
;
++
sameind
)
{
samei
=
types
[
sameind
];
samei
=
types
[
sameind
];
if
(
sp
->
ttis
[
samei
].
tt_isdst
!=
tmp
->
tm_isdst
)
if
(
sp
->
ttis
[
samei
].
tt_isdst
!=
tmp
->
tm_isdst
)
continue
;
continue
;
for
(
otherind
=
0
;
otherind
<
nseen
;
++
otherind
)
{
for
(
otherind
=
0
;
otherind
<
nseen
;
++
otherind
)
{
otheri
=
types
[
otherind
];
otheri
=
types
[
otherind
];
if
(
sp
->
ttis
[
otheri
].
tt_isdst
==
tmp
->
tm_isdst
)
if
(
sp
->
ttis
[
otheri
].
tt_isdst
==
tmp
->
tm_isdst
)
continue
;
continue
;
tmp
->
tm_sec
+=
sp
->
ttis
[
otheri
].
tt_gmtoff
-
tmp
->
tm_sec
+=
sp
->
ttis
[
otheri
].
tt_gmtoff
-
sp
->
ttis
[
samei
].
tt_gmtoff
;
sp
->
ttis
[
samei
].
tt_gmtoff
;
tmp
->
tm_isdst
=
!
tmp
->
tm_isdst
;
tmp
->
tm_isdst
=
!
tmp
->
tm_isdst
;
t
=
time2
(
tmp
,
funcp
,
offset
,
&
okay
);
t
=
time2
(
tmp
,
funcp
,
offset
,
&
okay
);
if
(
okay
)
if
(
okay
)
return
t
;
return
t
;
tmp
->
tm_sec
-=
sp
->
ttis
[
otheri
].
tt_gmtoff
-
tmp
->
tm_sec
-=
sp
->
ttis
[
otheri
].
tt_gmtoff
-
sp
->
ttis
[
samei
].
tt_gmtoff
;
sp
->
ttis
[
samei
].
tt_gmtoff
;
tmp
->
tm_isdst
=
!
tmp
->
tm_isdst
;
tmp
->
tm_isdst
=
!
tmp
->
tm_isdst
;
}
}
}
}
return
WRONG
;
return
WRONG
;
}
}
time_t
pg_mktime
(
struct
pg_tm
*
tmp
)
time_t
pg_mktime
(
struct
pg_tm
*
tmp
)
{
{
return
time1
(
tmp
,
localsub
,
0L
);
return
time1
(
tmp
,
localsub
,
0L
);
}
}
...
@@ -1225,7 +1359,8 @@ time_t pg_mktime(struct pg_tm *tmp)
...
@@ -1225,7 +1359,8 @@ time_t pg_mktime(struct pg_tm *tmp)
* Return the name of the current timezone
* Return the name of the current timezone
*/
*/
const
char
*
const
char
*
pg_get_current_timezone
(
void
)
{
pg_get_current_timezone
(
void
)
{
if
(
lcl_is_set
)
if
(
lcl_is_set
)
return
lcl_TZname
;
return
lcl_TZname
;
return
NULL
;
return
NULL
;
...
...
src/timezone/pgtz.c
View file @
0a19fb42
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.1
0 2004/05/21 05:08:06 tgl
Exp $
* $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.1
1 2004/05/21 12:30:25 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -45,36 +45,46 @@ pg_TZDIR(void)
...
@@ -45,36 +45,46 @@ pg_TZDIR(void)
* set in our own library).
* set in our own library).
*/
*/
#define T_YEAR (60*60*24*365)
#define T_YEAR (60*60*24*365)
#define T_MONTH
(60*60*24*30)
#define T_MONTH
(60*60*24*30)
struct
tztry
{
struct
tztry
time_t
std_t
,
dst_t
;
{
char
std_time
[
TZ_STRLEN_MAX
+
1
],
dst_time
[
TZ_STRLEN_MAX
+
1
];
time_t
std_t
,
int
std_ofs
,
dst_ofs
;
dst_t
;
struct
tm
std_tm
,
dst_tm
;
char
std_time
[
TZ_STRLEN_MAX
+
1
],
dst_time
[
TZ_STRLEN_MAX
+
1
];
int
std_ofs
,
dst_ofs
;
struct
tm
std_tm
,
dst_tm
;
};
};
static
bool
compare_tm
(
struct
tm
*
s
,
struct
pg_tm
*
p
)
{
static
bool
if
(
s
->
tm_sec
!=
p
->
tm_sec
||
compare_tm
(
struct
tm
*
s
,
struct
pg_tm
*
p
)
s
->
tm_min
!=
p
->
tm_min
||
{
s
->
tm_hour
!=
p
->
tm_hour
||
if
(
s
->
tm_sec
!=
p
->
tm_sec
||
s
->
tm_mday
!=
p
->
tm_mday
||
s
->
tm_min
!=
p
->
tm_min
||
s
->
tm_mon
!=
p
->
tm_mon
||
s
->
tm_hour
!=
p
->
tm_hour
||
s
->
tm_year
!=
p
->
tm_year
||
s
->
tm_mday
!=
p
->
tm_mday
||
s
->
tm_wday
!=
p
->
tm_wday
||
s
->
tm_mon
!=
p
->
tm_mon
||
s
->
tm_yday
!=
p
->
tm_yday
||
s
->
tm_year
!=
p
->
tm_year
||
s
->
tm_wday
!=
p
->
tm_wday
||
s
->
tm_yday
!=
p
->
tm_yday
||
s
->
tm_isdst
!=
p
->
tm_isdst
)
s
->
tm_isdst
!=
p
->
tm_isdst
)
return
false
;
return
false
;
return
true
;
return
true
;
}
}
static
bool
try_timezone
(
char
*
tzname
,
struct
tztry
*
tt
,
bool
checkdst
)
{
static
bool
try_timezone
(
char
*
tzname
,
struct
tztry
*
tt
,
bool
checkdst
)
{
struct
pg_tm
*
pgtm
;
struct
pg_tm
*
pgtm
;
if
(
!
pg_tzset
(
tzname
))
if
(
!
pg_tzset
(
tzname
))
return
false
;
/* If this timezone couldn't be picked at all */
return
false
;
/* If this timezone couldn't be picked at
* all */
/* Verify standard time */
/* Verify standard time */
pgtm
=
pg_localtime
(
&
(
tt
->
std_t
));
pgtm
=
pg_localtime
(
&
(
tt
->
std_t
));
if
(
!
pgtm
)
if
(
!
pgtm
)
...
@@ -95,7 +105,9 @@ static bool try_timezone(char *tzname, struct tztry *tt, bool checkdst) {
...
@@ -95,7 +105,9 @@ static bool try_timezone(char *tzname, struct tztry *tt, bool checkdst) {
return
true
;
return
true
;
}
}
static
int
get_timezone_offset
(
struct
tm
*
tm
)
{
static
int
get_timezone_offset
(
struct
tm
*
tm
)
{
#if defined(HAVE_STRUCT_TM_TM_ZONE)
#if defined(HAVE_STRUCT_TM_TM_ZONE)
return
tm
->
tm_gmtoff
;
return
tm
->
tm_gmtoff
;
#elif defined(HAVE_INT_TIMEZONE)
#elif defined(HAVE_INT_TIMEZONE)
...
@@ -113,12 +125,15 @@ static int get_timezone_offset(struct tm *tm) {
...
@@ -113,12 +125,15 @@ static int get_timezone_offset(struct tm *tm) {
#ifdef WIN32
#ifdef WIN32
#define TZABBREV(tz) win32_get_timezone_abbrev(tz)
#define TZABBREV(tz) win32_get_timezone_abbrev(tz)
static
char
*
win32_get_timezone_abbrev
(
char
*
tz
)
{
static
char
*
static
char
w32tzabbr
[
TZ_STRLEN_MAX
+
1
];
win32_get_timezone_abbrev
(
char
*
tz
)
int
l
=
0
;
{
char
*
c
;
static
char
w32tzabbr
[
TZ_STRLEN_MAX
+
1
];
int
l
=
0
;
char
*
c
;
for
(
c
=
tz
;
*
c
;
c
++
)
{
for
(
c
=
tz
;
*
c
;
c
++
)
{
if
(
isupper
(
*
c
))
if
(
isupper
(
*
c
))
w32tzabbr
[
l
++
]
=
*
c
;
w32tzabbr
[
l
++
]
=
*
c
;
}
}
...
@@ -140,47 +155,50 @@ static char *win32_get_timezone_abbrev(char *tz) {
...
@@ -140,47 +155,50 @@ static char *win32_get_timezone_abbrev(char *tz) {
static
char
*
static
char
*
identify_system_timezone
(
void
)
identify_system_timezone
(
void
)
{
{
static
char
__tzbuf
[
TZ_STRLEN_MAX
+
1
];
static
char
__tzbuf
[
TZ_STRLEN_MAX
+
1
];
bool
std_found
=
false
,
bool
std_found
=
false
,
dst_found
=
false
;
dst_found
=
false
;
time_t
tnow
=
time
(
NULL
);
time_t
tnow
=
time
(
NULL
);
time_t
t
;
time_t
t
;
struct
tztry
tt
;
struct
tztry
tt
;
char
cbuf
[
TZ_STRLEN_MAX
+
1
];
char
cbuf
[
TZ_STRLEN_MAX
+
1
];
/* Initialize OS timezone library */
/* Initialize OS timezone library */
tzset
();
tzset
();
memset
(
&
tt
,
0
,
sizeof
(
tt
));
memset
(
&
tt
,
0
,
sizeof
(
tt
));
for
(
t
=
tnow
;
t
<
tnow
+
T_YEAR
;
t
+=
T_MONTH
)
{
struct
tm
*
tm
=
localtime
(
&
t
);
if
(
tm
->
tm_isdst
==
0
&&
!
std_found
)
{
for
(
t
=
tnow
;
t
<
tnow
+
T_YEAR
;
t
+=
T_MONTH
)
{
struct
tm
*
tm
=
localtime
(
&
t
);
if
(
tm
->
tm_isdst
==
0
&&
!
std_found
)
{
/* Standard time */
/* Standard time */
memcpy
(
&
tt
.
std_tm
,
tm
,
sizeof
(
struct
tm
));
memcpy
(
&
tt
.
std_tm
,
tm
,
sizeof
(
struct
tm
));
memset
(
cbuf
,
0
,
sizeof
(
cbuf
));
memset
(
cbuf
,
0
,
sizeof
(
cbuf
));
strftime
(
cbuf
,
sizeof
(
cbuf
)
-
1
,
"%Z"
,
tm
);
/* zone abbr */
strftime
(
cbuf
,
sizeof
(
cbuf
)
-
1
,
"%Z"
,
tm
);
/* zone abbr */
strcpy
(
tt
.
std_time
,
TZABBREV
(
cbuf
));
strcpy
(
tt
.
std_time
,
TZABBREV
(
cbuf
));
tt
.
std_ofs
=
get_timezone_offset
(
tm
);
tt
.
std_ofs
=
get_timezone_offset
(
tm
);
tt
.
std_t
=
t
;
tt
.
std_t
=
t
;
std_found
=
true
;
std_found
=
true
;
}
}
else
if
(
tm
->
tm_isdst
==
1
&&
!
dst_found
)
{
else
if
(
tm
->
tm_isdst
==
1
&&
!
dst_found
)
{
/* Daylight time */
/* Daylight time */
memcpy
(
&
tt
.
dst_tm
,
tm
,
sizeof
(
struct
tm
));
memcpy
(
&
tt
.
dst_tm
,
tm
,
sizeof
(
struct
tm
));
memset
(
cbuf
,
0
,
sizeof
(
cbuf
));
memset
(
cbuf
,
0
,
sizeof
(
cbuf
));
strftime
(
cbuf
,
sizeof
(
cbuf
)
-
1
,
"%Z"
,
tm
);
/* zone abbr */
strftime
(
cbuf
,
sizeof
(
cbuf
)
-
1
,
"%Z"
,
tm
);
/* zone abbr */
strcpy
(
tt
.
dst_time
,
TZABBREV
(
cbuf
));
strcpy
(
tt
.
dst_time
,
TZABBREV
(
cbuf
));
tt
.
dst_ofs
=
get_timezone_offset
(
tm
);
tt
.
dst_ofs
=
get_timezone_offset
(
tm
);
tt
.
dst_t
=
t
;
tt
.
dst_t
=
t
;
dst_found
=
true
;
dst_found
=
true
;
}
}
if
(
std_found
&&
dst_found
)
if
(
std_found
&&
dst_found
)
break
;
/* Got both standard and daylight */
break
;
/* Got both standard and daylight */
}
}
if
(
!
std_found
)
if
(
!
std_found
)
{
{
/* Failed to determine TZ! */
/* Failed to determine TZ! */
ereport
(
LOG
,
ereport
(
LOG
,
...
@@ -189,24 +207,25 @@ identify_system_timezone(void)
...
@@ -189,24 +207,25 @@ identify_system_timezone(void)
return
NULL
;
/* go to GMT */
return
NULL
;
/* go to GMT */
}
}
if
(
dst_found
)
{
if
(
dst_found
)
{
/* Try STD<ofs>DST */
/* Try STD<ofs>DST */
sprintf
(
__tzbuf
,
"%s%d%s"
,
tt
.
std_time
,
-
tt
.
std_ofs
/
3600
,
tt
.
dst_time
);
sprintf
(
__tzbuf
,
"%s%d%s"
,
tt
.
std_time
,
-
tt
.
std_ofs
/
3600
,
tt
.
dst_time
);
if
(
try_timezone
(
__tzbuf
,
&
tt
,
dst_found
))
if
(
try_timezone
(
__tzbuf
,
&
tt
,
dst_found
))
return
__tzbuf
;
return
__tzbuf
;
}
}
/* Try just the STD timezone */
/* Try just the STD timezone */
strcpy
(
__tzbuf
,
tt
.
std_time
);
strcpy
(
__tzbuf
,
tt
.
std_time
);
if
(
try_timezone
(
__tzbuf
,
&
tt
,
dst_found
))
if
(
try_timezone
(
__tzbuf
,
&
tt
,
dst_found
))
return
__tzbuf
;
return
__tzbuf
;
/* Did not find the timezone. Fallback to try a GMT zone. */
/* Did not find the timezone. Fallback to try a GMT zone. */
sprintf
(
__tzbuf
,
"Etc/GMT%s%d"
,
sprintf
(
__tzbuf
,
"Etc/GMT%s%d"
,
(
-
tt
.
std_ofs
<
0
)
?
"+"
:
""
,
tt
.
std_ofs
/
3600
);
(
-
tt
.
std_ofs
<
0
)
?
"+"
:
""
,
tt
.
std_ofs
/
3600
);
ereport
(
LOG
,
ereport
(
LOG
,
(
errmsg
(
"could not recognize system timezone, defaulting to
\"
%s
\"
"
,
(
errmsg
(
"could not recognize system timezone, defaulting to
\"
%s
\"
"
,
__tzbuf
),
__tzbuf
),
errhint
(
"You can specify the correct timezone in postgresql.conf."
)));
errhint
(
"You can specify the correct timezone in postgresql.conf."
)));
return
__tzbuf
;
return
__tzbuf
;
}
}
...
@@ -223,7 +242,7 @@ identify_system_timezone(void)
...
@@ -223,7 +242,7 @@ identify_system_timezone(void)
bool
bool
tz_acceptable
(
void
)
tz_acceptable
(
void
)
{
{
struct
pg_tm
tt
;
struct
pg_tm
tt
;
time_t
time2000
;
time_t
time2000
;
/*
/*
...
@@ -255,7 +274,7 @@ tz_acceptable(void)
...
@@ -255,7 +274,7 @@ tz_acceptable(void)
const
char
*
const
char
*
select_default_timezone
(
void
)
select_default_timezone
(
void
)
{
{
char
*
def_tz
;
char
*
def_tz
;
def_tz
=
getenv
(
"TZ"
);
def_tz
=
getenv
(
"TZ"
);
if
(
def_tz
&&
pg_tzset
(
def_tz
)
&&
tz_acceptable
())
if
(
def_tz
&&
pg_tzset
(
def_tz
)
&&
tz_acceptable
())
...
@@ -280,9 +299,12 @@ select_default_timezone(void)
...
@@ -280,9 +299,12 @@ select_default_timezone(void)
* This is called after initial loading of postgresql.conf. If no TimeZone
* This is called after initial loading of postgresql.conf. If no TimeZone
* setting was found therein, we try to derive one from the environment.
* setting was found therein, we try to derive one from the environment.
*/
*/
void
pg_timezone_initialize
(
void
)
{
void
pg_timezone_initialize
(
void
)
{
/* Do we need to try to figure the timezone? */
/* Do we need to try to figure the timezone? */
if
(
strcmp
(
GetConfigOption
(
"timezone"
),
"UNKNOWN"
)
==
0
)
{
if
(
strcmp
(
GetConfigOption
(
"timezone"
),
"UNKNOWN"
)
==
0
)
{
const
char
*
def_tz
;
const
char
*
def_tz
;
/* Select setting */
/* Select setting */
...
...
src/timezone/pgtz.h
View file @
0a19fb42
...
@@ -9,7 +9,7 @@
...
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
*
* IDENTIFICATION
* IDENTIFICATION
* $PostgreSQL: pgsql/src/timezone/pgtz.h,v 1.
7 2004/05/21 05:08:06 tgl
Exp $
* $PostgreSQL: pgsql/src/timezone/pgtz.h,v 1.
8 2004/05/21 12:30:25 momjian
Exp $
*
*
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
...
@@ -18,6 +18,6 @@
...
@@ -18,6 +18,6 @@
#define TZ_STRLEN_MAX 255
#define TZ_STRLEN_MAX 255
extern
char
*
pg_TZDIR
(
void
);
extern
char
*
pg_TZDIR
(
void
);
#endif
/* _PGTZ_H */
#endif
/* _PGTZ_H */
src/timezone/private.h
View file @
0a19fb42
...
@@ -14,19 +14,19 @@
...
@@ -14,19 +14,19 @@
** Thank you!
** Thank you!
*/
*/
#include <limits.h>
/* for CHAR_BIT */
#include <limits.h>
/* for CHAR_BIT */
#include <sys/wait.h>
/* for WIFEXITED and WEXITSTATUS */
#include <sys/wait.h>
/* for WIFEXITED and WEXITSTATUS */
#include <unistd.h>
/* for F_OK and R_OK */
#include <unistd.h>
/* for F_OK and R_OK */
#include "pgtime.h"
#include "pgtime.h"
#ifndef WIFEXITED
#ifndef WIFEXITED
#define WIFEXITED(status) (((status) & 0xff) == 0)
#define WIFEXITED(status) (((status) & 0xff) == 0)
#endif
/* !defined WIFEXITED */
#endif
/* !defined WIFEXITED */
#ifndef WEXITSTATUS
#ifndef WEXITSTATUS
#define WEXITSTATUS(status)
(((status) >> 8) & 0xff)
#define WEXITSTATUS(status)
(((status) >> 8) & 0xff)
#endif
/* !defined WEXITSTATUS */
#endif
/* !defined WEXITSTATUS */
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
...
@@ -37,7 +37,7 @@
...
@@ -37,7 +37,7 @@
#ifndef EXIT_SUCCESS
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#define EXIT_SUCCESS 0
#endif
/* !defined EXIT_SUCCESS */
#endif
/* !defined EXIT_SUCCESS */
/*
/*
** SunOS 4.1.1 headers lack EXIT_FAILURE.
** SunOS 4.1.1 headers lack EXIT_FAILURE.
...
@@ -45,28 +45,29 @@
...
@@ -45,28 +45,29 @@
#ifndef EXIT_FAILURE
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#define EXIT_FAILURE 1
#endif
/* !defined EXIT_FAILURE */
#endif
/* !defined EXIT_FAILURE */
/*
/*
** SunOS 4.1.1 libraries lack remove.
** SunOS 4.1.1 libraries lack remove.
*/
*/
#ifndef remove
#ifndef remove
extern
int
unlink
(
const
char
*
filename
);
extern
int
unlink
(
const
char
*
filename
);
#define remove unlink
#define remove unlink
#endif
/* !defined remove */
#endif
/* !defined remove */
/*
/*
* Private function declarations.
* Private function declarations.
*/
*/
extern
char
*
icalloc
(
int
nelem
,
int
elsize
);
extern
char
*
icalloc
(
int
nelem
,
int
elsize
);
extern
char
*
icatalloc
(
char
*
old
,
const
char
*
new
);
extern
char
*
icatalloc
(
char
*
old
,
const
char
*
new
);
extern
char
*
icpyalloc
(
const
char
*
string
);
extern
char
*
icpyalloc
(
const
char
*
string
);
extern
char
*
imalloc
(
int
n
);
extern
char
*
imalloc
(
int
n
);
extern
void
*
irealloc
(
void
*
pointer
,
int
size
);
extern
void
*
irealloc
(
void
*
pointer
,
int
size
);
extern
void
icfree
(
char
*
pointer
);
extern
void
icfree
(
char
*
pointer
);
extern
void
ifree
(
char
*
pointer
);
extern
void
ifree
(
char
*
pointer
);
extern
char
*
scheck
(
const
char
*
string
,
const
char
*
format
);
extern
char
*
scheck
(
const
char
*
string
,
const
char
*
format
);
/*
/*
...
@@ -75,19 +76,19 @@ extern char *scheck (const char *string, const char *format);
...
@@ -75,19 +76,19 @@ extern char *scheck (const char *string, const char *format);
#ifndef TRUE
#ifndef TRUE
#define TRUE 1
#define TRUE 1
#endif
/* !defined TRUE */
#endif
/* !defined TRUE */
#ifndef FALSE
#ifndef FALSE
#define FALSE 0
#define FALSE 0
#endif
/* !defined FALSE */
#endif
/* !defined FALSE */
#ifndef TYPE_BIT
#ifndef TYPE_BIT
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
#endif
/* !defined TYPE_BIT */
#endif
/* !defined TYPE_BIT */
#ifndef TYPE_SIGNED
#ifndef TYPE_SIGNED
#define TYPE_SIGNED(type) (((type) -1) < 0)
#define TYPE_SIGNED(type) (((type) -1) < 0)
#endif
/* !defined TYPE_SIGNED */
#endif
/* !defined TYPE_SIGNED */
#ifndef INT_STRLEN_MAXIMUM
#ifndef INT_STRLEN_MAXIMUM
/*
/*
...
@@ -97,8 +98,8 @@ extern char *scheck (const char *string, const char *format);
...
@@ -97,8 +98,8 @@ extern char *scheck (const char *string, const char *format);
** add one more for a minus sign if the type is signed.
** add one more for a minus sign if the type is signed.
*/
*/
#define INT_STRLEN_MAXIMUM(type) \
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
#endif
/* !defined INT_STRLEN_MAXIMUM */
#endif
/* !defined INT_STRLEN_MAXIMUM */
#define _(msgid) (msgid)
#define _(msgid) (msgid)
...
@@ -106,4 +107,4 @@ extern char *scheck (const char *string, const char *format);
...
@@ -106,4 +107,4 @@ extern char *scheck (const char *string, const char *format);
** UNIX was a registered trademark of The Open Group in 2003.
** UNIX was a registered trademark of The Open Group in 2003.
*/
*/
#endif
/* !defined PRIVATE_H */
#endif
/* !defined PRIVATE_H */
src/timezone/scheck.c
View file @
0a19fb42
...
@@ -3,15 +3,16 @@
...
@@ -3,15 +3,16 @@
#include "private.h"
#include "private.h"
char
*
scheck
(
const
char
*
string
,
const
char
*
format
)
char
*
scheck
(
const
char
*
string
,
const
char
*
format
)
{
{
register
char
*
fbuf
;
register
char
*
fbuf
;
register
const
char
*
fp
;
register
const
char
*
fp
;
register
char
*
tp
;
register
char
*
tp
;
register
int
c
;
register
int
c
;
register
char
*
result
;
register
char
*
result
;
char
dummy
;
char
dummy
;
static
char
nada
;
static
char
nada
;
result
=
&
nada
;
result
=
&
nada
;
if
(
string
==
NULL
||
format
==
NULL
)
if
(
string
==
NULL
||
format
==
NULL
)
...
@@ -21,10 +22,12 @@ char *scheck(const char *string, const char *format)
...
@@ -21,10 +22,12 @@ char *scheck(const char *string, const char *format)
return
result
;
return
result
;
fp
=
format
;
fp
=
format
;
tp
=
fbuf
;
tp
=
fbuf
;
while
((
*
tp
++
=
c
=
*
fp
++
)
!=
'\0'
)
{
while
((
*
tp
++
=
c
=
*
fp
++
)
!=
'\0'
)
{
if
(
c
!=
'%'
)
if
(
c
!=
'%'
)
continue
;
continue
;
if
(
*
fp
==
'%'
)
{
if
(
*
fp
==
'%'
)
{
*
tp
++
=
*
fp
++
;
*
tp
++
=
*
fp
++
;
continue
;
continue
;
}
}
...
@@ -36,8 +39,9 @@ char *scheck(const char *string, const char *format)
...
@@ -36,8 +39,9 @@ char *scheck(const char *string, const char *format)
if
(
*
fp
==
'l'
||
*
fp
==
'h'
)
if
(
*
fp
==
'l'
||
*
fp
==
'h'
)
*
tp
++
=
*
fp
++
;
*
tp
++
=
*
fp
++
;
else
if
(
*
fp
==
'['
)
else
if
(
*
fp
==
'['
)
do
*
tp
++
=
*
fp
++
;
do
while
(
*
fp
!=
'\0'
&&
*
fp
!=
']'
);
*
tp
++
=
*
fp
++
;
while
(
*
fp
!=
'\0'
&&
*
fp
!=
']'
);
if
((
*
tp
++
=
*
fp
++
)
==
'\0'
)
if
((
*
tp
++
=
*
fp
++
)
==
'\0'
)
break
;
break
;
}
}
...
...
src/timezone/strftime.c
View file @
0a19fb42
...
@@ -25,22 +25,23 @@
...
@@ -25,22 +25,23 @@
#include "tzfile.h"
#include "tzfile.h"
struct
lc_time_T
{
struct
lc_time_T
const
char
*
mon
[
MONSPERYEAR
];
{
const
char
*
month
[
MONSPERYEAR
];
const
char
*
mon
[
MONSPERYEAR
];
const
char
*
wday
[
DAYSPERWEEK
];
const
char
*
month
[
MONSPERYEAR
];
const
char
*
weekday
[
DAYSPERWEEK
];
const
char
*
wday
[
DAYSPERWEEK
];
const
char
*
X_fmt
;
const
char
*
weekday
[
DAYSPERWEEK
];
const
char
*
x_fmt
;
const
char
*
X_fmt
;
const
char
*
c_fmt
;
const
char
*
x_fmt
;
const
char
*
am
;
const
char
*
c_fmt
;
const
char
*
pm
;
const
char
*
am
;
const
char
*
date_fmt
;
const
char
*
pm
;
const
char
*
date_fmt
;
};
};
#define Locale (&C_time_locale)
#define Locale (&C_time_locale)
static
const
struct
lc_time_T
C_time_locale
=
{
static
const
struct
lc_time_T
C_time_locale
=
{
{
{
"Jan"
,
"Feb"
,
"Mar"
,
"Apr"
,
"May"
,
"Jun"
,
"Jan"
,
"Feb"
,
"Mar"
,
"Apr"
,
"May"
,
"Jun"
,
"Jul"
,
"Aug"
,
"Sep"
,
"Oct"
,
"Nov"
,
"Dec"
"Jul"
,
"Aug"
,
"Sep"
,
"Oct"
,
"Nov"
,
"Dec"
...
@@ -59,21 +60,16 @@ static const struct lc_time_T C_time_locale = {
...
@@ -59,21 +60,16 @@ static const struct lc_time_T C_time_locale = {
"%H:%M:%S"
,
"%H:%M:%S"
,
/*
/*
** x_fmt
* * x_fmt * C99 requires this format. * Using just numbers (as here)
** C99 requires this format.
* makes Quakers happier; * it's also compatible with SVR4.
** Using just numbers (as here) makes Quakers happier;
*/
** it's also compatible with SVR4.
*/
"%m/%d/%y"
,
"%m/%d/%y"
,
/*
/*
** c_fmt
* * c_fmt * C99 requires this format. * Previously this code used "%D
** C99 requires this format.
* %X", but we now conform to C99. * Note that * "%a %b %d
** Previously this code used "%D %X", but we now conform to C99.
* %H:%M:%S %Y" * is used by Solaris 2.3.
** Note that
*/
** "%a %b %d %H:%M:%S %Y"
** is used by Solaris 2.3.
*/
"%a %b %e %T %Y"
,
"%a %b %e %T %Y"
,
/* am */
/* am */
...
@@ -86,20 +82,21 @@ static const struct lc_time_T C_time_locale = {
...
@@ -86,20 +82,21 @@ static const struct lc_time_T C_time_locale = {
"%a %b %e %H:%M:%S %Z %Y"
"%a %b %e %H:%M:%S %Z %Y"
};
};
static
char
*
_add
(
const
char
*
,
char
*
,
const
char
*
);
static
char
*
_add
(
const
char
*
,
char
*
,
const
char
*
);
static
char
*
_conv
(
int
,
const
char
*
,
char
*
,
const
char
*
);
static
char
*
_conv
(
int
,
const
char
*
,
char
*
,
const
char
*
);
static
char
*
_fmt
(
const
char
*
,
const
struct
pg_tm
*
,
char
*
,
const
char
*
,
int
*
);
static
char
*
_fmt
(
const
char
*
,
const
struct
pg_tm
*
,
char
*
,
const
char
*
,
int
*
);
#define IN_NONE
0
#define IN_NONE
0
#define IN_SOME
1
#define IN_SOME
1
#define IN_THIS
2
#define IN_THIS
2
#define IN_ALL 3
#define IN_ALL 3
size_t
pg_strftime
(
char
*
s
,
size_t
maxsize
,
const
char
*
format
,
const
struct
pg_tm
*
t
)
size_t
pg_strftime
(
char
*
s
,
size_t
maxsize
,
const
char
*
format
,
const
struct
pg_tm
*
t
)
{
{
char
*
p
;
char
*
p
;
int
warn
;
int
warn
;
warn
=
IN_NONE
;
warn
=
IN_NONE
;
p
=
_fmt
(((
format
==
NULL
)
?
"%c"
:
format
),
t
,
s
,
s
+
maxsize
,
&
warn
);
p
=
_fmt
(((
format
==
NULL
)
?
"%c"
:
format
),
t
,
s
,
s
+
maxsize
,
&
warn
);
...
@@ -109,196 +106,196 @@ size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_
...
@@ -109,196 +106,196 @@ size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_
return
p
-
s
;
return
p
-
s
;
}
}
static
char
*
_fmt
(
const
char
*
format
,
const
struct
pg_tm
*
t
,
char
*
pt
,
const
char
*
ptlim
,
int
*
warnp
)
static
char
*
_fmt
(
const
char
*
format
,
const
struct
pg_tm
*
t
,
char
*
pt
,
const
char
*
ptlim
,
int
*
warnp
)
{
{
for
(
;
*
format
;
++
format
)
{
for
(;
*
format
;
++
format
)
if
(
*
format
==
'%'
)
{
{
label:
if
(
*
format
==
'%'
)
switch
(
*++
format
)
{
{
case
'\0'
:
label:
--
format
;
switch
(
*++
format
)
break
;
{
case
'A'
:
case
'\0'
:
pt
=
_add
((
t
->
tm_wday
<
0
||
--
format
;
t
->
tm_wday
>=
DAYSPERWEEK
)
?
break
;
"?"
:
Locale
->
weekday
[
t
->
tm_wday
],
case
'A'
:
pt
,
ptlim
);
pt
=
_add
((
t
->
tm_wday
<
0
||
continue
;
t
->
tm_wday
>=
DAYSPERWEEK
)
?
case
'a'
:
"?"
:
Locale
->
weekday
[
t
->
tm_wday
],
pt
=
_add
((
t
->
tm_wday
<
0
||
pt
,
ptlim
);
t
->
tm_wday
>=
DAYSPERWEEK
)
?
continue
;
"?"
:
Locale
->
wday
[
t
->
tm_wday
],
case
'a'
:
pt
,
ptlim
);
pt
=
_add
((
t
->
tm_wday
<
0
||
continue
;
t
->
tm_wday
>=
DAYSPERWEEK
)
?
case
'B'
:
"?"
:
Locale
->
wday
[
t
->
tm_wday
],
pt
=
_add
((
t
->
tm_mon
<
0
||
pt
,
ptlim
);
t
->
tm_mon
>=
MONSPERYEAR
)
?
continue
;
"?"
:
Locale
->
month
[
t
->
tm_mon
],
case
'B'
:
pt
,
ptlim
);
pt
=
_add
((
t
->
tm_mon
<
0
||
continue
;
t
->
tm_mon
>=
MONSPERYEAR
)
?
case
'b'
:
"?"
:
Locale
->
month
[
t
->
tm_mon
],
case
'h'
:
pt
,
ptlim
);
pt
=
_add
((
t
->
tm_mon
<
0
||
continue
;
t
->
tm_mon
>=
MONSPERYEAR
)
?
case
'b'
:
"?"
:
Locale
->
mon
[
t
->
tm_mon
],
case
'h'
:
pt
,
ptlim
);
pt
=
_add
((
t
->
tm_mon
<
0
||
continue
;
t
->
tm_mon
>=
MONSPERYEAR
)
?
case
'C'
:
"?"
:
Locale
->
mon
[
t
->
tm_mon
],
/*
pt
,
ptlim
);
** %C used to do a...
continue
;
** _fmt("%a %b %e %X %Y", t);
case
'C'
:
** ...whereas now POSIX 1003.2 calls for
** something completely different.
/*
** (ado, 1993-05-24)
* * %C used to do a... * _fmt("%a %b %e %X %Y", t); *
*/
* ...whereas now POSIX 1003.2 calls for * something
pt
=
_conv
((
t
->
tm_year
+
TM_YEAR_BASE
)
/
100
,
* completely different. * (ado, 1993-05-24)
"%02d"
,
pt
,
ptlim
);
*/
continue
;
pt
=
_conv
((
t
->
tm_year
+
TM_YEAR_BASE
)
/
100
,
case
'c'
:
"%02d"
,
pt
,
ptlim
);
{
continue
;
int
warn2
=
IN_SOME
;
case
'c'
:
{
pt
=
_fmt
(
Locale
->
c_fmt
,
t
,
pt
,
ptlim
,
warnp
);
int
warn2
=
IN_SOME
;
if
(
warn2
==
IN_ALL
)
warn2
=
IN_THIS
;
pt
=
_fmt
(
Locale
->
c_fmt
,
t
,
pt
,
ptlim
,
warnp
);
if
(
warn2
>
*
warnp
)
if
(
warn2
==
IN_ALL
)
*
warnp
=
warn2
;
warn2
=
IN_THIS
;
}
if
(
warn2
>
*
warnp
)
continue
;
*
warnp
=
warn2
;
case
'D'
:
}
pt
=
_fmt
(
"%m/%d/%y"
,
t
,
pt
,
ptlim
,
warnp
);
continue
;
continue
;
case
'D'
:
case
'd'
:
pt
=
_fmt
(
"%m/%d/%y"
,
t
,
pt
,
ptlim
,
warnp
);
pt
=
_conv
(
t
->
tm_mday
,
"%02d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'd'
:
case
'E'
:
pt
=
_conv
(
t
->
tm_mday
,
"%02d"
,
pt
,
ptlim
);
case
'O'
:
continue
;
/*
case
'E'
:
** C99 locale modifiers.
case
'O'
:
** The sequences
** %Ec %EC %Ex %EX %Ey %EY
/*
** %Od %oe %OH %OI %Om %OM
* * C99 locale modifiers. * The sequences * %Ec %EC
** %OS %Ou %OU %OV %Ow %OW %Oy
* %Ex %EX %Ey %EY * %Od %oe %OH %OI %Om %OM * %OS
** are supposed to provide alternate
* %Ou %OU %OV %Ow %OW %Oy * are supposed to provide
** representations.
* alternate * representations.
*/
*/
goto
label
;
goto
label
;
case
'e'
:
case
'e'
:
pt
=
_conv
(
t
->
tm_mday
,
"%2d"
,
pt
,
ptlim
);
pt
=
_conv
(
t
->
tm_mday
,
"%2d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'F'
:
case
'F'
:
pt
=
_fmt
(
"%Y-%m-%d"
,
t
,
pt
,
ptlim
,
warnp
);
pt
=
_fmt
(
"%Y-%m-%d"
,
t
,
pt
,
ptlim
,
warnp
);
continue
;
continue
;
case
'H'
:
case
'H'
:
pt
=
_conv
(
t
->
tm_hour
,
"%02d"
,
pt
,
ptlim
);
pt
=
_conv
(
t
->
tm_hour
,
"%02d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'I'
:
case
'I'
:
pt
=
_conv
((
t
->
tm_hour
%
12
)
?
pt
=
_conv
((
t
->
tm_hour
%
12
)
?
(
t
->
tm_hour
%
12
)
:
12
,
(
t
->
tm_hour
%
12
)
:
12
,
"%02d"
,
pt
,
ptlim
);
"%02d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'j'
:
case
'j'
:
pt
=
_conv
(
t
->
tm_yday
+
1
,
"%03d"
,
pt
,
ptlim
);
pt
=
_conv
(
t
->
tm_yday
+
1
,
"%03d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'k'
:
case
'k'
:
/*
** This used to be...
/*
** _conv(t->tm_hour % 12 ?
* * This used to be... * _conv(t->tm_hour % 12 ? *
** t->tm_hour % 12 : 12, 2, ' ');
* t->tm_hour % 12 : 12, 2, ' '); * ...and has been
** ...and has been changed to the below to
* changed to the below to * match SunOS 4.1.1 and
** match SunOS 4.1.1 and Arnold Robbins'
* Arnold Robbins' * strftime version 3.0. That is,
** strftime version 3.0. That is, "%k" and
* "%k" and * "%l" have been swapped. * (ado,
** "%l" have been swapped.
* 1993-05-24)
** (ado, 1993-05-24)
*/
*/
pt
=
_conv
(
t
->
tm_hour
,
"%2d"
,
pt
,
ptlim
);
pt
=
_conv
(
t
->
tm_hour
,
"%2d"
,
pt
,
ptlim
);
continue
;
continue
;
#ifdef KITCHEN_SINK
#ifdef KITCHEN_SINK
case
'K'
:
case
'K'
:
/*
** After all this time, still unclaimed!
/*
*/
* * After all this time, still unclaimed!
pt
=
_add
(
"kitchen sink"
,
pt
,
ptlim
);
*/
continue
;
pt
=
_add
(
"kitchen sink"
,
pt
,
ptlim
)
;
#endif
/* defined KITCHEN_SINK */
continue
;
case
'l'
:
#endif
/* defined KITCHEN_SINK */
/*
case
'l'
:
** This used to be...
** _conv(t->tm_hour, 2, ' ');
/*
** ...and has been changed to the below to
* * This used to be... * _conv(t->tm_hour, 2, ' '); *
** match SunOS 4.1.1 and Arnold Robbin's
* ...and has been changed to the below to * match
** strftime version 3.0. That is, "%k" and
* SunOS 4.1.1 and Arnold Robbin's * strftime version
** "%l" have been swapped.
* 3.0. That is, "%k" and * "%l" have been swapped. *
*
* (ado, 1993-05-24)
* (ado, 1993-05-24)
*/
*/
pt
=
_conv
((
t
->
tm_hour
%
12
)
?
pt
=
_conv
((
t
->
tm_hour
%
12
)
?
(
t
->
tm_hour
%
12
)
:
12
,
(
t
->
tm_hour
%
12
)
:
12
,
"%2d"
,
pt
,
ptlim
);
"%2d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'M'
:
case
'M'
:
pt
=
_conv
(
t
->
tm_min
,
"%02d"
,
pt
,
ptlim
);
pt
=
_conv
(
t
->
tm_min
,
"%02d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'm'
:
case
'm'
:
pt
=
_conv
(
t
->
tm_mon
+
1
,
"%02d"
,
pt
,
ptlim
);
pt
=
_conv
(
t
->
tm_mon
+
1
,
"%02d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'n'
:
case
'n'
:
pt
=
_add
(
"
\n
"
,
pt
,
ptlim
);
pt
=
_add
(
"
\n
"
,
pt
,
ptlim
);
continue
;
continue
;
case
'p'
:
case
'p'
:
pt
=
_add
((
t
->
tm_hour
>=
(
HOURSPERDAY
/
2
))
?
pt
=
_add
((
t
->
tm_hour
>=
(
HOURSPERDAY
/
2
))
?
Locale
->
pm
:
Locale
->
pm
:
Locale
->
am
,
Locale
->
am
,
pt
,
ptlim
);
pt
,
ptlim
);
continue
;
continue
;
case
'R'
:
case
'R'
:
pt
=
_fmt
(
"%H:%M"
,
t
,
pt
,
ptlim
,
warnp
);
pt
=
_fmt
(
"%H:%M"
,
t
,
pt
,
ptlim
,
warnp
);
continue
;
continue
;
case
'r'
:
case
'r'
:
pt
=
_fmt
(
"%I:%M:%S %p"
,
t
,
pt
,
ptlim
,
warnp
);
pt
=
_fmt
(
"%I:%M:%S %p"
,
t
,
pt
,
ptlim
,
warnp
);
continue
;
continue
;
case
'S'
:
case
'S'
:
pt
=
_conv
(
t
->
tm_sec
,
"%02d"
,
pt
,
ptlim
);
pt
=
_conv
(
t
->
tm_sec
,
"%02d"
,
pt
,
ptlim
);
continue
;
continue
;
case
's'
:
case
's'
:
{
{
struct
pg_tm
tm
;
struct
pg_tm
tm
;
char
buf
[
INT_STRLEN_MAXIMUM
(
time_t
)
+
1
];
char
buf
[
INT_STRLEN_MAXIMUM
(
time_t
)
+
1
];
time_t
mkt
;
time_t
mkt
;
tm
=
*
t
;
tm
=
*
t
;
mkt
=
pg_mktime
(
&
tm
);
mkt
=
pg_mktime
(
&
tm
);
if
(
TYPE_SIGNED
(
time_t
))
if
(
TYPE_SIGNED
(
time_t
))
(
void
)
sprintf
(
buf
,
"%ld"
,
(
long
)
mkt
);
(
void
)
sprintf
(
buf
,
"%ld"
,
(
long
)
mkt
);
else
else
(
void
)
sprintf
(
buf
,
"%lu"
,
(
unsigned
long
)
mkt
);
(
void
)
sprintf
(
buf
,
"%lu"
,
(
unsigned
long
)
mkt
);
pt
=
_add
(
buf
,
pt
,
ptlim
);
pt
=
_add
(
buf
,
pt
,
ptlim
);
}
}
continue
;
continue
;
case
'T'
:
case
'T'
:
pt
=
_fmt
(
"%H:%M:%S"
,
t
,
pt
,
ptlim
,
warnp
);
pt
=
_fmt
(
"%H:%M:%S"
,
t
,
pt
,
ptlim
,
warnp
);
continue
;
continue
;
case
't'
:
case
't'
:
pt
=
_add
(
"
\t
"
,
pt
,
ptlim
);
pt
=
_add
(
"
\t
"
,
pt
,
ptlim
);
continue
;
continue
;
case
'U'
:
case
'U'
:
pt
=
_conv
((
t
->
tm_yday
+
DAYSPERWEEK
-
pt
=
_conv
((
t
->
tm_yday
+
DAYSPERWEEK
-
t
->
tm_wday
)
/
DAYSPERWEEK
,
t
->
tm_wday
)
/
DAYSPERWEEK
,
"%02d"
,
pt
,
ptlim
);
"%02d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'u'
:
case
'u'
:
/*
** From Arnold Robbins' strftime version 3.0:
/*
** "ISO 8601: Weekday as a decimal number
* * From Arnold Robbins' strftime version 3.0: * "ISO
** [1 (Monday) - 7]"
* 8601: Weekday as a decimal number * [1 (Monday) -
*
* (ado, 1993-05-24)
* 7]"
* (ado, 1993-05-24)
*/
*/
pt
=
_conv
((
t
->
tm_wday
==
0
)
?
pt
=
_conv
((
t
->
tm_wday
==
0
)
?
DAYSPERWEEK
:
t
->
tm_wday
,
DAYSPERWEEK
:
t
->
tm_wday
,
"%d"
,
pt
,
ptlim
);
"%d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'V'
:
/* ISO 8601 week number */
case
'V'
:
/* ISO 8601 week number */
case
'G'
:
/* ISO 8601 year (four digits) */
case
'G'
:
/* ISO 8601 year (four digits) */
case
'g'
:
/* ISO 8601 year (two digits) */
case
'g'
:
/* ISO 8601 year (two digits) */
/*
/*
** From Arnold Robbins' strftime version 3.0: "the week number of the
** From Arnold Robbins' strftime version 3.0: "the week number of the
** year (the first Monday as the first day of week 1) as a decimal number
** year (the first Monday as the first day of week 1) as a decimal number
...
@@ -317,144 +314,156 @@ label:
...
@@ -317,144 +314,156 @@ label:
** 1997 lasts from 1996-12-30 to 1997-01-05..."
** 1997 lasts from 1996-12-30 to 1997-01-05..."
** (ado, 1996-01-02)
** (ado, 1996-01-02)
*/
*/
{
{
int
year
;
int
year
;
int
yday
;
int
yday
;
int
wday
;
int
wday
;
int
w
;
int
w
;
year
=
t
->
tm_year
+
TM_YEAR_BASE
;
year
=
t
->
tm_year
+
TM_YEAR_BASE
;
yday
=
t
->
tm_yday
;
yday
=
t
->
tm_yday
;
wday
=
t
->
tm_wday
;
wday
=
t
->
tm_wday
;
for
(
;
;
)
{
for
(;;)
int
len
;
{
int
bot
;
int
len
;
int
top
;
int
bot
;
int
top
;
len
=
isleap
(
year
)
?
DAYSPERLYEAR
:
len
=
isleap
(
year
)
?
DAYSPERNYEAR
;
DAYSPERLYEAR
:
/*
DAYSPERNYEAR
;
** What yday (-3 ... 3) does
** the ISO year begin on?
/*
*/
* * What yday (-3 ... 3) does * the ISO year
bot
=
((
yday
+
11
-
wday
)
%
* begin on?
DAYSPERWEEK
)
-
3
;
*/
/*
bot
=
((
yday
+
11
-
wday
)
%
** What yday does the NEXT
DAYSPERWEEK
)
-
3
;
** ISO year begin on?
*/
/*
top
=
bot
-
* * What yday does the NEXT * ISO year begin
(
len
%
DAYSPERWEEK
);
* on?
if
(
top
<
-
3
)
*/
top
+=
DAYSPERWEEK
;
top
=
bot
-
top
+=
len
;
(
len
%
DAYSPERWEEK
);
if
(
yday
>=
top
)
{
if
(
top
<
-
3
)
++
year
;
top
+=
DAYSPERWEEK
;
w
=
1
;
top
+=
len
;
break
;
if
(
yday
>=
top
)
{
++
year
;
w
=
1
;
break
;
}
if
(
yday
>=
bot
)
{
w
=
1
+
((
yday
-
bot
)
/
DAYSPERWEEK
);
break
;
}
--
year
;
yday
+=
isleap
(
year
)
?
DAYSPERLYEAR
:
DAYSPERNYEAR
;
}
}
if
(
yday
>=
bot
)
{
if
(
*
format
==
'V'
)
w
=
1
+
((
yday
-
bot
)
/
pt
=
_conv
(
w
,
"%02d"
,
DAYSPERWEEK
);
pt
,
ptlim
);
break
;
else
if
(
*
format
==
'g'
)
{
*
warnp
=
IN_ALL
;
pt
=
_conv
(
year
%
100
,
"%02d"
,
pt
,
ptlim
);
}
}
--
year
;
else
yday
+=
isleap
(
year
)
?
pt
=
_conv
(
year
,
"%04d"
,
DAYSPERLYEAR
:
pt
,
ptlim
);
DAYSPERNYEAR
;
}
}
if
(
*
format
==
'V'
)
continue
;
pt
=
_conv
(
w
,
"%02d"
,
case
'v'
:
pt
,
ptlim
);
else
if
(
*
format
==
'g'
)
{
/*
*
warnp
=
IN_ALL
;
* * From Arnold Robbins' strftime version 3.0: *
pt
=
_conv
(
year
%
100
,
"%02d"
,
* "date as dd-bbb-YYYY" * (ado, 1993-05-24)
pt
,
ptlim
);
*/
}
else
pt
=
_conv
(
year
,
"%04d"
,
pt
=
_fmt
(
"%e-%b-%Y"
,
t
,
pt
,
ptlim
,
warnp
);
pt
,
ptlim
);
continue
;
}
case
'W'
:
continue
;
pt
=
_conv
((
t
->
tm_yday
+
DAYSPERWEEK
-
case
'v'
:
(
t
->
tm_wday
?
/*
(
t
->
tm_wday
-
1
)
:
** From Arnold Robbins' strftime version 3.0:
(
DAYSPERWEEK
-
1
)))
/
DAYSPERWEEK
,
** "date as dd-bbb-YYYY"
"%02d"
,
pt
,
ptlim
);
** (ado, 1993-05-24)
continue
;
*/
case
'w'
:
pt
=
_fmt
(
"%e-%b-%Y"
,
t
,
pt
,
ptlim
,
warnp
);
pt
=
_conv
(
t
->
tm_wday
,
"%d"
,
pt
,
ptlim
);
continue
;
continue
;
case
'W'
:
case
'X'
:
pt
=
_conv
((
t
->
tm_yday
+
DAYSPERWEEK
-
pt
=
_fmt
(
Locale
->
X_fmt
,
t
,
pt
,
ptlim
,
warnp
);
(
t
->
tm_wday
?
continue
;
(
t
->
tm_wday
-
1
)
:
case
'x'
:
(
DAYSPERWEEK
-
1
)))
/
DAYSPERWEEK
,
{
"%02d"
,
pt
,
ptlim
);
int
warn2
=
IN_SOME
;
continue
;
case
'w'
:
pt
=
_fmt
(
Locale
->
x_fmt
,
t
,
pt
,
ptlim
,
&
warn2
);
pt
=
_conv
(
t
->
tm_wday
,
"%d"
,
pt
,
ptlim
);
if
(
warn2
==
IN_ALL
)
continue
;
warn2
=
IN_THIS
;
case
'X'
:
if
(
warn2
>
*
warnp
)
pt
=
_fmt
(
Locale
->
X_fmt
,
t
,
pt
,
ptlim
,
warnp
);
*
warnp
=
warn2
;
continue
;
}
case
'x'
:
continue
;
{
case
'y'
:
int
warn2
=
IN_SOME
;
*
warnp
=
IN_ALL
;
pt
=
_conv
((
t
->
tm_year
+
TM_YEAR_BASE
)
%
100
,
pt
=
_fmt
(
Locale
->
x_fmt
,
t
,
pt
,
ptlim
,
&
warn2
);
"%02d"
,
pt
,
ptlim
);
if
(
warn2
==
IN_ALL
)
continue
;
warn2
=
IN_THIS
;
case
'Y'
:
if
(
warn2
>
*
warnp
)
pt
=
_conv
(
t
->
tm_year
+
TM_YEAR_BASE
,
"%04d"
,
*
warnp
=
warn2
;
pt
,
ptlim
);
}
continue
;
continue
;
case
'Z'
:
case
'y'
:
if
(
t
->
tm_zone
!=
NULL
)
*
warnp
=
IN_ALL
;
pt
=
_add
(
t
->
tm_zone
,
pt
,
ptlim
);
pt
=
_conv
((
t
->
tm_year
+
TM_YEAR_BASE
)
%
100
,
"%02d"
,
pt
,
ptlim
);
/*
continue
;
* * C99 says that %Z must be replaced by the * empty
case
'Y'
:
* string if the time zone is not * determinable.
pt
=
_conv
(
t
->
tm_year
+
TM_YEAR_BASE
,
"%04d"
,
*/
pt
,
ptlim
);
continue
;
continue
;
case
'z'
:
case
'Z'
:
{
if
(
t
->
tm_zone
!=
NULL
)
int
diff
;
pt
=
_add
(
t
->
tm_zone
,
pt
,
ptlim
);
char
const
*
sign
;
/*
** C99 says that %Z must be replaced by the
if
(
t
->
tm_isdst
<
0
)
** empty string if the time zone is not
continue
;
** determinable.
diff
=
t
->
tm_gmtoff
;
*/
if
(
diff
<
0
)
continue
;
{
case
'z'
:
sign
=
"-"
;
{
diff
=
-
diff
;
int
diff
;
}
char
const
*
sign
;
else
sign
=
"+"
;
if
(
t
->
tm_isdst
<
0
)
pt
=
_add
(
sign
,
pt
,
ptlim
);
continue
;
diff
/=
60
;
diff
=
t
->
tm_gmtoff
;
pt
=
_conv
((
diff
/
60
)
*
100
+
diff
%
60
,
if
(
diff
<
0
)
{
"%04d"
,
pt
,
ptlim
);
sign
=
"-"
;
}
diff
=
-
diff
;
continue
;
}
else
sign
=
"+"
;
case
'+'
:
pt
=
_add
(
sign
,
pt
,
ptlim
);
pt
=
_fmt
(
Locale
->
date_fmt
,
t
,
pt
,
ptlim
,
diff
/=
60
;
warnp
);
pt
=
_conv
((
diff
/
60
)
*
100
+
diff
%
60
,
continue
;
"%04d"
,
pt
,
ptlim
);
case
'%'
:
}
continue
;
/*
case
'+'
:
* * X311J/88-090 (4.12.3.5): if conversion char is *
pt
=
_fmt
(
Locale
->
date_fmt
,
t
,
pt
,
ptlim
,
* undefined, behavior is undefined. Print out the *
warnp
);
* character itself as printf(3) also does.
continue
;
*/
case
'%'
:
default:
/*
break
;
** X311J/88-090 (4.12.3.5): if conversion char is
** undefined, behavior is undefined. Print out the
** character itself as printf(3) also does.
*/
default:
break
;
}
}
}
}
if
(
pt
==
ptlim
)
if
(
pt
==
ptlim
)
...
@@ -464,15 +473,17 @@ label:
...
@@ -464,15 +473,17 @@ label:
return
pt
;
return
pt
;
}
}
static
char
*
_conv
(
const
int
n
,
const
char
*
format
,
char
*
pt
,
const
char
*
ptlim
)
static
char
*
_conv
(
const
int
n
,
const
char
*
format
,
char
*
pt
,
const
char
*
ptlim
)
{
{
char
buf
[
INT_STRLEN_MAXIMUM
(
int
)
+
1
];
char
buf
[
INT_STRLEN_MAXIMUM
(
int
)
+
1
];
(
void
)
sprintf
(
buf
,
format
,
n
);
(
void
)
sprintf
(
buf
,
format
,
n
);
return
_add
(
buf
,
pt
,
ptlim
);
return
_add
(
buf
,
pt
,
ptlim
);
}
}
static
char
*
_add
(
const
char
*
str
,
char
*
pt
,
const
char
*
ptlim
)
static
char
*
_add
(
const
char
*
str
,
char
*
pt
,
const
char
*
ptlim
)
{
{
while
(
pt
<
ptlim
&&
(
*
pt
=
*
str
++
)
!=
'\0'
)
while
(
pt
<
ptlim
&&
(
*
pt
=
*
str
++
)
!=
'\0'
)
++
pt
;
++
pt
;
...
...
src/timezone/tzfile.h
View file @
0a19fb42
...
@@ -26,17 +26,20 @@
...
@@ -26,17 +26,20 @@
** Each file begins with. . .
** Each file begins with. . .
*/
*/
#define TZ_MAGIC "TZif"
#define TZ_MAGIC "TZif"
struct
tzhead
{
struct
tzhead
char
tzh_magic
[
4
];
/* TZ_MAGIC */
{
char
tzh_reserved
[
16
];
/* reserved for future use */
char
tzh_magic
[
4
];
/* TZ_MAGIC */
char
tzh_ttisgmtcnt
[
4
];
/* coded number of trans. time flags */
char
tzh_reserved
[
16
];
/* reserved for future use */
char
tzh_ttisstdcnt
[
4
];
/* coded number of trans. time flags */
char
tzh_ttisgmtcnt
[
4
];
/* coded number of trans. time
char
tzh_leapcnt
[
4
];
/* coded number of leap seconds */
* flags */
char
tzh_timecnt
[
4
];
/* coded number of transition times */
char
tzh_ttisstdcnt
[
4
];
/* coded number of trans. time
char
tzh_typecnt
[
4
];
/* coded number of local time types */
* flags */
char
tzh_charcnt
[
4
];
/* coded number of abbr. chars */
char
tzh_leapcnt
[
4
];
/* coded number of leap seconds */
char
tzh_timecnt
[
4
];
/* coded number of transition times */
char
tzh_typecnt
[
4
];
/* coded number of local time types */
char
tzh_charcnt
[
4
];
/* coded number of abbr. chars */
};
};
/*
/*
...
@@ -46,8 +49,8 @@ struct tzhead {
...
@@ -46,8 +49,8 @@ struct tzhead {
** tzh_timecnt (unsigned char)s types of local time starting at above
** tzh_timecnt (unsigned char)s types of local time starting at above
** tzh_typecnt repetitions of
** tzh_typecnt repetitions of
** one (char [4]) coded UTC offset in seconds
** one (char [4]) coded UTC offset in seconds
** one (unsigned char)
used to set tm_isdst
** one (unsigned char)
used to set tm_isdst
** one (unsigned char)
that's an abbreviation list index
** one (unsigned char)
that's an abbreviation list index
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
** tzh_leapcnt repetitions of
** tzh_leapcnt repetitions of
** one (char [4]) coded leap second transition times
** one (char [4]) coded leap second transition times
...
@@ -77,33 +80,36 @@ struct tzhead {
...
@@ -77,33 +80,36 @@ struct tzhead {
*/
*/
#define TZ_MAX_TIMES 370
#define TZ_MAX_TIMES 370
#define TZ_MAX_TYPES 256
/* Limited by what (unsigned char)'s can hold */
#define TZ_MAX_TYPES 256
/* Limited by what (unsigned char)'s can
* hold */
#define TZ_MAX_CHARS 50
/* Maximum number of abbreviation characters */
#define TZ_MAX_CHARS 50
/* Maximum number of abbreviation
/* (limited by what unsigned chars can hold) */
* characters */
/* (limited by what unsigned chars can hold) */
#define TZ_MAX_LEAPS 50
/* Maximum number of leap second corrections */
#define TZ_MAX_LEAPS 50
/* Maximum number of leap second
* corrections */
#define SECSPERMIN 60
#define SECSPERMIN 60
#define MINSPERHOUR
60
#define MINSPERHOUR
60
#define HOURSPERDAY
24
#define HOURSPERDAY
24
#define DAYSPERWEEK
7
#define DAYSPERWEEK
7
#define DAYSPERNYEAR 365
#define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366
#define DAYSPERLYEAR 366
#define SECSPERHOUR
(SECSPERMIN * MINSPERHOUR)
#define SECSPERHOUR
(SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
#define MONSPERYEAR
12
#define MONSPERYEAR
12
#define TM_SUNDAY 0
#define TM_SUNDAY 0
#define TM_MONDAY 1
#define TM_MONDAY 1
#define TM_TUESDAY 2
#define TM_TUESDAY 2
#define TM_WEDNESDAY 3
#define TM_WEDNESDAY 3
#define TM_THURSDAY
4
#define TM_THURSDAY
4
#define TM_FRIDAY 5
#define TM_FRIDAY 5
#define TM_SATURDAY
6
#define TM_SATURDAY
6
#define TM_JANUARY 0
#define TM_JANUARY 0
#define TM_FEBRUARY
1
#define TM_FEBRUARY
1
#define TM_MARCH 2
#define TM_MARCH 2
#define TM_APRIL 3
#define TM_APRIL 3
#define TM_MAY 4
#define TM_MAY 4
...
@@ -112,8 +118,8 @@ struct tzhead {
...
@@ -112,8 +118,8 @@ struct tzhead {
#define TM_AUGUST 7
#define TM_AUGUST 7
#define TM_SEPTEMBER 8
#define TM_SEPTEMBER 8
#define TM_OCTOBER 9
#define TM_OCTOBER 9
#define TM_NOVEMBER
10
#define TM_NOVEMBER
10
#define TM_DECEMBER
11
#define TM_DECEMBER
11
#define TM_YEAR_BASE 1900
#define TM_YEAR_BASE 1900
...
@@ -127,4 +133,4 @@ struct tzhead {
...
@@ -127,4 +133,4 @@ struct tzhead {
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
#endif
/* !defined TZFILE_H */
#endif
/* !defined TZFILE_H */
src/timezone/zic.c
View file @
0a19fb42
...
@@ -23,11 +23,11 @@
...
@@ -23,11 +23,11 @@
#endif
#endif
#endif
#endif
static
char
elsieid
[]
=
"@(#)zic.c 7.115"
;
static
char
elsieid
[]
=
"@(#)zic.c 7.115"
;
/*
/*
** On some ancient hosts, predicates like `isspace(C)' are defined
** On some ancient hosts, predicates like `isspace(C)' are defined
** only if isascii(C) || C == EOF.
Modern hosts obey the C Standard,
** only if isascii(C) || C == EOF.
Modern hosts obey the C Standard,
** which says they are defined only if C == ((unsigned char) C) || C == EOF.
** which says they are defined only if C == ((unsigned char) C) || C == EOF.
** Neither the C Standard nor Posix require that `isascii' exist.
** Neither the C Standard nor Posix require that `isascii' exist.
** For portability, we check both ancient and modern requirements.
** For portability, we check both ancient and modern requirements.
...
@@ -38,128 +38,130 @@ static char elsieid[] = "@(#)zic.c 7.115";
...
@@ -38,128 +38,130 @@ static char elsieid[] = "@(#)zic.c 7.115";
#define isascii(x) 1
#define isascii(x) 1
#endif
#endif
struct
rule
{
struct
rule
const
char
*
r_filename
;
{
int
r_linenum
;
const
char
*
r_filename
;
const
char
*
r_name
;
int
r_linenum
;
const
char
*
r_name
;
int
r_loyear
;
/* for example, 1986 */
int
r_hiyear
;
/* for example, 1986 */
int
r_loyear
;
/* for example, 1986 */
const
char
*
r_yrtype
;
int
r_hiyear
;
/* for example, 1986 */
const
char
*
r_yrtype
;
int
r_month
;
/* 0..11 */
int
r_month
;
/* 0..11 */
int
r_dycode
;
/* see below */
int
r_dayofmonth
;
int
r_dycode
;
/* see below */
int
r_wday
;
int
r_dayofmonth
;
int
r_wday
;
long
r_tod
;
/* time from midnight */
int
r_todisstd
;
/* above is standard time if TRUE */
long
r_tod
;
/* time from midnight */
/* or wall clock time if FALSE */
int
r_todisstd
;
/* above is standard time if TRUE */
int
r_todisgmt
;
/* above is GMT if TRUE */
/* or wall clock time if FALSE */
/* or local time if FALSE */
int
r_todisgmt
;
/* above is GMT if TRUE */
long
r_stdoff
;
/* offset from standard time */
/* or local time if FALSE */
const
char
*
r_abbrvar
;
/* variable part of abbreviation */
long
r_stdoff
;
/* offset from standard time */
const
char
*
r_abbrvar
;
/* variable part of abbreviation */
int
r_todo
;
/* a rule to do (used in outzone) */
time_t
r_temp
;
/* used in outzone */
int
r_todo
;
/* a rule to do (used in outzone) */
time_t
r_temp
;
/* used in outzone */
};
};
/*
/*
** r_dycode r_dayofmonth r_wday
** r_dycode r_dayofmonth r_wday
*/
*/
#define DC_DOM 0
/* 1..31 */
/* unused */
#define DC_DOM 0
/* 1..31 */
/* unused */
#define DC_DOWGEQ 1
/* 1..31 */
/* 0..6 (Sun..Sat) */
#define DC_DOWGEQ 1
/* 1..31 */
/* 0..6 (Sun..Sat) */
#define DC_DOWLEQ 2
/* 1..31 */
/* 0..6 (Sun..Sat) */
#define DC_DOWLEQ 2
/* 1..31 */
/* 0..6 (Sun..Sat) */
struct
zone
{
struct
zone
const
char
*
z_filename
;
{
int
z_linenum
;
const
char
*
z_filename
;
int
z_linenum
;
const
char
*
z_name
;
const
char
*
z_name
;
long
z_gmtoff
;
long
z_gmtoff
;
const
char
*
z_rule
;
const
char
*
z_rule
;
const
char
*
z_format
;
const
char
*
z_format
;
long
z_stdoff
;
long
z_stdoff
;
struct
rule
*
z_rules
;
struct
rule
*
z_rules
;
int
z_nrules
;
int
z_nrules
;
struct
rule
z_untilrule
;
struct
rule
z_untilrule
;
time_t
z_untiltime
;
time_t
z_untiltime
;
};
};
extern
int
link
(
const
char
*
fromname
,
const
char
*
toname
);
extern
int
link
(
const
char
*
fromname
,
const
char
*
toname
);
static
void
addtt
(
time_t
starttime
,
int
type
);
static
void
addtt
(
time_t
starttime
,
int
type
);
static
int
addtype
(
long
gmtoff
,
const
char
*
abbr
,
int
isdst
,
static
int
addtype
(
long
gmtoff
,
const
char
*
abbr
,
int
isdst
,
int
ttisstd
,
int
ttisgmt
);
int
ttisstd
,
int
ttisgmt
);
static
void
leapadd
(
time_t
t
,
int
positive
,
int
rolling
,
int
count
);
static
void
leapadd
(
time_t
t
,
int
positive
,
int
rolling
,
int
count
);
static
void
adjleap
(
void
);
static
void
adjleap
(
void
);
static
void
associate
(
void
);
static
void
associate
(
void
);
static
int
ciequal
(
const
char
*
ap
,
const
char
*
bp
);
static
int
ciequal
(
const
char
*
ap
,
const
char
*
bp
);
static
void
convert
(
long
val
,
char
*
buf
);
static
void
convert
(
long
val
,
char
*
buf
);
static
void
dolink
(
const
char
*
fromfile
,
const
char
*
tofile
);
static
void
dolink
(
const
char
*
fromfile
,
const
char
*
tofile
);
static
void
doabbr
(
char
*
abbr
,
const
char
*
format
,
static
void
doabbr
(
char
*
abbr
,
const
char
*
format
,
const
char
*
letters
,
int
isdst
);
const
char
*
letters
,
int
isdst
);
static
void
eat
(
const
char
*
name
,
int
num
);
static
void
eat
(
const
char
*
name
,
int
num
);
static
void
eats
(
const
char
*
name
,
int
num
,
static
void
eats
(
const
char
*
name
,
int
num
,
const
char
*
rname
,
int
rnum
);
const
char
*
rname
,
int
rnum
);
static
long
eitol
(
int
i
);
static
long
eitol
(
int
i
);
static
void
error
(
const
char
*
message
);
static
void
error
(
const
char
*
message
);
static
char
**
getfields
(
char
*
buf
);
static
char
**
getfields
(
char
*
buf
);
static
long
gethms
(
const
char
*
string
,
const
char
*
errstrng
,
static
long
gethms
(
const
char
*
string
,
const
char
*
errstrng
,
int
signable
);
int
signable
);
static
void
infile
(
const
char
*
filename
);
static
void
infile
(
const
char
*
filename
);
static
void
inleap
(
char
**
fields
,
int
nfields
);
static
void
inleap
(
char
**
fields
,
int
nfields
);
static
void
inlink
(
char
**
fields
,
int
nfields
);
static
void
inlink
(
char
**
fields
,
int
nfields
);
static
void
inrule
(
char
**
fields
,
int
nfields
);
static
void
inrule
(
char
**
fields
,
int
nfields
);
static
int
inzcont
(
char
**
fields
,
int
nfields
);
static
int
inzcont
(
char
**
fields
,
int
nfields
);
static
int
inzone
(
char
**
fields
,
int
nfields
);
static
int
inzone
(
char
**
fields
,
int
nfields
);
static
int
inzsub
(
char
**
fields
,
int
nfields
,
int
iscont
);
static
int
inzsub
(
char
**
fields
,
int
nfields
,
int
iscont
);
static
int
itsabbr
(
const
char
*
abbr
,
const
char
*
word
);
static
int
itsabbr
(
const
char
*
abbr
,
const
char
*
word
);
static
int
itsdir
(
const
char
*
name
);
static
int
itsdir
(
const
char
*
name
);
static
int
lowerit
(
int
c
);
static
int
lowerit
(
int
c
);
static
char
*
memcheck
(
char
*
tocheck
);
static
char
*
memcheck
(
char
*
tocheck
);
static
int
mkdirs
(
char
*
filename
);
static
int
mkdirs
(
char
*
filename
);
static
void
newabbr
(
const
char
*
abbr
);
static
void
newabbr
(
const
char
*
abbr
);
static
long
oadd
(
long
t1
,
long
t2
);
static
long
oadd
(
long
t1
,
long
t2
);
static
void
outzone
(
const
struct
zone
*
zp
,
int
ntzones
);
static
void
outzone
(
const
struct
zone
*
zp
,
int
ntzones
);
static
void
puttzcode
(
long
code
,
FILE
*
fp
);
static
void
puttzcode
(
long
code
,
FILE
*
fp
);
static
int
rcomp
(
const
void
*
leftp
,
const
void
*
rightp
);
static
int
rcomp
(
const
void
*
leftp
,
const
void
*
rightp
);
static
time_t
rpytime
(
const
struct
rule
*
rp
,
int
wantedy
);
static
time_t
rpytime
(
const
struct
rule
*
rp
,
int
wantedy
);
static
void
rulesub
(
struct
rule
*
rp
,
static
void
rulesub
(
struct
rule
*
rp
,
const
char
*
loyearp
,
const
char
*
hiyearp
,
const
char
*
loyearp
,
const
char
*
hiyearp
,
const
char
*
typep
,
const
char
*
monthp
,
const
char
*
typep
,
const
char
*
monthp
,
const
char
*
dayp
,
const
char
*
timep
);
const
char
*
dayp
,
const
char
*
timep
);
static
void
setboundaries
(
void
);
static
void
setboundaries
(
void
);
static
time_t
tadd
(
time_t
t1
,
long
t2
);
static
time_t
tadd
(
time_t
t1
,
long
t2
);
static
void
usage
(
void
);
static
void
usage
(
void
);
static
void
writezone
(
const
char
*
name
);
static
void
writezone
(
const
char
*
name
);
static
int
yearistype
(
int
year
,
const
char
*
type
);
static
int
yearistype
(
int
year
,
const
char
*
type
);
#ifndef HAVE_STRERROR
#ifndef HAVE_STRERROR
static
char
*
strerror
(
int
);
static
char
*
strerror
(
int
);
#endif
#endif
static
int
charcnt
;
static
int
charcnt
;
static
int
errors
;
static
int
errors
;
static
const
char
*
filename
;
static
const
char
*
filename
;
static
int
leapcnt
;
static
int
leapcnt
;
static
int
linenum
;
static
int
linenum
;
static
time_t
max_time
;
static
time_t
max_time
;
static
int
max_year
;
static
int
max_year
;
static
int
max_year_representable
;
static
int
max_year_representable
;
static
time_t
min_time
;
static
time_t
min_time
;
static
int
min_year
;
static
int
min_year
;
static
int
min_year_representable
;
static
int
min_year_representable
;
static
int
noise
;
static
int
noise
;
static
const
char
*
rfilename
;
static
const
char
*
rfilename
;
static
int
rlinenum
;
static
int
rlinenum
;
static
const
char
*
progname
;
static
const
char
*
progname
;
static
int
timecnt
;
static
int
timecnt
;
static
int
typecnt
;
static
int
typecnt
;
/*
/*
** Line codes.
** Line codes.
...
@@ -179,7 +181,7 @@ static int typecnt;
...
@@ -179,7 +181,7 @@ static int typecnt;
#define ZF_RULE 3
#define ZF_RULE 3
#define ZF_FORMAT 4
#define ZF_FORMAT 4
#define ZF_TILYEAR 5
#define ZF_TILYEAR 5
#define ZF_TILMONTH
6
#define ZF_TILMONTH
6
#define ZF_TILDAY 7
#define ZF_TILDAY 7
#define ZF_TILTIME 8
#define ZF_TILTIME 8
#define ZONE_MINFIELDS 5
#define ZONE_MINFIELDS 5
...
@@ -192,12 +194,12 @@ static int typecnt;
...
@@ -192,12 +194,12 @@ static int typecnt;
#define ZFC_GMTOFF 0
#define ZFC_GMTOFF 0
#define ZFC_RULE 1
#define ZFC_RULE 1
#define ZFC_FORMAT 2
#define ZFC_FORMAT 2
#define ZFC_TILYEAR
3
#define ZFC_TILYEAR
3
#define ZFC_TILMONTH 4
#define ZFC_TILMONTH 4
#define ZFC_TILDAY 5
#define ZFC_TILDAY 5
#define ZFC_TILTIME
6
#define ZFC_TILTIME
6
#define ZONEC_MINFIELDS
3
#define ZONEC_MINFIELDS
3
#define ZONEC_MAXFIELDS
7
#define ZONEC_MAXFIELDS
7
/*
/*
** Which files are which on a Rule line.
** Which files are which on a Rule line.
...
@@ -212,7 +214,7 @@ static int typecnt;
...
@@ -212,7 +214,7 @@ static int typecnt;
#define RF_TOD 7
#define RF_TOD 7
#define RF_STDOFF 8
#define RF_STDOFF 8
#define RF_ABBRVAR 9
#define RF_ABBRVAR 9
#define RULE_FIELDS
10
#define RULE_FIELDS
10
/*
/*
** Which fields are which on a Link line.
** Which fields are which on a Link line.
...
@@ -220,7 +222,7 @@ static int typecnt;
...
@@ -220,7 +222,7 @@ static int typecnt;
#define LF_FROM 1
#define LF_FROM 1
#define LF_TO 2
#define LF_TO 2
#define LINK_FIELDS
3
#define LINK_FIELDS
3
/*
/*
** Which fields are which on a Leap line.
** Which fields are which on a Leap line.
...
@@ -232,7 +234,7 @@ static int typecnt;
...
@@ -232,7 +234,7 @@ static int typecnt;
#define LP_TIME 4
#define LP_TIME 4
#define LP_CORR 5
#define LP_CORR 5
#define LP_ROLL 6
#define LP_ROLL 6
#define LEAP_FIELDS
7
#define LEAP_FIELDS
7
/*
/*
** Year synonyms.
** Year synonyms.
...
@@ -242,117 +244,120 @@ static int typecnt;
...
@@ -242,117 +244,120 @@ static int typecnt;
#define YR_MAXIMUM 1
#define YR_MAXIMUM 1
#define YR_ONLY 2
#define YR_ONLY 2
static
struct
rule
*
rules
;
static
struct
rule
*
rules
;
static
int
nrules
;
/* number of rules */
static
int
nrules
;
/* number of rules */
static
struct
zone
*
zones
;
static
struct
zone
*
zones
;
static
int
nzones
;
/* number of zones */
static
int
nzones
;
/* number of zones */
struct
link
{
struct
link
const
char
*
l_filename
;
{
int
l_linenum
;
const
char
*
l_filename
;
const
char
*
l_from
;
int
l_linenum
;
const
char
*
l_to
;
const
char
*
l_from
;
const
char
*
l_to
;
};
};
static
struct
link
*
links
;
static
struct
link
*
links
;
static
int
nlinks
;
static
int
nlinks
;
struct
lookup
{
struct
lookup
const
char
*
l_word
;
{
const
char
*
l_word
;
const
int
l_value
;
const
int
l_value
;
};
};
static
struct
lookup
const
*
byword
(
const
char
*
string
,
static
struct
lookup
const
*
byword
(
const
char
*
string
,
const
struct
lookup
*
lp
);
const
struct
lookup
*
lp
);
static
struct
lookup
const
line_codes
[]
=
{
static
struct
lookup
const
line_codes
[]
=
{
{
"Rule"
,
LC_RULE
},
{
"Rule"
,
LC_RULE
},
{
"Zone"
,
LC_ZONE
},
{
"Zone"
,
LC_ZONE
},
{
"Link"
,
LC_LINK
},
{
"Link"
,
LC_LINK
},
{
"Leap"
,
LC_LEAP
},
{
"Leap"
,
LC_LEAP
},
{
NULL
,
0
}
{
NULL
,
0
}
};
};
static
struct
lookup
const
mon_names
[]
=
{
static
struct
lookup
const
mon_names
[]
=
{
{
"January"
,
TM_JANUARY
},
{
"January"
,
TM_JANUARY
},
{
"February"
,
TM_FEBRUARY
},
{
"February"
,
TM_FEBRUARY
},
{
"March"
,
TM_MARCH
},
{
"March"
,
TM_MARCH
},
{
"April"
,
TM_APRIL
},
{
"April"
,
TM_APRIL
},
{
"May"
,
TM_MAY
},
{
"May"
,
TM_MAY
},
{
"June"
,
TM_JUNE
},
{
"June"
,
TM_JUNE
},
{
"July"
,
TM_JULY
},
{
"July"
,
TM_JULY
},
{
"August"
,
TM_AUGUST
},
{
"August"
,
TM_AUGUST
},
{
"September"
,
TM_SEPTEMBER
},
{
"September"
,
TM_SEPTEMBER
},
{
"October"
,
TM_OCTOBER
},
{
"October"
,
TM_OCTOBER
},
{
"November"
,
TM_NOVEMBER
},
{
"November"
,
TM_NOVEMBER
},
{
"December"
,
TM_DECEMBER
},
{
"December"
,
TM_DECEMBER
},
{
NULL
,
0
}
{
NULL
,
0
}
};
};
static
struct
lookup
const
wday_names
[]
=
{
static
struct
lookup
const
wday_names
[]
=
{
{
"Sunday"
,
TM_SUNDAY
},
{
"Sunday"
,
TM_SUNDAY
},
{
"Monday"
,
TM_MONDAY
},
{
"Monday"
,
TM_MONDAY
},
{
"Tuesday"
,
TM_TUESDAY
},
{
"Tuesday"
,
TM_TUESDAY
},
{
"Wednesday"
,
TM_WEDNESDAY
},
{
"Wednesday"
,
TM_WEDNESDAY
},
{
"Thursday"
,
TM_THURSDAY
},
{
"Thursday"
,
TM_THURSDAY
},
{
"Friday"
,
TM_FRIDAY
},
{
"Friday"
,
TM_FRIDAY
},
{
"Saturday"
,
TM_SATURDAY
},
{
"Saturday"
,
TM_SATURDAY
},
{
NULL
,
0
}
{
NULL
,
0
}
};
};
static
struct
lookup
const
lasts
[]
=
{
static
struct
lookup
const
lasts
[]
=
{
{
"last-Sunday"
,
TM_SUNDAY
},
{
"last-Sunday"
,
TM_SUNDAY
},
{
"last-Monday"
,
TM_MONDAY
},
{
"last-Monday"
,
TM_MONDAY
},
{
"last-Tuesday"
,
TM_TUESDAY
},
{
"last-Tuesday"
,
TM_TUESDAY
},
{
"last-Wednesday"
,
TM_WEDNESDAY
},
{
"last-Wednesday"
,
TM_WEDNESDAY
},
{
"last-Thursday"
,
TM_THURSDAY
},
{
"last-Thursday"
,
TM_THURSDAY
},
{
"last-Friday"
,
TM_FRIDAY
},
{
"last-Friday"
,
TM_FRIDAY
},
{
"last-Saturday"
,
TM_SATURDAY
},
{
"last-Saturday"
,
TM_SATURDAY
},
{
NULL
,
0
}
{
NULL
,
0
}
};
};
static
struct
lookup
const
begin_years
[]
=
{
static
struct
lookup
const
begin_years
[]
=
{
{
"minimum"
,
YR_MINIMUM
},
{
"minimum"
,
YR_MINIMUM
},
{
"maximum"
,
YR_MAXIMUM
},
{
"maximum"
,
YR_MAXIMUM
},
{
NULL
,
0
}
{
NULL
,
0
}
};
};
static
struct
lookup
const
end_years
[]
=
{
static
struct
lookup
const
end_years
[]
=
{
{
"minimum"
,
YR_MINIMUM
},
{
"minimum"
,
YR_MINIMUM
},
{
"maximum"
,
YR_MAXIMUM
},
{
"maximum"
,
YR_MAXIMUM
},
{
"only"
,
YR_ONLY
},
{
"only"
,
YR_ONLY
},
{
NULL
,
0
}
{
NULL
,
0
}
};
};
static
struct
lookup
const
leap_types
[]
=
{
static
struct
lookup
const
leap_types
[]
=
{
{
"Rolling"
,
TRUE
},
{
"Rolling"
,
TRUE
},
{
"Stationary"
,
FALSE
},
{
"Stationary"
,
FALSE
},
{
NULL
,
0
}
{
NULL
,
0
}
};
};
static
const
int
len_months
[
2
][
MONSPERYEAR
]
=
{
static
const
int
len_months
[
2
][
MONSPERYEAR
]
=
{
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
},
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
},
{
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
{
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
};
};
static
const
int
len_years
[
2
]
=
{
static
const
int
len_years
[
2
]
=
{
DAYSPERNYEAR
,
DAYSPERLYEAR
DAYSPERNYEAR
,
DAYSPERLYEAR
};
};
static
struct
attype
{
static
struct
attype
{
time_t
at
;
time_t
at
;
unsigned
char
type
;
unsigned
char
type
;
}
attypes
[
TZ_MAX_TIMES
];
}
attypes
[
TZ_MAX_TIMES
];
static
long
gmtoffs
[
TZ_MAX_TYPES
];
static
long
gmtoffs
[
TZ_MAX_TYPES
];
static
char
isdsts
[
TZ_MAX_TYPES
];
static
char
isdsts
[
TZ_MAX_TYPES
];
static
unsigned
char
abbrinds
[
TZ_MAX_TYPES
];
static
unsigned
char
abbrinds
[
TZ_MAX_TYPES
];
static
char
ttisstds
[
TZ_MAX_TYPES
];
static
char
ttisstds
[
TZ_MAX_TYPES
];
static
char
ttisgmts
[
TZ_MAX_TYPES
];
static
char
ttisgmts
[
TZ_MAX_TYPES
];
static
char
chars
[
TZ_MAX_CHARS
];
static
char
chars
[
TZ_MAX_CHARS
];
static
time_t
trans
[
TZ_MAX_LEAPS
];
static
time_t
trans
[
TZ_MAX_LEAPS
];
static
long
corr
[
TZ_MAX_LEAPS
];
static
long
corr
[
TZ_MAX_LEAPS
];
static
char
roll
[
TZ_MAX_LEAPS
];
static
char
roll
[
TZ_MAX_LEAPS
];
/*
/*
** Memory allocation.
** Memory allocation.
...
@@ -360,20 +365,21 @@ static char roll[TZ_MAX_LEAPS];
...
@@ -360,20 +365,21 @@ static char roll[TZ_MAX_LEAPS];
static
char
*
static
char
*
memcheck
(
ptr
)
memcheck
(
ptr
)
char
*
const
ptr
;
char
*
const
ptr
;
{
{
if
(
ptr
==
NULL
)
{
if
(
ptr
==
NULL
)
{
const
char
*
e
=
strerror
(
errno
);
const
char
*
e
=
strerror
(
errno
);
(
void
)
fprintf
(
stderr
,
_
(
"%s: Memory exhausted: %s
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: Memory exhausted: %s
\n
"
),
progname
,
e
);
progname
,
e
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
return
ptr
;
return
ptr
;
}
}
#define emalloc(size) memcheck(imalloc(size))
#define emalloc(size) memcheck(imalloc(size))
#define erealloc(ptr, size)
memcheck(irealloc((ptr), (size)))
#define erealloc(ptr, size)
memcheck(irealloc((ptr), (size)))
#define ecpyalloc(ptr) memcheck(icpyalloc(ptr))
#define ecpyalloc(ptr) memcheck(icpyalloc(ptr))
#define ecatalloc(oldp, newp) memcheck(icatalloc((oldp), (newp)))
#define ecatalloc(oldp, newp) memcheck(icatalloc((oldp), (newp)))
...
@@ -382,9 +388,10 @@ char * const ptr;
...
@@ -382,9 +388,10 @@ char * const ptr;
*/
*/
#ifndef HAVE_STRERROR
#ifndef HAVE_STRERROR
static
char
*
strerror
(
int
errnum
)
static
char
*
strerror
(
int
errnum
)
{
{
extern
char
*
sys_errlist
[];
extern
char
*
sys_errlist
[];
extern
int
sys_nerr
;
extern
int
sys_nerr
;
return
(
errnum
>
0
&&
errnum
<=
sys_nerr
)
?
return
(
errnum
>
0
&&
errnum
<=
sys_nerr
)
?
...
@@ -392,7 +399,8 @@ static char *strerror(int errnum)
...
@@ -392,7 +399,8 @@ static char *strerror(int errnum)
}
}
#endif
#endif
static
void
eats
(
const
char
*
name
,
const
int
num
,
const
char
*
rname
,
const
int
rnum
)
static
void
eats
(
const
char
*
name
,
const
int
num
,
const
char
*
rname
,
const
int
rnum
)
{
{
filename
=
name
;
filename
=
name
;
linenum
=
num
;
linenum
=
num
;
...
@@ -400,30 +408,32 @@ static void eats(const char *name, const int num, const char *rname, const int r
...
@@ -400,30 +408,32 @@ static void eats(const char *name, const int num, const char *rname, const int r
rlinenum
=
rnum
;
rlinenum
=
rnum
;
}
}
static
void
eat
(
const
char
*
name
,
const
int
num
)
static
void
eat
(
const
char
*
name
,
const
int
num
)
{
{
eats
(
name
,
num
,
(
char
*
)
NULL
,
-
1
);
eats
(
name
,
num
,
(
char
*
)
NULL
,
-
1
);
}
}
static
void
error
(
const
char
*
string
)
static
void
error
(
const
char
*
string
)
{
{
/*
/*
** Match the format of "cc" to allow sh users to
* * Match the format of "cc" to allow sh users to * zic ... 2>&1 |
** zic ... 2>&1 | error -t "*" -v
* error -t "*" -v * on BSD systems.
** on BSD systems.
*/
*/
(
void
)
fprintf
(
stderr
,
_
(
"
\"
%s
\"
, line %d: %s"
),
(
void
)
fprintf
(
stderr
,
_
(
"
\"
%s
\"
, line %d: %s"
),
filename
,
linenum
,
string
);
filename
,
linenum
,
string
);
if
(
rfilename
!=
NULL
)
if
(
rfilename
!=
NULL
)
(
void
)
fprintf
(
stderr
,
_
(
" (rule from
\"
%s
\"
, line %d)"
),
(
void
)
fprintf
(
stderr
,
_
(
" (rule from
\"
%s
\"
, line %d)"
),
rfilename
,
rlinenum
);
rfilename
,
rlinenum
);
(
void
)
fprintf
(
stderr
,
"
\n
"
);
(
void
)
fprintf
(
stderr
,
"
\n
"
);
++
errors
;
++
errors
;
}
}
static
void
warning
(
const
char
*
string
)
static
void
warning
(
const
char
*
string
)
{
{
char
*
cp
;
char
*
cp
;
cp
=
ecpyalloc
(
_
(
"warning: "
));
cp
=
ecpyalloc
(
_
(
"warning: "
));
cp
=
ecatalloc
(
cp
,
string
);
cp
=
ecatalloc
(
cp
,
string
);
...
@@ -432,86 +442,95 @@ static void warning(const char *string)
...
@@ -432,86 +442,95 @@ static void warning(const char *string)
--
errors
;
--
errors
;
}
}
static
void
usage
(
void
)
static
void
usage
(
void
)
{
{
(
void
)
fprintf
(
stderr
,
_
(
"%s: usage is %s [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ]
\\\n\t
[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: usage is %s [ --version ] [ -s ] [ -v ] [ -l localtime ] [ -p posixrules ]
\\\n\t
[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]
\n
"
),
progname
,
progname
);
progname
,
progname
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
static
const
char
*
psxrules
;
static
const
char
*
psxrules
;
static
const
char
*
lcltime
;
static
const
char
*
lcltime
;
static
const
char
*
directory
;
static
const
char
*
directory
;
static
const
char
*
leapsec
;
static
const
char
*
leapsec
;
static
const
char
*
yitcommand
;
static
const
char
*
yitcommand
;
static
int
sflag
=
FALSE
;
static
int
sflag
=
FALSE
;
int
main
(
int
argc
,
char
*
argv
[])
int
main
(
int
argc
,
char
*
argv
[])
{
{
register
int
i
;
register
int
i
;
register
int
j
;
register
int
j
;
register
int
c
;
register
int
c
;
#ifndef WIN32
#ifndef WIN32
(
void
)
umask
(
umask
(
S_IWGRP
|
S_IWOTH
)
|
(
S_IWGRP
|
S_IWOTH
));
(
void
)
umask
(
umask
(
S_IWGRP
|
S_IWOTH
)
|
(
S_IWGRP
|
S_IWOTH
));
#endif
/* !WIN32 */
#endif
/* !WIN32 */
progname
=
argv
[
0
];
progname
=
argv
[
0
];
for
(
i
=
1
;
i
<
argc
;
++
i
)
for
(
i
=
1
;
i
<
argc
;
++
i
)
if
(
strcmp
(
argv
[
i
],
"--version"
)
==
0
)
{
if
(
strcmp
(
argv
[
i
],
"--version"
)
==
0
)
{
(
void
)
printf
(
"%s
\n
"
,
elsieid
);
(
void
)
printf
(
"%s
\n
"
,
elsieid
);
(
void
)
exit
(
EXIT_SUCCESS
);
(
void
)
exit
(
EXIT_SUCCESS
);
}
}
while
((
c
=
getopt
(
argc
,
argv
,
"d:l:p:L:vsy:"
))
!=
EOF
&&
c
!=
-
1
)
while
((
c
=
getopt
(
argc
,
argv
,
"d:l:p:L:vsy:"
))
!=
EOF
&&
c
!=
-
1
)
switch
(
c
)
{
switch
(
c
)
{
default:
default:
usage
();
usage
();
case
'd'
:
case
'd'
:
if
(
directory
==
NULL
)
if
(
directory
==
NULL
)
directory
=
optarg
;
directory
=
optarg
;
else
{
else
{
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: More than one -d option specified
\n
"
),
_
(
"%s: More than one -d option specified
\n
"
),
progname
);
progname
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
break
;
break
;
case
'l'
:
case
'l'
:
if
(
lcltime
==
NULL
)
if
(
lcltime
==
NULL
)
lcltime
=
optarg
;
lcltime
=
optarg
;
else
{
else
{
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: More than one -l option specified
\n
"
),
_
(
"%s: More than one -l option specified
\n
"
),
progname
);
progname
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
break
;
break
;
case
'p'
:
case
'p'
:
if
(
psxrules
==
NULL
)
if
(
psxrules
==
NULL
)
psxrules
=
optarg
;
psxrules
=
optarg
;
else
{
else
{
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: More than one -p option specified
\n
"
),
_
(
"%s: More than one -p option specified
\n
"
),
progname
);
progname
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
break
;
break
;
case
'y'
:
case
'y'
:
if
(
yitcommand
==
NULL
)
if
(
yitcommand
==
NULL
)
yitcommand
=
optarg
;
yitcommand
=
optarg
;
else
{
else
{
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: More than one -y option specified
\n
"
),
_
(
"%s: More than one -y option specified
\n
"
),
progname
);
progname
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
break
;
break
;
case
'L'
:
case
'L'
:
if
(
leapsec
==
NULL
)
if
(
leapsec
==
NULL
)
leapsec
=
optarg
;
leapsec
=
optarg
;
else
{
else
{
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: More than one -L option specified
\n
"
),
_
(
"%s: More than one -L option specified
\n
"
),
progname
);
progname
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
break
;
break
;
...
@@ -523,7 +542,7 @@ _("%s: More than one -L option specified\n"),
...
@@ -523,7 +542,7 @@ _("%s: More than one -L option specified\n"),
break
;
break
;
}
}
if
(
optind
==
argc
-
1
&&
strcmp
(
argv
[
optind
],
"="
)
==
0
)
if
(
optind
==
argc
-
1
&&
strcmp
(
argv
[
optind
],
"="
)
==
0
)
usage
();
/* usage message by request */
usage
();
/* usage message by request */
if
(
directory
==
NULL
)
if
(
directory
==
NULL
)
directory
=
"data"
;
directory
=
"data"
;
if
(
yitcommand
==
NULL
)
if
(
yitcommand
==
NULL
)
...
@@ -531,7 +550,8 @@ _("%s: More than one -L option specified\n"),
...
@@ -531,7 +550,8 @@ _("%s: More than one -L option specified\n"),
setboundaries
();
setboundaries
();
if
(
optind
<
argc
&&
leapsec
!=
NULL
)
{
if
(
optind
<
argc
&&
leapsec
!=
NULL
)
{
infile
(
leapsec
);
infile
(
leapsec
);
adjleap
();
adjleap
();
}
}
...
@@ -541,59 +561,69 @@ _("%s: More than one -L option specified\n"),
...
@@ -541,59 +561,69 @@ _("%s: More than one -L option specified\n"),
if
(
errors
)
if
(
errors
)
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
associate
();
associate
();
for
(
i
=
0
;
i
<
nzones
;
i
=
j
)
{
for
(
i
=
0
;
i
<
nzones
;
i
=
j
)
{
/*
/*
*
* Find the next non-continuation zone entry.
*
* Find the next non-continuation zone entry.
*/
*/
for
(
j
=
i
+
1
;
j
<
nzones
&&
zones
[
j
].
z_name
==
NULL
;
++
j
)
for
(
j
=
i
+
1
;
j
<
nzones
&&
zones
[
j
].
z_name
==
NULL
;
++
j
)
continue
;
continue
;
outzone
(
&
zones
[
i
],
j
-
i
);
outzone
(
&
zones
[
i
],
j
-
i
);
}
}
/*
/*
** Make links.
* * Make links.
*/
*/
for
(
i
=
0
;
i
<
nlinks
;
++
i
)
{
for
(
i
=
0
;
i
<
nlinks
;
++
i
)
{
eat
(
links
[
i
].
l_filename
,
links
[
i
].
l_linenum
);
eat
(
links
[
i
].
l_filename
,
links
[
i
].
l_linenum
);
dolink
(
links
[
i
].
l_from
,
links
[
i
].
l_to
);
dolink
(
links
[
i
].
l_from
,
links
[
i
].
l_to
);
}
}
if
(
lcltime
!=
NULL
)
{
if
(
lcltime
!=
NULL
)
{
eat
(
"command line"
,
1
);
eat
(
"command line"
,
1
);
dolink
(
lcltime
,
TZDEFAULT
);
dolink
(
lcltime
,
TZDEFAULT
);
}
}
if
(
psxrules
!=
NULL
)
{
if
(
psxrules
!=
NULL
)
{
eat
(
"command line"
,
1
);
eat
(
"command line"
,
1
);
dolink
(
psxrules
,
TZDEFRULES
);
dolink
(
psxrules
,
TZDEFRULES
);
}
}
return
(
errors
==
0
)
?
EXIT_SUCCESS
:
EXIT_FAILURE
;
return
(
errors
==
0
)
?
EXIT_SUCCESS
:
EXIT_FAILURE
;
}
}
static
void
dolink
(
const
char
*
fromfile
,
const
char
*
tofile
)
static
void
dolink
(
const
char
*
fromfile
,
const
char
*
tofile
)
{
{
register
char
*
fromname
;
register
char
*
fromname
;
register
char
*
toname
;
register
char
*
toname
;
if
(
fromfile
[
0
]
==
'/'
)
if
(
fromfile
[
0
]
==
'/'
)
fromname
=
ecpyalloc
(
fromfile
);
fromname
=
ecpyalloc
(
fromfile
);
else
{
else
{
fromname
=
ecpyalloc
(
directory
);
fromname
=
ecpyalloc
(
directory
);
fromname
=
ecatalloc
(
fromname
,
"/"
);
fromname
=
ecatalloc
(
fromname
,
"/"
);
fromname
=
ecatalloc
(
fromname
,
fromfile
);
fromname
=
ecatalloc
(
fromname
,
fromfile
);
}
}
if
(
tofile
[
0
]
==
'/'
)
if
(
tofile
[
0
]
==
'/'
)
toname
=
ecpyalloc
(
tofile
);
toname
=
ecpyalloc
(
tofile
);
else
{
else
{
toname
=
ecpyalloc
(
directory
);
toname
=
ecpyalloc
(
directory
);
toname
=
ecatalloc
(
toname
,
"/"
);
toname
=
ecatalloc
(
toname
,
"/"
);
toname
=
ecatalloc
(
toname
,
tofile
);
toname
=
ecatalloc
(
toname
,
tofile
);
}
}
/*
/*
** We get to be careful here since
* * We get to be careful here since * there's a fair chance of root
** there's a fair chance of root
running us.
*
running us.
*/
*/
if
(
!
itsdir
(
toname
))
if
(
!
itsdir
(
toname
))
(
void
)
remove
(
toname
);
(
void
)
remove
(
toname
);
if
(
link
(
fromname
,
toname
)
!=
0
)
{
if
(
link
(
fromname
,
toname
)
!=
0
)
int
result
;
{
int
result
;
if
(
mkdirs
(
toname
)
!=
0
)
if
(
mkdirs
(
toname
)
!=
0
)
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
...
@@ -601,26 +631,29 @@ static void dolink(const char *fromfile, const char *tofile)
...
@@ -601,26 +631,29 @@ static void dolink(const char *fromfile, const char *tofile)
result
=
link
(
fromname
,
toname
);
result
=
link
(
fromname
,
toname
);
#ifdef HAVE_SYMLINK
#ifdef HAVE_SYMLINK
if
(
result
!=
0
&&
if
(
result
!=
0
&&
access
(
fromname
,
F_OK
)
==
0
&&
access
(
fromname
,
F_OK
)
==
0
&&
!
itsdir
(
fromname
))
{
!
itsdir
(
fromname
))
const
char
*
s
=
tofile
;
{
register
char
*
symlinkcontents
=
NULL
;
const
char
*
s
=
tofile
;
while
((
s
=
strchr
(
s
+
1
,
'/'
))
!=
NULL
)
register
char
*
symlinkcontents
=
NULL
;
symlinkcontents
=
ecatalloc
(
symlinkcontents
,
"../"
);
while
((
s
=
strchr
(
s
+
1
,
'/'
))
!=
NULL
)
symlinkcontents
=
ecatalloc
(
symlinkcontents
,
"../"
);
symlinkcontents
=
ecatalloc
(
symlinkcontents
,
fromfile
);
symlinkcontents
=
ecatalloc
(
symlinkcontents
,
fromfile
);
result
=
symlink
(
symlinkcontents
,
toname
);
result
=
symlink
(
symlinkcontents
,
toname
);
if
(
result
==
0
)
if
(
result
==
0
)
warning
(
_
(
"hard link failed, symbolic link used"
));
warning
(
_
(
"hard link failed, symbolic link used"
));
ifree
(
symlinkcontents
);
ifree
(
symlinkcontents
);
}
}
#endif
#endif
if
(
result
!=
0
)
{
if
(
result
!=
0
)
{
const
char
*
e
=
strerror
(
errno
);
const
char
*
e
=
strerror
(
errno
);
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't link from %s to %s: %s
\n
"
),
_
(
"%s: Can't link from %s to %s: %s
\n
"
),
progname
,
fromname
,
toname
,
e
);
progname
,
fromname
,
toname
,
e
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
}
}
...
@@ -629,12 +662,12 @@ warning(_("hard link failed, symbolic link used"));
...
@@ -629,12 +662,12 @@ warning(_("hard link failed, symbolic link used"));
}
}
#ifndef INT_MAX
#ifndef INT_MAX
#define INT_MAX
((int) (((unsigned)~0)>>1))
#define INT_MAX
((int) (((unsigned)~0)>>1))
#endif
/* !defined INT_MAX */
#endif
/* !defined INT_MAX */
#ifndef INT_MIN
#ifndef INT_MIN
#define INT_MIN
((int) ~(((unsigned)~0)>>1))
#define INT_MIN
((int) ~(((unsigned)~0)>>1))
#endif
/* !defined INT_MIN */
#endif
/* !defined INT_MIN */
/*
/*
** The tz file format currently allows at most 32-bit quantities.
** The tz file format currently allows at most 32-bit quantities.
...
@@ -644,17 +677,21 @@ warning(_("hard link failed, symbolic link used"));
...
@@ -644,17 +677,21 @@ warning(_("hard link failed, symbolic link used"));
*/
*/
#define MAX_BITS_IN_FILE 32
#define MAX_BITS_IN_FILE 32
#define TIME_T_BITS_IN_FILE
((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE)
#define TIME_T_BITS_IN_FILE
((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE)
static
void
setboundaries
(
void
)
static
void
setboundaries
(
void
)
{
{
if
(
TYPE_SIGNED
(
time_t
))
{
if
(
TYPE_SIGNED
(
time_t
))
min_time
=
~
(
time_t
)
0
;
{
min_time
=
~
(
time_t
)
0
;
min_time
<<=
TIME_T_BITS_IN_FILE
-
1
;
min_time
<<=
TIME_T_BITS_IN_FILE
-
1
;
max_time
=
~
(
time_t
)
0
-
min_time
;
max_time
=
~
(
time_t
)
0
-
min_time
;
if
(
sflag
)
if
(
sflag
)
min_time
=
0
;
min_time
=
0
;
}
else
{
}
else
{
min_time
=
0
;
min_time
=
0
;
max_time
=
2
-
sflag
;
max_time
=
2
-
sflag
;
max_time
<<=
TIME_T_BITS_IN_FILE
-
1
;
max_time
<<=
TIME_T_BITS_IN_FILE
-
1
;
...
@@ -666,10 +703,11 @@ static void setboundaries(void)
...
@@ -666,10 +703,11 @@ static void setboundaries(void)
max_year_representable
=
max_year
;
max_year_representable
=
max_year
;
}
}
static
int
itsdir
(
const
char
*
name
)
static
int
itsdir
(
const
char
*
name
)
{
{
register
char
*
myname
;
register
char
*
myname
;
register
int
accres
;
register
int
accres
;
myname
=
ecpyalloc
(
name
);
myname
=
ecpyalloc
(
name
);
myname
=
ecatalloc
(
myname
,
"/."
);
myname
=
ecatalloc
(
myname
,
"/."
);
...
@@ -686,59 +724,69 @@ static int itsdir(const char *name)
...
@@ -686,59 +724,69 @@ static int itsdir(const char *name)
** Sort by rule name.
** Sort by rule name.
*/
*/
static
int
rcomp
(
const
void
*
cp1
,
const
void
*
cp2
)
static
int
rcomp
(
const
void
*
cp1
,
const
void
*
cp2
)
{
{
return
strcmp
(((
const
struct
rule
*
)
cp1
)
->
r_name
,
return
strcmp
(((
const
struct
rule
*
)
cp1
)
->
r_name
,
((
const
struct
rule
*
)
cp2
)
->
r_name
);
((
const
struct
rule
*
)
cp2
)
->
r_name
);
}
}
static
void
associate
(
void
)
static
void
associate
(
void
)
{
{
register
struct
zone
*
zp
;
register
struct
zone
*
zp
;
register
struct
rule
*
rp
;
register
struct
rule
*
rp
;
register
int
base
,
out
;
register
int
base
,
register
int
i
,
j
;
out
;
register
int
i
,
if
(
nrules
!=
0
)
{
j
;
if
(
nrules
!=
0
)
{
(
void
)
qsort
((
void
*
)
rules
,
(
size_t
)
nrules
,
(
void
)
qsort
((
void
*
)
rules
,
(
size_t
)
nrules
,
(
size_t
)
sizeof
*
rules
,
rcomp
);
(
size_t
)
sizeof
*
rules
,
rcomp
);
for
(
i
=
0
;
i
<
nrules
-
1
;
++
i
)
{
for
(
i
=
0
;
i
<
nrules
-
1
;
++
i
)
{
if
(
strcmp
(
rules
[
i
].
r_name
,
if
(
strcmp
(
rules
[
i
].
r_name
,
rules
[
i
+
1
].
r_name
)
!=
0
)
rules
[
i
+
1
].
r_name
)
!=
0
)
continue
;
continue
;
if
(
strcmp
(
rules
[
i
].
r_filename
,
if
(
strcmp
(
rules
[
i
].
r_filename
,
rules
[
i
+
1
].
r_filename
)
==
0
)
rules
[
i
+
1
].
r_filename
)
==
0
)
continue
;
continue
;
eat
(
rules
[
i
].
r_filename
,
rules
[
i
].
r_linenum
);
eat
(
rules
[
i
].
r_filename
,
rules
[
i
].
r_linenum
);
warning
(
_
(
"same rule name in multiple files"
));
warning
(
_
(
"same rule name in multiple files"
));
eat
(
rules
[
i
+
1
].
r_filename
,
rules
[
i
+
1
].
r_linenum
);
eat
(
rules
[
i
+
1
].
r_filename
,
rules
[
i
+
1
].
r_linenum
);
warning
(
_
(
"same rule name in multiple files"
));
warning
(
_
(
"same rule name in multiple files"
));
for
(
j
=
i
+
2
;
j
<
nrules
;
++
j
)
{
for
(
j
=
i
+
2
;
j
<
nrules
;
++
j
)
{
if
(
strcmp
(
rules
[
i
].
r_name
,
if
(
strcmp
(
rules
[
i
].
r_name
,
rules
[
j
].
r_name
)
!=
0
)
rules
[
j
].
r_name
)
!=
0
)
break
;
break
;
if
(
strcmp
(
rules
[
i
].
r_filename
,
if
(
strcmp
(
rules
[
i
].
r_filename
,
rules
[
j
].
r_filename
)
==
0
)
rules
[
j
].
r_filename
)
==
0
)
continue
;
continue
;
if
(
strcmp
(
rules
[
i
+
1
].
r_filename
,
if
(
strcmp
(
rules
[
i
+
1
].
r_filename
,
rules
[
j
].
r_filename
)
==
0
)
rules
[
j
].
r_filename
)
==
0
)
continue
;
continue
;
break
;
break
;
}
}
i
=
j
-
1
;
i
=
j
-
1
;
}
}
}
}
for
(
i
=
0
;
i
<
nzones
;
++
i
)
{
for
(
i
=
0
;
i
<
nzones
;
++
i
)
{
zp
=
&
zones
[
i
];
zp
=
&
zones
[
i
];
zp
->
z_rules
=
NULL
;
zp
->
z_rules
=
NULL
;
zp
->
z_nrules
=
0
;
zp
->
z_nrules
=
0
;
}
}
for
(
base
=
0
;
base
<
nrules
;
base
=
out
)
{
for
(
base
=
0
;
base
<
nrules
;
base
=
out
)
{
rp
=
&
rules
[
base
];
rp
=
&
rules
[
base
];
for
(
out
=
base
+
1
;
out
<
nrules
;
++
out
)
for
(
out
=
base
+
1
;
out
<
nrules
;
++
out
)
if
(
strcmp
(
rp
->
r_name
,
rules
[
out
].
r_name
)
!=
0
)
if
(
strcmp
(
rp
->
r_name
,
rules
[
out
].
r_name
)
!=
0
)
break
;
break
;
for
(
i
=
0
;
i
<
nzones
;
++
i
)
{
for
(
i
=
0
;
i
<
nzones
;
++
i
)
{
zp
=
&
zones
[
i
];
zp
=
&
zones
[
i
];
if
(
strcmp
(
zp
->
z_rule
,
rp
->
r_name
)
!=
0
)
if
(
strcmp
(
zp
->
z_rule
,
rp
->
r_name
)
!=
0
)
continue
;
continue
;
...
@@ -746,19 +794,22 @@ static void associate(void)
...
@@ -746,19 +794,22 @@ static void associate(void)
zp
->
z_nrules
=
out
-
base
;
zp
->
z_nrules
=
out
-
base
;
}
}
}
}
for
(
i
=
0
;
i
<
nzones
;
++
i
)
{
for
(
i
=
0
;
i
<
nzones
;
++
i
)
{
zp
=
&
zones
[
i
];
zp
=
&
zones
[
i
];
if
(
zp
->
z_nrules
==
0
)
{
if
(
zp
->
z_nrules
==
0
)
{
/*
/*
*
* Maybe we have a local standard time offset.
*
* Maybe we have a local standard time offset.
*/
*/
eat
(
zp
->
z_filename
,
zp
->
z_linenum
);
eat
(
zp
->
z_filename
,
zp
->
z_linenum
);
zp
->
z_stdoff
=
gethms
(
zp
->
z_rule
,
_
(
"unruly zone"
),
zp
->
z_stdoff
=
gethms
(
zp
->
z_rule
,
_
(
"unruly zone"
),
TRUE
);
TRUE
);
/*
/*
** Note, though, that if there's no rule,
* * Note, though, that if there's no rule, * a '%s' in the
** a '%s' in the
format is a bad thing.
*
format is a bad thing.
*/
*/
if
(
strchr
(
zp
->
z_format
,
'%'
)
!=
0
)
if
(
strchr
(
zp
->
z_format
,
'%'
)
!=
0
)
error
(
_
(
"%s in ruleless zone"
));
error
(
_
(
"%s in ruleless zone"
));
}
}
...
@@ -767,94 +818,109 @@ static void associate(void)
...
@@ -767,94 +818,109 @@ static void associate(void)
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
static
void
infile
(
const
char
*
name
)
static
void
infile
(
const
char
*
name
)
{
{
register
FILE
*
fp
;
register
FILE
*
fp
;
register
char
**
fields
;
register
char
**
fields
;
register
char
*
cp
;
register
char
*
cp
;
register
const
struct
lookup
*
lp
;
register
const
struct
lookup
*
lp
;
register
int
nfields
;
register
int
nfields
;
register
int
wantcont
;
register
int
wantcont
;
register
int
num
;
register
int
num
;
char
buf
[
BUFSIZ
];
char
buf
[
BUFSIZ
];
if
(
strcmp
(
name
,
"-"
)
==
0
)
{
if
(
strcmp
(
name
,
"-"
)
==
0
)
{
name
=
_
(
"standard input"
);
name
=
_
(
"standard input"
);
fp
=
stdin
;
fp
=
stdin
;
}
else
if
((
fp
=
fopen
(
name
,
"r"
))
==
NULL
)
{
}
else
if
((
fp
=
fopen
(
name
,
"r"
))
==
NULL
)
{
const
char
*
e
=
strerror
(
errno
);
const
char
*
e
=
strerror
(
errno
);
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't open %s: %s
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't open %s: %s
\n
"
),
progname
,
name
,
e
);
progname
,
name
,
e
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
wantcont
=
FALSE
;
wantcont
=
FALSE
;
for
(
num
=
1
;
;
++
num
)
{
for
(
num
=
1
;;
++
num
)
{
eat
(
name
,
num
);
eat
(
name
,
num
);
if
(
fgets
(
buf
,
(
int
)
sizeof
buf
,
fp
)
!=
buf
)
if
(
fgets
(
buf
,
(
int
)
sizeof
buf
,
fp
)
!=
buf
)
break
;
break
;
cp
=
strchr
(
buf
,
'\n'
);
cp
=
strchr
(
buf
,
'\n'
);
if
(
cp
==
NULL
)
{
if
(
cp
==
NULL
)
{
error
(
_
(
"line too long"
));
error
(
_
(
"line too long"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
*
cp
=
'\0'
;
*
cp
=
'\0'
;
fields
=
getfields
(
buf
);
fields
=
getfields
(
buf
);
nfields
=
0
;
nfields
=
0
;
while
(
fields
[
nfields
]
!=
NULL
)
{
while
(
fields
[
nfields
]
!=
NULL
)
static
char
nada
;
{
static
char
nada
;
if
(
strcmp
(
fields
[
nfields
],
"-"
)
==
0
)
if
(
strcmp
(
fields
[
nfields
],
"-"
)
==
0
)
fields
[
nfields
]
=
&
nada
;
fields
[
nfields
]
=
&
nada
;
++
nfields
;
++
nfields
;
}
}
if
(
nfields
==
0
)
{
if
(
nfields
==
0
)
{
/* nothing to do */
/* nothing to do */
}
else
if
(
wantcont
)
{
}
else
if
(
wantcont
)
wantcont
=
inzcont
(
fields
,
nfields
);
wantcont
=
inzcont
(
fields
,
nfields
);
}
else
{
else
{
lp
=
byword
(
fields
[
0
],
line_codes
);
lp
=
byword
(
fields
[
0
],
line_codes
);
if
(
lp
==
NULL
)
if
(
lp
==
NULL
)
error
(
_
(
"input line of unknown type"
));
error
(
_
(
"input line of unknown type"
));
else
switch
((
int
)
(
lp
->
l_value
))
{
else
case
LC_RULE
:
switch
((
int
)
(
lp
->
l_value
))
inrule
(
fields
,
nfields
);
{
wantcont
=
FALSE
;
case
LC_RULE
:
break
;
inrule
(
fields
,
nfields
);
case
LC_ZONE
:
wantcont
=
FALSE
;
wantcont
=
inzone
(
fields
,
nfields
);
break
;
break
;
case
LC_ZONE
:
case
LC_LINK
:
wantcont
=
inzone
(
fields
,
nfields
);
inlink
(
fields
,
nfields
);
break
;
wantcont
=
FALSE
;
case
LC_LINK
:
break
;
inlink
(
fields
,
nfields
);
case
LC_LEAP
:
wantcont
=
FALSE
;
if
(
name
!=
leapsec
)
break
;
case
LC_LEAP
:
if
(
name
!=
leapsec
)
(
void
)
fprintf
(
stderr
,
_
(
"%s: Leap line in non leap seconds file %s
\n
"
),
progname
,
name
);
else
inleap
(
fields
,
nfields
);
wantcont
=
FALSE
;
break
;
default:
/* "cannot happen" */
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: Leap line in non leap seconds file %s
\n
"
),
_
(
"%s: panic: Invalid l_value %d
\n
"
),
progname
,
name
);
progname
,
lp
->
l_value
);
else
inleap
(
fields
,
nfields
);
(
void
)
exit
(
EXIT_FAILURE
);
wantcont
=
FALSE
;
}
break
;
default:
/* "cannot happen" */
(
void
)
fprintf
(
stderr
,
_
(
"%s: panic: Invalid l_value %d
\n
"
),
progname
,
lp
->
l_value
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
}
ifree
((
char
*
)
fields
);
ifree
((
char
*
)
fields
);
}
}
if
(
ferror
(
fp
))
{
if
(
ferror
(
fp
))
{
(
void
)
fprintf
(
stderr
,
_
(
"%s: Error reading %s
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: Error reading %s
\n
"
),
progname
,
filename
);
progname
,
filename
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
if
(
fp
!=
stdin
&&
fclose
(
fp
))
{
if
(
fp
!=
stdin
&&
fclose
(
fp
))
{
const
char
*
e
=
strerror
(
errno
);
const
char
*
e
=
strerror
(
errno
);
(
void
)
fprintf
(
stderr
,
_
(
"%s: Error closing %s: %s
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: Error closing %s: %s
\n
"
),
progname
,
filename
,
e
);
progname
,
filename
,
e
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
if
(
wantcont
)
if
(
wantcont
)
...
@@ -869,50 +935,62 @@ _("%s: panic: Invalid l_value %d\n"),
...
@@ -869,50 +935,62 @@ _("%s: panic: Invalid l_value %d\n"),
** Call error with errstring and return zero on errors.
** Call error with errstring and return zero on errors.
*/
*/
static
long
gethms
(
const
char
*
string
,
const
char
*
errstring
,
const
int
signable
)
static
long
gethms
(
const
char
*
string
,
const
char
*
errstring
,
const
int
signable
)
{
{
int
hh
,
mm
,
ss
,
sign
;
int
hh
,
mm
,
ss
,
sign
;
if
(
string
==
NULL
||
*
string
==
'\0'
)
if
(
string
==
NULL
||
*
string
==
'\0'
)
return
0
;
return
0
;
if
(
!
signable
)
if
(
!
signable
)
sign
=
1
;
sign
=
1
;
else
if
(
*
string
==
'-'
)
{
else
if
(
*
string
==
'-'
)
{
sign
=
-
1
;
sign
=
-
1
;
++
string
;
++
string
;
}
else
sign
=
1
;
}
else
sign
=
1
;
if
(
sscanf
(
string
,
scheck
(
string
,
"%d"
),
&
hh
)
==
1
)
if
(
sscanf
(
string
,
scheck
(
string
,
"%d"
),
&
hh
)
==
1
)
mm
=
ss
=
0
;
mm
=
ss
=
0
;
else
if
(
sscanf
(
string
,
scheck
(
string
,
"%d:%d"
),
&
hh
,
&
mm
)
==
2
)
else
if
(
sscanf
(
string
,
scheck
(
string
,
"%d:%d"
),
&
hh
,
&
mm
)
==
2
)
ss
=
0
;
ss
=
0
;
else
if
(
sscanf
(
string
,
scheck
(
string
,
"%d:%d:%d"
),
else
if
(
sscanf
(
string
,
scheck
(
string
,
"%d:%d:%d"
),
&
hh
,
&
mm
,
&
ss
)
!=
3
)
{
&
hh
,
&
mm
,
&
ss
)
!=
3
)
error
(
errstring
);
{
return
0
;
error
(
errstring
);
return
0
;
}
}
if
((
hh
<
0
||
hh
>=
HOURSPERDAY
||
if
((
hh
<
0
||
hh
>=
HOURSPERDAY
||
mm
<
0
||
mm
>=
MINSPERHOUR
||
mm
<
0
||
mm
>=
MINSPERHOUR
||
ss
<
0
||
ss
>
SECSPERMIN
)
&&
ss
<
0
||
ss
>
SECSPERMIN
)
&&
!
(
hh
==
HOURSPERDAY
&&
mm
==
0
&&
ss
==
0
))
{
!
(
hh
==
HOURSPERDAY
&&
mm
==
0
&&
ss
==
0
))
error
(
errstring
);
{
return
0
;
error
(
errstring
);
return
0
;
}
}
if
(
noise
&&
hh
==
HOURSPERDAY
)
if
(
noise
&&
hh
==
HOURSPERDAY
)
warning
(
_
(
"24:00 not handled by pre-1998 versions of zic"
));
warning
(
_
(
"24:00 not handled by pre-1998 versions of zic"
));
return
eitol
(
sign
)
*
return
eitol
(
sign
)
*
(
eitol
(
hh
*
MINSPERHOUR
+
mm
)
*
(
eitol
(
hh
*
MINSPERHOUR
+
mm
)
*
eitol
(
SECSPERMIN
)
+
eitol
(
ss
));
eitol
(
SECSPERMIN
)
+
eitol
(
ss
));
}
}
static
void
inrule
(
register
char
**
fields
,
const
int
nfields
)
static
void
inrule
(
register
char
**
fields
,
const
int
nfields
)
{
{
static
struct
rule
r
;
static
struct
rule
r
;
if
(
nfields
!=
RULE_FIELDS
)
{
if
(
nfields
!=
RULE_FIELDS
)
{
error
(
_
(
"wrong number of fields on Rule line"
));
error
(
_
(
"wrong number of fields on Rule line"
));
return
;
return
;
}
}
if
(
*
fields
[
RF_NAME
]
==
'\0'
)
{
if
(
*
fields
[
RF_NAME
]
==
'\0'
)
{
error
(
_
(
"nameless rule"
));
error
(
_
(
"nameless rule"
));
return
;
return
;
}
}
...
@@ -920,75 +998,88 @@ static void inrule(register char **fields, const int nfields)
...
@@ -920,75 +998,88 @@ static void inrule(register char **fields, const int nfields)
r
.
r_linenum
=
linenum
;
r
.
r_linenum
=
linenum
;
r
.
r_stdoff
=
gethms
(
fields
[
RF_STDOFF
],
_
(
"invalid saved time"
),
TRUE
);
r
.
r_stdoff
=
gethms
(
fields
[
RF_STDOFF
],
_
(
"invalid saved time"
),
TRUE
);
rulesub
(
&
r
,
fields
[
RF_LOYEAR
],
fields
[
RF_HIYEAR
],
fields
[
RF_COMMAND
],
rulesub
(
&
r
,
fields
[
RF_LOYEAR
],
fields
[
RF_HIYEAR
],
fields
[
RF_COMMAND
],
fields
[
RF_MONTH
],
fields
[
RF_DAY
],
fields
[
RF_TOD
]);
fields
[
RF_MONTH
],
fields
[
RF_DAY
],
fields
[
RF_TOD
]);
r
.
r_name
=
ecpyalloc
(
fields
[
RF_NAME
]);
r
.
r_name
=
ecpyalloc
(
fields
[
RF_NAME
]);
r
.
r_abbrvar
=
ecpyalloc
(
fields
[
RF_ABBRVAR
]);
r
.
r_abbrvar
=
ecpyalloc
(
fields
[
RF_ABBRVAR
]);
rules
=
(
struct
rule
*
)
(
void
*
)
erealloc
((
char
*
)
rules
,
rules
=
(
struct
rule
*
)
(
void
*
)
erealloc
((
char
*
)
rules
,
(
int
)
((
nrules
+
1
)
*
sizeof
*
rules
));
(
int
)
((
nrules
+
1
)
*
sizeof
*
rules
));
rules
[
nrules
++
]
=
r
;
rules
[
nrules
++
]
=
r
;
}
}
static
int
inzone
(
register
char
**
fields
,
const
int
nfields
)
static
int
inzone
(
register
char
**
fields
,
const
int
nfields
)
{
{
register
int
i
;
register
int
i
;
static
char
*
buf
;
static
char
*
buf
;
if
(
nfields
<
ZONE_MINFIELDS
||
nfields
>
ZONE_MAXFIELDS
)
{
if
(
nfields
<
ZONE_MINFIELDS
||
nfields
>
ZONE_MAXFIELDS
)
{
error
(
_
(
"wrong number of fields on Zone line"
));
error
(
_
(
"wrong number of fields on Zone line"
));
return
FALSE
;
return
FALSE
;
}
}
if
(
strcmp
(
fields
[
ZF_NAME
],
TZDEFAULT
)
==
0
&&
lcltime
!=
NULL
)
{
if
(
strcmp
(
fields
[
ZF_NAME
],
TZDEFAULT
)
==
0
&&
lcltime
!=
NULL
)
{
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
strlen
(
TZDEFAULT
)));
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
strlen
(
TZDEFAULT
)));
(
void
)
sprintf
(
buf
,
(
void
)
sprintf
(
buf
,
_
(
"
\"
Zone %s
\"
line and -l option are mutually exclusive"
),
_
(
"
\"
Zone %s
\"
line and -l option are mutually exclusive"
),
TZDEFAULT
);
TZDEFAULT
);
error
(
buf
);
error
(
buf
);
return
FALSE
;
return
FALSE
;
}
}
if
(
strcmp
(
fields
[
ZF_NAME
],
TZDEFRULES
)
==
0
&&
psxrules
!=
NULL
)
{
if
(
strcmp
(
fields
[
ZF_NAME
],
TZDEFRULES
)
==
0
&&
psxrules
!=
NULL
)
{
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
strlen
(
TZDEFRULES
)));
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
strlen
(
TZDEFRULES
)));
(
void
)
sprintf
(
buf
,
(
void
)
sprintf
(
buf
,
_
(
"
\"
Zone %s
\"
line and -p option are mutually exclusive"
),
_
(
"
\"
Zone %s
\"
line and -p option are mutually exclusive"
),
TZDEFRULES
);
TZDEFRULES
);
error
(
buf
);
error
(
buf
);
return
FALSE
;
return
FALSE
;
}
}
for
(
i
=
0
;
i
<
nzones
;
++
i
)
for
(
i
=
0
;
i
<
nzones
;
++
i
)
if
(
zones
[
i
].
z_name
!=
NULL
&&
if
(
zones
[
i
].
z_name
!=
NULL
&&
strcmp
(
zones
[
i
].
z_name
,
fields
[
ZF_NAME
])
==
0
)
{
strcmp
(
zones
[
i
].
z_name
,
fields
[
ZF_NAME
])
==
0
)
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
{
strlen
(
fields
[
ZF_NAME
])
+
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
strlen
(
zones
[
i
].
z_filename
)));
strlen
(
fields
[
ZF_NAME
])
+
(
void
)
sprintf
(
buf
,
strlen
(
zones
[
i
].
z_filename
)));
_
(
"duplicate zone name %s (file
\"
%s
\"
, line %d)"
),
(
void
)
sprintf
(
buf
,
fields
[
ZF_NAME
],
_
(
"duplicate zone name %s (file
\"
%s
\"
, line %d)"
),
zones
[
i
].
z_filename
,
fields
[
ZF_NAME
],
zones
[
i
].
z_linenum
);
zones
[
i
].
z_filename
,
error
(
buf
);
zones
[
i
].
z_linenum
);
return
FALSE
;
error
(
buf
);
return
FALSE
;
}
}
return
inzsub
(
fields
,
nfields
,
FALSE
);
return
inzsub
(
fields
,
nfields
,
FALSE
);
}
}
static
int
inzcont
(
register
char
**
fields
,
const
int
nfields
)
static
int
inzcont
(
register
char
**
fields
,
const
int
nfields
)
{
{
if
(
nfields
<
ZONEC_MINFIELDS
||
nfields
>
ZONEC_MAXFIELDS
)
{
if
(
nfields
<
ZONEC_MINFIELDS
||
nfields
>
ZONEC_MAXFIELDS
)
{
error
(
_
(
"wrong number of fields on Zone continuation line"
));
error
(
_
(
"wrong number of fields on Zone continuation line"
));
return
FALSE
;
return
FALSE
;
}
}
return
inzsub
(
fields
,
nfields
,
TRUE
);
return
inzsub
(
fields
,
nfields
,
TRUE
);
}
}
static
int
inzsub
(
register
char
**
fields
,
const
int
nfields
,
const
int
iscont
)
static
int
inzsub
(
register
char
**
fields
,
const
int
nfields
,
const
int
iscont
)
{
{
register
char
*
cp
;
register
char
*
cp
;
static
struct
zone
z
;
static
struct
zone
z
;
register
int
i_gmtoff
,
i_rule
,
i_format
;
register
int
i_gmtoff
,
register
int
i_untilyear
,
i_untilmonth
;
i_rule
,
register
int
i_untilday
,
i_untiltime
;
i_format
;
register
int
hasuntil
;
register
int
i_untilyear
,
i_untilmonth
;
if
(
iscont
)
{
register
int
i_untilday
,
i_untiltime
;
register
int
hasuntil
;
if
(
iscont
)
{
i_gmtoff
=
ZFC_GMTOFF
;
i_gmtoff
=
ZFC_GMTOFF
;
i_rule
=
ZFC_RULE
;
i_rule
=
ZFC_RULE
;
i_format
=
ZFC_FORMAT
;
i_format
=
ZFC_FORMAT
;
...
@@ -997,7 +1088,9 @@ static int inzsub(register char **fields, const int nfields, const int iscont)
...
@@ -997,7 +1088,9 @@ static int inzsub(register char **fields, const int nfields, const int iscont)
i_untilday
=
ZFC_TILDAY
;
i_untilday
=
ZFC_TILDAY
;
i_untiltime
=
ZFC_TILTIME
;
i_untiltime
=
ZFC_TILTIME
;
z
.
z_name
=
NULL
;
z
.
z_name
=
NULL
;
}
else
{
}
else
{
i_gmtoff
=
ZF_GMTOFF
;
i_gmtoff
=
ZF_GMTOFF
;
i_rule
=
ZF_RULE
;
i_rule
=
ZF_RULE
;
i_format
=
ZF_FORMAT
;
i_format
=
ZF_FORMAT
;
...
@@ -1010,8 +1103,10 @@ static int inzsub(register char **fields, const int nfields, const int iscont)
...
@@ -1010,8 +1103,10 @@ static int inzsub(register char **fields, const int nfields, const int iscont)
z
.
z_filename
=
filename
;
z
.
z_filename
=
filename
;
z
.
z_linenum
=
linenum
;
z
.
z_linenum
=
linenum
;
z
.
z_gmtoff
=
gethms
(
fields
[
i_gmtoff
],
_
(
"invalid UTC offset"
),
TRUE
);
z
.
z_gmtoff
=
gethms
(
fields
[
i_gmtoff
],
_
(
"invalid UTC offset"
),
TRUE
);
if
((
cp
=
strchr
(
fields
[
i_format
],
'%'
))
!=
0
)
{
if
((
cp
=
strchr
(
fields
[
i_format
],
'%'
))
!=
0
)
if
(
*++
cp
!=
's'
||
strchr
(
cp
,
'%'
)
!=
0
)
{
{
if
(
*++
cp
!=
's'
||
strchr
(
cp
,
'%'
)
!=
0
)
{
error
(
_
(
"invalid abbreviation format"
));
error
(
_
(
"invalid abbreviation format"
));
return
FALSE
;
return
FALSE
;
}
}
...
@@ -1019,126 +1114,157 @@ static int inzsub(register char **fields, const int nfields, const int iscont)
...
@@ -1019,126 +1114,157 @@ static int inzsub(register char **fields, const int nfields, const int iscont)
z
.
z_rule
=
ecpyalloc
(
fields
[
i_rule
]);
z
.
z_rule
=
ecpyalloc
(
fields
[
i_rule
]);
z
.
z_format
=
ecpyalloc
(
fields
[
i_format
]);
z
.
z_format
=
ecpyalloc
(
fields
[
i_format
]);
hasuntil
=
nfields
>
i_untilyear
;
hasuntil
=
nfields
>
i_untilyear
;
if
(
hasuntil
)
{
if
(
hasuntil
)
{
z
.
z_untilrule
.
r_filename
=
filename
;
z
.
z_untilrule
.
r_filename
=
filename
;
z
.
z_untilrule
.
r_linenum
=
linenum
;
z
.
z_untilrule
.
r_linenum
=
linenum
;
rulesub
(
&
z
.
z_untilrule
,
rulesub
(
&
z
.
z_untilrule
,
fields
[
i_untilyear
],
fields
[
i_untilyear
],
"only"
,
"only"
,
""
,
""
,
(
nfields
>
i_untilmonth
)
?
(
nfields
>
i_untilmonth
)
?
fields
[
i_untilmonth
]
:
"Jan"
,
fields
[
i_untilmonth
]
:
"Jan"
,
(
nfields
>
i_untilday
)
?
fields
[
i_untilday
]
:
"1"
,
(
nfields
>
i_untilday
)
?
fields
[
i_untilday
]
:
"1"
,
(
nfields
>
i_untiltime
)
?
fields
[
i_untiltime
]
:
"0"
);
(
nfields
>
i_untiltime
)
?
fields
[
i_untiltime
]
:
"0"
);
z
.
z_untiltime
=
rpytime
(
&
z
.
z_untilrule
,
z
.
z_untiltime
=
rpytime
(
&
z
.
z_untilrule
,
z
.
z_untilrule
.
r_loyear
);
z
.
z_untilrule
.
r_loyear
);
if
(
iscont
&&
nzones
>
0
&&
if
(
iscont
&&
nzones
>
0
&&
z
.
z_untiltime
>
min_time
&&
z
.
z_untiltime
>
min_time
&&
z
.
z_untiltime
<
max_time
&&
z
.
z_untiltime
<
max_time
&&
zones
[
nzones
-
1
].
z_untiltime
>
min_time
&&
zones
[
nzones
-
1
].
z_untiltime
>
min_time
&&
zones
[
nzones
-
1
].
z_untiltime
<
max_time
&&
zones
[
nzones
-
1
].
z_untiltime
<
max_time
&&
zones
[
nzones
-
1
].
z_untiltime
>=
z
.
z_untiltime
)
{
zones
[
nzones
-
1
].
z_untiltime
>=
z
.
z_untiltime
)
error
(
_
(
"Zone continuation line end time is not after end time of previous line"
));
{
return
FALSE
;
error
(
_
(
"Zone continuation line end time is not after end time of previous line"
));
return
FALSE
;
}
}
}
}
zones
=
(
struct
zone
*
)
(
void
*
)
erealloc
((
char
*
)
zones
,
zones
=
(
struct
zone
*
)
(
void
*
)
erealloc
((
char
*
)
zones
,
(
int
)
((
nzones
+
1
)
*
sizeof
*
zones
));
(
int
)
((
nzones
+
1
)
*
sizeof
*
zones
));
zones
[
nzones
++
]
=
z
;
zones
[
nzones
++
]
=
z
;
/*
/*
** If there was an UNTIL field on this line,
* * If there was an UNTIL field on this line, * there's more
** there's more
information about the zone on the next line.
*
information about the zone on the next line.
*/
*/
return
hasuntil
;
return
hasuntil
;
}
}
static
void
inleap
(
register
char
**
fields
,
const
int
nfields
)
static
void
inleap
(
register
char
**
fields
,
const
int
nfields
)
{
{
register
const
char
*
cp
;
register
const
char
*
cp
;
register
const
struct
lookup
*
lp
;
register
const
struct
lookup
*
lp
;
register
int
i
,
j
;
register
int
i
,
int
year
,
month
,
day
;
j
;
long
dayoff
,
tod
;
int
year
,
time_t
t
;
month
,
day
;
if
(
nfields
!=
LEAP_FIELDS
)
{
long
dayoff
,
tod
;
time_t
t
;
if
(
nfields
!=
LEAP_FIELDS
)
{
error
(
_
(
"wrong number of fields on Leap line"
));
error
(
_
(
"wrong number of fields on Leap line"
));
return
;
return
;
}
}
dayoff
=
0
;
dayoff
=
0
;
cp
=
fields
[
LP_YEAR
];
cp
=
fields
[
LP_YEAR
];
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
year
)
!=
1
)
{
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
year
)
!=
1
)
/*
{
* Leapin' Lizards!
/*
*/
* Leapin' Lizards!
error
(
_
(
"invalid leaping year"
));
*/
return
;
error
(
_
(
"invalid leaping year"
));
return
;
}
}
j
=
EPOCH_YEAR
;
j
=
EPOCH_YEAR
;
while
(
j
!=
year
)
{
while
(
j
!=
year
)
if
(
year
>
j
)
{
{
if
(
year
>
j
)
{
i
=
len_years
[
isleap
(
j
)];
i
=
len_years
[
isleap
(
j
)];
++
j
;
++
j
;
}
else
{
}
else
{
--
j
;
--
j
;
i
=
-
len_years
[
isleap
(
j
)];
i
=
-
len_years
[
isleap
(
j
)];
}
}
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
}
}
if
((
lp
=
byword
(
fields
[
LP_MONTH
],
mon_names
))
==
NULL
)
{
if
((
lp
=
byword
(
fields
[
LP_MONTH
],
mon_names
))
==
NULL
)
{
error
(
_
(
"invalid month name"
));
error
(
_
(
"invalid month name"
));
return
;
return
;
}
}
month
=
lp
->
l_value
;
month
=
lp
->
l_value
;
j
=
TM_JANUARY
;
j
=
TM_JANUARY
;
while
(
j
!=
month
)
{
while
(
j
!=
month
)
{
i
=
len_months
[
isleap
(
year
)][
j
];
i
=
len_months
[
isleap
(
year
)][
j
];
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
++
j
;
++
j
;
}
}
cp
=
fields
[
LP_DAY
];
cp
=
fields
[
LP_DAY
];
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
day
)
!=
1
||
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
day
)
!=
1
||
day
<=
0
||
day
>
len_months
[
isleap
(
year
)][
month
])
{
day
<=
0
||
day
>
len_months
[
isleap
(
year
)][
month
])
error
(
_
(
"invalid day of month"
));
{
return
;
error
(
_
(
"invalid day of month"
));
return
;
}
}
dayoff
=
oadd
(
dayoff
,
eitol
(
day
-
1
));
dayoff
=
oadd
(
dayoff
,
eitol
(
day
-
1
));
if
(
dayoff
<
0
&&
!
TYPE_SIGNED
(
time_t
))
{
if
(
dayoff
<
0
&&
!
TYPE_SIGNED
(
time_t
))
{
error
(
_
(
"time before zero"
));
error
(
_
(
"time before zero"
));
return
;
return
;
}
}
if
(
dayoff
<
min_time
/
SECSPERDAY
)
{
if
(
dayoff
<
min_time
/
SECSPERDAY
)
{
error
(
_
(
"time too small"
));
error
(
_
(
"time too small"
));
return
;
return
;
}
}
if
(
dayoff
>
max_time
/
SECSPERDAY
)
{
if
(
dayoff
>
max_time
/
SECSPERDAY
)
{
error
(
_
(
"time too large"
));
error
(
_
(
"time too large"
));
return
;
return
;
}
}
t
=
(
time_t
)
dayoff
*
SECSPERDAY
;
t
=
(
time_t
)
dayoff
*
SECSPERDAY
;
tod
=
gethms
(
fields
[
LP_TIME
],
_
(
"invalid time of day"
),
FALSE
);
tod
=
gethms
(
fields
[
LP_TIME
],
_
(
"invalid time of day"
),
FALSE
);
cp
=
fields
[
LP_CORR
];
cp
=
fields
[
LP_CORR
];
{
{
register
int
positive
;
register
int
positive
;
int
count
;
int
count
;
if
(
strcmp
(
cp
,
""
)
==
0
)
{
/* infile() turns "-" into "" */
if
(
strcmp
(
cp
,
""
)
==
0
)
{
/* infile() turns "-" into "" */
positive
=
FALSE
;
positive
=
FALSE
;
count
=
1
;
count
=
1
;
}
else
if
(
strcmp
(
cp
,
"--"
)
==
0
)
{
}
else
if
(
strcmp
(
cp
,
"--"
)
==
0
)
{
positive
=
FALSE
;
positive
=
FALSE
;
count
=
2
;
count
=
2
;
}
else
if
(
strcmp
(
cp
,
"+"
)
==
0
)
{
}
else
if
(
strcmp
(
cp
,
"+"
)
==
0
)
{
positive
=
TRUE
;
positive
=
TRUE
;
count
=
1
;
count
=
1
;
}
else
if
(
strcmp
(
cp
,
"++"
)
==
0
)
{
}
else
if
(
strcmp
(
cp
,
"++"
)
==
0
)
{
positive
=
TRUE
;
positive
=
TRUE
;
count
=
2
;
count
=
2
;
}
else
{
}
else
{
error
(
_
(
"illegal CORRECTION field on Leap line"
));
error
(
_
(
"illegal CORRECTION field on Leap line"
));
return
;
return
;
}
}
if
((
lp
=
byword
(
fields
[
LP_ROLL
],
leap_types
))
==
NULL
)
{
if
((
lp
=
byword
(
fields
[
LP_ROLL
],
leap_types
))
==
NULL
)
{
error
(
_
(
"illegal Rolling/Stationary field on Leap line"
));
error
(
_
(
"illegal Rolling/Stationary field on Leap line"
));
return
;
return
;
}
}
...
@@ -1146,19 +1272,23 @@ static void inleap(register char **fields, const int nfields)
...
@@ -1146,19 +1272,23 @@ static void inleap(register char **fields, const int nfields)
}
}
}
}
static
void
inlink
(
register
char
**
fields
,
const
int
nfields
)
static
void
inlink
(
register
char
**
fields
,
const
int
nfields
)
{
{
struct
link
l
;
struct
link
l
;
if
(
nfields
!=
LINK_FIELDS
)
{
if
(
nfields
!=
LINK_FIELDS
)
{
error
(
_
(
"wrong number of fields on Link line"
));
error
(
_
(
"wrong number of fields on Link line"
));
return
;
return
;
}
}
if
(
*
fields
[
LF_FROM
]
==
'\0'
)
{
if
(
*
fields
[
LF_FROM
]
==
'\0'
)
{
error
(
_
(
"blank FROM field on Link line"
));
error
(
_
(
"blank FROM field on Link line"
));
return
;
return
;
}
}
if
(
*
fields
[
LF_TO
]
==
'\0'
)
{
if
(
*
fields
[
LF_TO
]
==
'\0'
)
{
error
(
_
(
"blank TO field on Link line"
));
error
(
_
(
"blank TO field on Link line"
));
return
;
return
;
}
}
...
@@ -1167,18 +1297,20 @@ static void inlink(register char **fields, const int nfields)
...
@@ -1167,18 +1297,20 @@ static void inlink(register char **fields, const int nfields)
l
.
l_from
=
ecpyalloc
(
fields
[
LF_FROM
]);
l
.
l_from
=
ecpyalloc
(
fields
[
LF_FROM
]);
l
.
l_to
=
ecpyalloc
(
fields
[
LF_TO
]);
l
.
l_to
=
ecpyalloc
(
fields
[
LF_TO
]);
links
=
(
struct
link
*
)
(
void
*
)
erealloc
((
char
*
)
links
,
links
=
(
struct
link
*
)
(
void
*
)
erealloc
((
char
*
)
links
,
(
int
)
((
nlinks
+
1
)
*
sizeof
*
links
));
(
int
)
((
nlinks
+
1
)
*
sizeof
*
links
));
links
[
nlinks
++
]
=
l
;
links
[
nlinks
++
]
=
l
;
}
}
static
void
rulesub
(
register
struct
rule
*
rp
,
const
char
*
loyearp
,
const
char
*
hiyearp
,
const
char
*
typep
,
const
char
*
monthp
,
const
char
*
dayp
,
const
char
*
timep
)
static
void
rulesub
(
register
struct
rule
*
rp
,
const
char
*
loyearp
,
const
char
*
hiyearp
,
const
char
*
typep
,
const
char
*
monthp
,
const
char
*
dayp
,
const
char
*
timep
)
{
{
register
const
struct
lookup
*
lp
;
register
const
struct
lookup
*
lp
;
register
const
char
*
cp
;
register
const
char
*
cp
;
register
char
*
dp
;
register
char
*
dp
;
register
char
*
ep
;
register
char
*
ep
;
if
((
lp
=
byword
(
monthp
,
mon_names
))
==
NULL
)
{
if
((
lp
=
byword
(
monthp
,
mon_names
))
==
NULL
)
{
error
(
_
(
"invalid month name"
));
error
(
_
(
"invalid month name"
));
return
;
return
;
}
}
...
@@ -1186,22 +1318,24 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
...
@@ -1186,22 +1318,24 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
rp
->
r_todisstd
=
FALSE
;
rp
->
r_todisstd
=
FALSE
;
rp
->
r_todisgmt
=
FALSE
;
rp
->
r_todisgmt
=
FALSE
;
dp
=
ecpyalloc
(
timep
);
dp
=
ecpyalloc
(
timep
);
if
(
*
dp
!=
'\0'
)
{
if
(
*
dp
!=
'\0'
)
{
ep
=
dp
+
strlen
(
dp
)
-
1
;
ep
=
dp
+
strlen
(
dp
)
-
1
;
switch
(
lowerit
(
*
ep
))
{
switch
(
lowerit
(
*
ep
))
case
's'
:
/* Standard */
{
case
's'
:
/* Standard */
rp
->
r_todisstd
=
TRUE
;
rp
->
r_todisstd
=
TRUE
;
rp
->
r_todisgmt
=
FALSE
;
rp
->
r_todisgmt
=
FALSE
;
*
ep
=
'\0'
;
*
ep
=
'\0'
;
break
;
break
;
case
'w'
:
/* Wall */
case
'w'
:
/* Wall */
rp
->
r_todisstd
=
FALSE
;
rp
->
r_todisstd
=
FALSE
;
rp
->
r_todisgmt
=
FALSE
;
rp
->
r_todisgmt
=
FALSE
;
*
ep
=
'\0'
;
*
ep
=
'\0'
;
break
;
break
;
case
'g'
:
/* Greenwich */
case
'g'
:
/* Greenwich */
case
'u'
:
/* Universal */
case
'u'
:
/* Universal */
case
'z'
:
/* Zulu */
case
'z'
:
/* Zulu */
rp
->
r_todisstd
=
TRUE
;
rp
->
r_todisstd
=
TRUE
;
rp
->
r_todisgmt
=
TRUE
;
rp
->
r_todisgmt
=
TRUE
;
*
ep
=
'\0'
;
*
ep
=
'\0'
;
...
@@ -1210,65 +1344,81 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
...
@@ -1210,65 +1344,81 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
}
}
rp
->
r_tod
=
gethms
(
dp
,
_
(
"invalid time of day"
),
FALSE
);
rp
->
r_tod
=
gethms
(
dp
,
_
(
"invalid time of day"
),
FALSE
);
ifree
(
dp
);
ifree
(
dp
);
/*
/*
*
* Year work.
*
* Year work.
*/
*/
cp
=
loyearp
;
cp
=
loyearp
;
lp
=
byword
(
cp
,
begin_years
);
lp
=
byword
(
cp
,
begin_years
);
if
(
lp
!=
NULL
)
switch
((
int
)
lp
->
l_value
)
{
if
(
lp
!=
NULL
)
case
YR_MINIMUM
:
switch
((
int
)
lp
->
l_value
)
rp
->
r_loyear
=
INT_MIN
;
{
break
;
case
YR_MINIMUM
:
case
YR_MAXIMUM
:
rp
->
r_loyear
=
INT_MIN
;
rp
->
r_loyear
=
INT_MAX
;
break
;
break
;
case
YR_MAXIMUM
:
default:
/* "cannot happen" */
rp
->
r_loyear
=
INT_MAX
;
(
void
)
fprintf
(
stderr
,
break
;
_
(
"%s: panic: Invalid l_value %d
\n
"
),
default:
/* "cannot happen" */
progname
,
lp
->
l_value
);
(
void
)
fprintf
(
stderr
,
(
void
)
exit
(
EXIT_FAILURE
);
_
(
"%s: panic: Invalid l_value %d
\n
"
),
}
else
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
rp
->
r_loyear
)
!=
1
)
{
progname
,
lp
->
l_value
);
(
void
)
exit
(
EXIT_FAILURE
);
}
else
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
rp
->
r_loyear
)
!=
1
)
{
error
(
_
(
"invalid starting year"
));
error
(
_
(
"invalid starting year"
));
return
;
return
;
}
else
if
(
noise
)
{
}
else
if
(
noise
)
{
if
(
rp
->
r_loyear
<
min_year_representable
)
if
(
rp
->
r_loyear
<
min_year_representable
)
warning
(
_
(
"starting year too low to be represented"
));
warning
(
_
(
"starting year too low to be represented"
));
else
if
(
rp
->
r_loyear
>
max_year_representable
)
else
if
(
rp
->
r_loyear
>
max_year_representable
)
warning
(
_
(
"starting year too high to be represented"
));
warning
(
_
(
"starting year too high to be represented"
));
}
}
cp
=
hiyearp
;
cp
=
hiyearp
;
if
((
lp
=
byword
(
cp
,
end_years
))
!=
NULL
)
switch
((
int
)
lp
->
l_value
)
{
if
((
lp
=
byword
(
cp
,
end_years
))
!=
NULL
)
case
YR_MINIMUM
:
switch
((
int
)
lp
->
l_value
)
rp
->
r_hiyear
=
INT_MIN
;
{
break
;
case
YR_MINIMUM
:
case
YR_MAXIMUM
:
rp
->
r_hiyear
=
INT_MIN
;
rp
->
r_hiyear
=
INT_MAX
;
break
;
break
;
case
YR_MAXIMUM
:
case
YR_ONLY
:
rp
->
r_hiyear
=
INT_MAX
;
rp
->
r_hiyear
=
rp
->
r_loyear
;
break
;
break
;
case
YR_ONLY
:
default:
/* "cannot happen" */
rp
->
r_hiyear
=
rp
->
r_loyear
;
(
void
)
fprintf
(
stderr
,
break
;
_
(
"%s: panic: Invalid l_value %d
\n
"
),
default:
/* "cannot happen" */
progname
,
lp
->
l_value
);
(
void
)
fprintf
(
stderr
,
(
void
)
exit
(
EXIT_FAILURE
);
_
(
"%s: panic: Invalid l_value %d
\n
"
),
}
else
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
rp
->
r_hiyear
)
!=
1
)
{
progname
,
lp
->
l_value
);
(
void
)
exit
(
EXIT_FAILURE
);
}
else
if
(
sscanf
(
cp
,
scheck
(
cp
,
"%d"
),
&
rp
->
r_hiyear
)
!=
1
)
{
error
(
_
(
"invalid ending year"
));
error
(
_
(
"invalid ending year"
));
return
;
return
;
}
else
if
(
noise
)
{
}
else
if
(
noise
)
{
if
(
rp
->
r_loyear
<
min_year_representable
)
if
(
rp
->
r_loyear
<
min_year_representable
)
warning
(
_
(
"ending year too low to be represented"
));
warning
(
_
(
"ending year too low to be represented"
));
else
if
(
rp
->
r_loyear
>
max_year_representable
)
else
if
(
rp
->
r_loyear
>
max_year_representable
)
warning
(
_
(
"ending year too high to be represented"
));
warning
(
_
(
"ending year too high to be represented"
));
}
}
if
(
rp
->
r_loyear
>
rp
->
r_hiyear
)
{
if
(
rp
->
r_loyear
>
rp
->
r_hiyear
)
{
error
(
_
(
"starting year greater than ending year"
));
error
(
_
(
"starting year greater than ending year"
));
return
;
return
;
}
}
if
(
*
typep
==
'\0'
)
if
(
*
typep
==
'\0'
)
rp
->
r_yrtype
=
NULL
;
rp
->
r_yrtype
=
NULL
;
else
{
else
if
(
rp
->
r_loyear
==
rp
->
r_hiyear
)
{
{
if
(
rp
->
r_loyear
==
rp
->
r_hiyear
)
{
error
(
_
(
"typed single year"
));
error
(
_
(
"typed single year"
));
return
;
return
;
}
}
...
@@ -1276,36 +1426,40 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
...
@@ -1276,36 +1426,40 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
}
}
if
(
rp
->
r_loyear
<
min_year
&&
rp
->
r_loyear
>
0
)
if
(
rp
->
r_loyear
<
min_year
&&
rp
->
r_loyear
>
0
)
min_year
=
rp
->
r_loyear
;
min_year
=
rp
->
r_loyear
;
/*
/*
** Day work.
* * Day work. * Accept things such as: * 1 * last-Sunday * Sun<=20 *
** Accept things such as:
* Sun>=7
** 1
*/
** last-Sunday
** Sun<=20
** Sun>=7
*/
dp
=
ecpyalloc
(
dayp
);
dp
=
ecpyalloc
(
dayp
);
if
((
lp
=
byword
(
dp
,
lasts
))
!=
NULL
)
{
if
((
lp
=
byword
(
dp
,
lasts
))
!=
NULL
)
{
rp
->
r_dycode
=
DC_DOWLEQ
;
rp
->
r_dycode
=
DC_DOWLEQ
;
rp
->
r_wday
=
lp
->
l_value
;
rp
->
r_wday
=
lp
->
l_value
;
rp
->
r_dayofmonth
=
len_months
[
1
][
rp
->
r_month
];
rp
->
r_dayofmonth
=
len_months
[
1
][
rp
->
r_month
];
}
else
{
}
else
{
if
((
ep
=
strchr
(
dp
,
'<'
))
!=
0
)
if
((
ep
=
strchr
(
dp
,
'<'
))
!=
0
)
rp
->
r_dycode
=
DC_DOWLEQ
;
rp
->
r_dycode
=
DC_DOWLEQ
;
else
if
((
ep
=
strchr
(
dp
,
'>'
))
!=
0
)
else
if
((
ep
=
strchr
(
dp
,
'>'
))
!=
0
)
rp
->
r_dycode
=
DC_DOWGEQ
;
rp
->
r_dycode
=
DC_DOWGEQ
;
else
{
else
{
ep
=
dp
;
ep
=
dp
;
rp
->
r_dycode
=
DC_DOM
;
rp
->
r_dycode
=
DC_DOM
;
}
}
if
(
rp
->
r_dycode
!=
DC_DOM
)
{
if
(
rp
->
r_dycode
!=
DC_DOM
)
{
*
ep
++
=
0
;
*
ep
++
=
0
;
if
(
*
ep
++
!=
'='
)
{
if
(
*
ep
++
!=
'='
)
{
error
(
_
(
"invalid day of month"
));
error
(
_
(
"invalid day of month"
));
ifree
(
dp
);
ifree
(
dp
);
return
;
return
;
}
}
if
((
lp
=
byword
(
dp
,
wday_names
))
==
NULL
)
{
if
((
lp
=
byword
(
dp
,
wday_names
))
==
NULL
)
{
error
(
_
(
"invalid weekday name"
));
error
(
_
(
"invalid weekday name"
));
ifree
(
dp
);
ifree
(
dp
);
return
;
return
;
...
@@ -1314,62 +1468,70 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
...
@@ -1314,62 +1468,70 @@ static void rulesub(register struct rule *rp, const char *loyearp, const char *h
}
}
if
(
sscanf
(
ep
,
scheck
(
ep
,
"%d"
),
&
rp
->
r_dayofmonth
)
!=
1
||
if
(
sscanf
(
ep
,
scheck
(
ep
,
"%d"
),
&
rp
->
r_dayofmonth
)
!=
1
||
rp
->
r_dayofmonth
<=
0
||
rp
->
r_dayofmonth
<=
0
||
(
rp
->
r_dayofmonth
>
len_months
[
1
][
rp
->
r_month
]))
{
(
rp
->
r_dayofmonth
>
len_months
[
1
][
rp
->
r_month
]))
error
(
_
(
"invalid day of month"
));
{
ifree
(
dp
);
error
(
_
(
"invalid day of month"
));
return
;
ifree
(
dp
);
return
;
}
}
}
}
ifree
(
dp
);
ifree
(
dp
);
}
}
static
void
convert
(
const
long
val
,
char
*
buf
)
static
void
convert
(
const
long
val
,
char
*
buf
)
{
{
register
int
i
;
register
int
i
;
register
long
shift
;
register
long
shift
;
for
(
i
=
0
,
shift
=
24
;
i
<
4
;
++
i
,
shift
-=
8
)
for
(
i
=
0
,
shift
=
24
;
i
<
4
;
++
i
,
shift
-=
8
)
buf
[
i
]
=
val
>>
shift
;
buf
[
i
]
=
val
>>
shift
;
}
}
static
void
puttzcode
(
const
long
val
,
FILE
*
fp
)
static
void
puttzcode
(
const
long
val
,
FILE
*
fp
)
{
{
char
buf
[
4
];
char
buf
[
4
];
convert
(
val
,
buf
);
convert
(
val
,
buf
);
(
void
)
fwrite
((
void
*
)
buf
,
(
size_t
)
sizeof
buf
,
(
size_t
)
1
,
fp
);
(
void
)
fwrite
((
void
*
)
buf
,
(
size_t
)
sizeof
buf
,
(
size_t
)
1
,
fp
);
}
}
static
int
atcomp
(
const
void
*
avp
,
const
void
*
bvp
)
static
int
atcomp
(
const
void
*
avp
,
const
void
*
bvp
)
{
{
if
(((
struct
attype
*
)
avp
)
->
at
<
((
struct
attype
*
)
bvp
)
->
at
)
if
(((
struct
attype
*
)
avp
)
->
at
<
((
struct
attype
*
)
bvp
)
->
at
)
return
-
1
;
return
-
1
;
else
if
(((
struct
attype
*
)
avp
)
->
at
>
((
struct
attype
*
)
bvp
)
->
at
)
else
if
(((
struct
attype
*
)
avp
)
->
at
>
((
struct
attype
*
)
bvp
)
->
at
)
return
1
;
return
1
;
else
return
0
;
else
return
0
;
}
}
static
void
writezone
(
const
char
*
name
)
static
void
writezone
(
const
char
*
name
)
{
{
register
FILE
*
fp
;
register
FILE
*
fp
;
register
int
i
,
j
;
register
int
i
,
static
char
*
fullname
;
j
;
static
struct
tzhead
tzh
;
static
char
*
fullname
;
time_t
ats
[
TZ_MAX_TIMES
];
static
struct
tzhead
tzh
;
unsigned
char
types
[
TZ_MAX_TIMES
];
time_t
ats
[
TZ_MAX_TIMES
];
unsigned
char
types
[
TZ_MAX_TIMES
];
/*
/*
*
* Sort.
*
* Sort.
*/
*/
if
(
timecnt
>
1
)
if
(
timecnt
>
1
)
(
void
)
qsort
((
void
*
)
attypes
,
(
size_t
)
timecnt
,
(
void
)
qsort
((
void
*
)
attypes
,
(
size_t
)
timecnt
,
(
size_t
)
sizeof
*
attypes
,
atcomp
);
(
size_t
)
sizeof
*
attypes
,
atcomp
);
/*
/*
*
* Optimize.
*
* Optimize.
*/
*/
{
{
int
fromi
;
int
fromi
;
int
toi
;
int
toi
;
toi
=
0
;
toi
=
0
;
fromi
=
0
;
fromi
=
0
;
...
@@ -1377,51 +1539,59 @@ static void writezone(const char *name)
...
@@ -1377,51 +1539,59 @@ static void writezone(const char *name)
++
fromi
;
++
fromi
;
if
(
isdsts
[
0
]
==
0
)
if
(
isdsts
[
0
]
==
0
)
while
(
fromi
<
timecnt
&&
attypes
[
fromi
].
type
==
0
)
while
(
fromi
<
timecnt
&&
attypes
[
fromi
].
type
==
0
)
++
fromi
;
/* handled by default rule */
++
fromi
;
/* handled by default rule */
for
(
;
fromi
<
timecnt
;
++
fromi
)
{
for
(;
fromi
<
timecnt
;
++
fromi
)
{
if
(
toi
!=
0
if
(
toi
!=
0
&&
((
attypes
[
fromi
].
at
&&
((
attypes
[
fromi
].
at
+
gmtoffs
[
attypes
[
toi
-
1
].
type
])
+
gmtoffs
[
attypes
[
toi
-
1
].
type
])
<=
(
attypes
[
toi
-
1
].
at
<=
(
attypes
[
toi
-
1
].
at
+
gmtoffs
[
toi
==
1
?
0
+
gmtoffs
[
toi
==
1
?
0
:
attypes
[
toi
-
2
].
type
])))
{
:
attypes
[
toi
-
2
].
type
])))
{
attypes
[
toi
-
1
].
type
=
attypes
[
fromi
].
type
;
attypes
[
toi
-
1
].
type
=
attypes
[
fromi
].
type
;
continue
;
continue
;
}
}
if
(
toi
==
0
||
if
(
toi
==
0
||
attypes
[
toi
-
1
].
type
!=
attypes
[
fromi
].
type
)
attypes
[
toi
-
1
].
type
!=
attypes
[
fromi
].
type
)
attypes
[
toi
++
]
=
attypes
[
fromi
];
attypes
[
toi
++
]
=
attypes
[
fromi
];
}
}
timecnt
=
toi
;
timecnt
=
toi
;
}
}
/*
/*
** Transfer.
* * Transfer.
*/
*/
for
(
i
=
0
;
i
<
timecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
timecnt
;
++
i
)
{
ats
[
i
]
=
attypes
[
i
].
at
;
ats
[
i
]
=
attypes
[
i
].
at
;
types
[
i
]
=
attypes
[
i
].
type
;
types
[
i
]
=
attypes
[
i
].
type
;
}
}
fullname
=
erealloc
(
fullname
,
fullname
=
erealloc
(
fullname
,
(
int
)
(
strlen
(
directory
)
+
1
+
strlen
(
name
)
+
1
));
(
int
)
(
strlen
(
directory
)
+
1
+
strlen
(
name
)
+
1
));
(
void
)
sprintf
(
fullname
,
"%s/%s"
,
directory
,
name
);
(
void
)
sprintf
(
fullname
,
"%s/%s"
,
directory
,
name
);
/*
/*
** Remove old file, if any, to snap links.
* * Remove old file, if any, to snap links.
*/
*/
if
(
!
itsdir
(
fullname
)
&&
remove
(
fullname
)
!=
0
&&
errno
!=
ENOENT
)
{
if
(
!
itsdir
(
fullname
)
&&
remove
(
fullname
)
!=
0
&&
errno
!=
ENOENT
)
{
const
char
*
e
=
strerror
(
errno
);
const
char
*
e
=
strerror
(
errno
);
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't remove %s: %s
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't remove %s: %s
\n
"
),
progname
,
fullname
,
e
);
progname
,
fullname
,
e
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
if
((
fp
=
fopen
(
fullname
,
"wb"
))
==
NULL
)
{
if
((
fp
=
fopen
(
fullname
,
"wb"
))
==
NULL
)
{
if
(
mkdirs
(
fullname
)
!=
0
)
if
(
mkdirs
(
fullname
)
!=
0
)
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
if
((
fp
=
fopen
(
fullname
,
"wb"
))
==
NULL
)
{
if
((
fp
=
fopen
(
fullname
,
"wb"
))
==
NULL
)
{
const
char
*
e
=
strerror
(
errno
);
const
char
*
e
=
strerror
(
errno
);
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't create %s: %s
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't create %s: %s
\n
"
),
progname
,
fullname
,
e
);
progname
,
fullname
,
e
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
}
}
...
@@ -1442,10 +1612,12 @@ static void writezone(const char *name)
...
@@ -1442,10 +1612,12 @@ static void writezone(const char *name)
DO
(
tzh_typecnt
);
DO
(
tzh_typecnt
);
DO
(
tzh_charcnt
);
DO
(
tzh_charcnt
);
#undef DO
#undef DO
for
(
i
=
0
;
i
<
timecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
timecnt
;
++
i
)
{
j
=
leapcnt
;
j
=
leapcnt
;
while
(
--
j
>=
0
)
while
(
--
j
>=
0
)
if
(
ats
[
i
]
>=
trans
[
j
])
{
if
(
ats
[
i
]
>=
trans
[
j
])
{
ats
[
i
]
=
tadd
(
ats
[
i
],
corr
[
j
]);
ats
[
i
]
=
tadd
(
ats
[
i
],
corr
[
j
]);
break
;
break
;
}
}
...
@@ -1453,92 +1625,112 @@ static void writezone(const char *name)
...
@@ -1453,92 +1625,112 @@ static void writezone(const char *name)
}
}
if
(
timecnt
>
0
)
if
(
timecnt
>
0
)
(
void
)
fwrite
((
void
*
)
types
,
(
size_t
)
sizeof
types
[
0
],
(
void
)
fwrite
((
void
*
)
types
,
(
size_t
)
sizeof
types
[
0
],
(
size_t
)
timecnt
,
fp
);
(
size_t
)
timecnt
,
fp
);
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
{
puttzcode
((
long
)
gmtoffs
[
i
],
fp
);
puttzcode
((
long
)
gmtoffs
[
i
],
fp
);
(
void
)
putc
(
isdsts
[
i
],
fp
);
(
void
)
putc
(
isdsts
[
i
],
fp
);
(
void
)
putc
(
abbrinds
[
i
],
fp
);
(
void
)
putc
(
abbrinds
[
i
],
fp
);
}
}
if
(
charcnt
!=
0
)
if
(
charcnt
!=
0
)
(
void
)
fwrite
((
void
*
)
chars
,
(
size_t
)
sizeof
chars
[
0
],
(
void
)
fwrite
((
void
*
)
chars
,
(
size_t
)
sizeof
chars
[
0
],
(
size_t
)
charcnt
,
fp
);
(
size_t
)
charcnt
,
fp
);
for
(
i
=
0
;
i
<
leapcnt
;
++
i
)
{
for
(
i
=
0
;
i
<
leapcnt
;
++
i
)
if
(
roll
[
i
])
{
{
if
(
timecnt
==
0
||
trans
[
i
]
<
ats
[
0
])
{
if
(
roll
[
i
])
{
if
(
timecnt
==
0
||
trans
[
i
]
<
ats
[
0
])
{
j
=
0
;
j
=
0
;
while
(
isdsts
[
j
])
while
(
isdsts
[
j
])
if
(
++
j
>=
typecnt
)
{
if
(
++
j
>=
typecnt
)
{
j
=
0
;
j
=
0
;
break
;
break
;
}
}
}
else
{
}
else
{
j
=
1
;
j
=
1
;
while
(
j
<
timecnt
&&
trans
[
i
]
>=
ats
[
j
])
while
(
j
<
timecnt
&&
trans
[
i
]
>=
ats
[
j
])
++
j
;
++
j
;
j
=
types
[
j
-
1
];
j
=
types
[
j
-
1
];
}
}
puttzcode
((
long
)
tadd
(
trans
[
i
],
-
gmtoffs
[
j
]),
fp
);
puttzcode
((
long
)
tadd
(
trans
[
i
],
-
gmtoffs
[
j
]),
fp
);
}
else
puttzcode
((
long
)
trans
[
i
],
fp
);
}
else
puttzcode
((
long
)
trans
[
i
],
fp
);
puttzcode
((
long
)
corr
[
i
],
fp
);
puttzcode
((
long
)
corr
[
i
],
fp
);
}
}
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
(
void
)
putc
(
ttisstds
[
i
],
fp
);
(
void
)
putc
(
ttisstds
[
i
],
fp
);
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
(
void
)
putc
(
ttisgmts
[
i
],
fp
);
(
void
)
putc
(
ttisgmts
[
i
],
fp
);
if
(
ferror
(
fp
)
||
fclose
(
fp
))
{
if
(
ferror
(
fp
)
||
fclose
(
fp
))
{
(
void
)
fprintf
(
stderr
,
_
(
"%s: Error writing %s
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: Error writing %s
\n
"
),
progname
,
fullname
);
progname
,
fullname
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
}
}
static
void
doabbr
(
char
*
abbr
,
const
char
*
format
,
const
char
*
letters
,
const
int
isdst
)
static
void
doabbr
(
char
*
abbr
,
const
char
*
format
,
const
char
*
letters
,
const
int
isdst
)
{
{
if
(
strchr
(
format
,
'/'
)
==
NULL
)
{
if
(
strchr
(
format
,
'/'
)
==
NULL
)
{
if
(
letters
==
NULL
)
if
(
letters
==
NULL
)
(
void
)
strcpy
(
abbr
,
format
);
(
void
)
strcpy
(
abbr
,
format
);
else
(
void
)
sprintf
(
abbr
,
format
,
letters
);
else
}
else
if
(
isdst
)
(
void
)
sprintf
(
abbr
,
format
,
letters
);
}
else
if
(
isdst
)
(
void
)
strcpy
(
abbr
,
strchr
(
format
,
'/'
)
+
1
);
(
void
)
strcpy
(
abbr
,
strchr
(
format
,
'/'
)
+
1
);
else
{
else
{
(
void
)
strcpy
(
abbr
,
format
);
(
void
)
strcpy
(
abbr
,
format
);
*
strchr
(
abbr
,
'/'
)
=
'\0'
;
*
strchr
(
abbr
,
'/'
)
=
'\0'
;
}
}
}
}
static
void
outzone
(
const
struct
zone
*
zpfirst
,
const
int
zonecount
)
static
void
outzone
(
const
struct
zone
*
zpfirst
,
const
int
zonecount
)
{
{
register
const
struct
zone
*
zp
;
register
const
struct
zone
*
zp
;
register
struct
rule
*
rp
;
register
struct
rule
*
rp
;
register
int
i
,
j
;
register
int
i
,
register
int
usestart
,
useuntil
;
j
;
register
time_t
starttime
=
0
;
register
int
usestart
,
register
time_t
untiltime
=
0
;
useuntil
;
register
long
gmtoff
;
register
time_t
starttime
=
0
;
register
long
stdoff
;
register
time_t
untiltime
=
0
;
register
int
year
;
register
long
gmtoff
;
register
long
startoff
;
register
long
stdoff
;
register
int
startttisstd
;
register
int
year
;
register
int
startttisgmt
;
register
long
startoff
;
register
int
type
;
register
int
startttisstd
;
char
startbuf
[
BUFSIZ
];
register
int
startttisgmt
;
register
int
type
;
char
startbuf
[
BUFSIZ
];
/*
/*
*
* Now. . .finally. . .generate some useful data!
*
* Now. . .finally. . .generate some useful data!
*/
*/
timecnt
=
0
;
timecnt
=
0
;
typecnt
=
0
;
typecnt
=
0
;
charcnt
=
0
;
charcnt
=
0
;
/*
/*
** Thanks to Earl Chew (earl@dnd.icp.nec.com.au)
* * Thanks to Earl Chew (earl@dnd.icp.nec.com.au) * for noting the
** for noting the
need to unconditionally initialize startttisstd.
*
need to unconditionally initialize startttisstd.
*/
*/
startttisstd
=
FALSE
;
startttisstd
=
FALSE
;
startttisgmt
=
FALSE
;
startttisgmt
=
FALSE
;
for
(
i
=
0
;
i
<
zonecount
;
++
i
)
{
for
(
i
=
0
;
i
<
zonecount
;
++
i
)
{
/*
/*
*
* A guess that may well be corrected later.
*
* A guess that may well be corrected later.
*/
*/
stdoff
=
0
;
stdoff
=
0
;
zp
=
&
zpfirst
[
i
];
zp
=
&
zpfirst
[
i
];
usestart
=
i
>
0
&&
(
zp
-
1
)
->
z_untiltime
>
min_time
;
usestart
=
i
>
0
&&
(
zp
-
1
)
->
z_untiltime
>
min_time
;
...
@@ -1549,134 +1741,154 @@ static void outzone(const struct zone *zpfirst, const int zonecount)
...
@@ -1549,134 +1741,154 @@ static void outzone(const struct zone *zpfirst, const int zonecount)
eat
(
zp
->
z_filename
,
zp
->
z_linenum
);
eat
(
zp
->
z_filename
,
zp
->
z_linenum
);
*
startbuf
=
'\0'
;
*
startbuf
=
'\0'
;
startoff
=
zp
->
z_gmtoff
;
startoff
=
zp
->
z_gmtoff
;
if
(
zp
->
z_nrules
==
0
)
{
if
(
zp
->
z_nrules
==
0
)
{
stdoff
=
zp
->
z_stdoff
;
stdoff
=
zp
->
z_stdoff
;
doabbr
(
startbuf
,
zp
->
z_format
,
doabbr
(
startbuf
,
zp
->
z_format
,
(
char
*
)
NULL
,
stdoff
!=
0
);
(
char
*
)
NULL
,
stdoff
!=
0
);
type
=
addtype
(
oadd
(
zp
->
z_gmtoff
,
stdoff
),
type
=
addtype
(
oadd
(
zp
->
z_gmtoff
,
stdoff
),
startbuf
,
stdoff
!=
0
,
startttisstd
,
startbuf
,
stdoff
!=
0
,
startttisstd
,
startttisgmt
);
startttisgmt
);
if
(
usestart
)
{
if
(
usestart
)
{
addtt
(
starttime
,
type
);
addtt
(
starttime
,
type
);
usestart
=
FALSE
;
usestart
=
FALSE
;
}
else
if
(
stdoff
!=
0
)
addtt
(
min_time
,
type
);
}
else
for
(
year
=
min_year
;
year
<=
max_year
;
++
year
)
{
if
(
useuntil
&&
year
>
zp
->
z_untilrule
.
r_hiyear
)
break
;
/*
** Mark which rules to do in the current year.
** For those to do, calculate rpytime(rp, year);
*/
for
(
j
=
0
;
j
<
zp
->
z_nrules
;
++
j
)
{
rp
=
&
zp
->
z_rules
[
j
];
eats
(
zp
->
z_filename
,
zp
->
z_linenum
,
rp
->
r_filename
,
rp
->
r_linenum
);
rp
->
r_todo
=
year
>=
rp
->
r_loyear
&&
year
<=
rp
->
r_hiyear
&&
yearistype
(
year
,
rp
->
r_yrtype
);
if
(
rp
->
r_todo
)
rp
->
r_temp
=
rpytime
(
rp
,
year
);
}
}
for
(
;
;
)
{
else
if
(
stdoff
!=
0
)
register
int
k
;
addtt
(
min_time
,
type
);
register
time_t
jtime
,
ktime
=
0
;
}
register
long
offset
;
else
char
buf
[
BUFSIZ
];
for
(
year
=
min_year
;
year
<=
max_year
;
++
year
)
{
if
(
useuntil
&&
year
>
zp
->
z_untilrule
.
r_hiyear
)
break
;
if
(
useuntil
)
{
/*
** Turn untiltime into UTC
** assuming the current gmtoff and
** stdoff values.
*/
untiltime
=
zp
->
z_untiltime
;
if
(
!
zp
->
z_untilrule
.
r_todisgmt
)
untiltime
=
tadd
(
untiltime
,
-
gmtoff
);
if
(
!
zp
->
z_untilrule
.
r_todisstd
)
untiltime
=
tadd
(
untiltime
,
-
stdoff
);
}
/*
/*
** Find the rule (of those to do, if any)
* * Mark which rules to do in the current year. * For
** that takes effect earliest in the year.
* those to do, calculate rpytime(rp, year);
*/
*/
k
=
-
1
;
for
(
j
=
0
;
j
<
zp
->
z_nrules
;
++
j
)
for
(
j
=
0
;
j
<
zp
->
z_nrules
;
++
j
)
{
{
rp
=
&
zp
->
z_rules
[
j
];
rp
=
&
zp
->
z_rules
[
j
];
if
(
!
rp
->
r_todo
)
continue
;
eats
(
zp
->
z_filename
,
zp
->
z_linenum
,
eats
(
zp
->
z_filename
,
zp
->
z_linenum
,
rp
->
r_filename
,
rp
->
r_linenum
);
rp
->
r_filename
,
rp
->
r_linenum
);
offset
=
rp
->
r_todisgmt
?
0
:
gmtoff
;
rp
->
r_todo
=
year
>=
rp
->
r_loyear
&&
if
(
!
rp
->
r_todisstd
)
year
<=
rp
->
r_hiyear
&&
offset
=
oadd
(
offset
,
stdoff
);
yearistype
(
year
,
rp
->
r_yrtype
);
jtime
=
rp
->
r_temp
;
if
(
rp
->
r_todo
)
if
(
jtime
==
min_time
||
rp
->
r_temp
=
rpytime
(
rp
,
year
);
jtime
==
max_time
)
continue
;
jtime
=
tadd
(
jtime
,
-
offset
);
if
(
k
<
0
||
jtime
<
ktime
)
{
k
=
j
;
ktime
=
jtime
;
}
}
}
if
(
k
<
0
)
for
(;;)
break
;
/* go on to next year */
{
rp
=
&
zp
->
z_rules
[
k
];
register
int
k
;
rp
->
r_todo
=
FALSE
;
register
time_t
jtime
,
if
(
useuntil
&&
ktime
>=
untiltime
)
ktime
=
0
;
break
;
register
long
offset
;
stdoff
=
rp
->
r_stdoff
;
char
buf
[
BUFSIZ
];
if
(
usestart
&&
ktime
==
starttime
)
usestart
=
FALSE
;
if
(
useuntil
)
if
(
usestart
)
{
{
if
(
ktime
<
starttime
)
{
/*
startoff
=
oadd
(
zp
->
z_gmtoff
,
* * Turn untiltime into UTC * assuming the
stdoff
);
* current gmtoff and * stdoff values.
doabbr
(
startbuf
,
zp
->
z_format
,
*/
rp
->
r_abbrvar
,
untiltime
=
zp
->
z_untiltime
;
rp
->
r_stdoff
!=
0
);
if
(
!
zp
->
z_untilrule
.
r_todisgmt
)
continue
;
untiltime
=
tadd
(
untiltime
,
-
gmtoff
);
if
(
!
zp
->
z_untilrule
.
r_todisstd
)
untiltime
=
tadd
(
untiltime
,
-
stdoff
);
}
}
if
(
*
startbuf
==
'\0'
&&
startoff
==
oadd
(
zp
->
z_gmtoff
,
/*
stdoff
))
{
* * Find the rule (of those to do, if any) * that
doabbr
(
startbuf
,
zp
->
z_format
,
* takes effect earliest in the year.
rp
->
r_abbrvar
,
*/
rp
->
r_stdoff
!=
0
);
k
=
-
1
;
for
(
j
=
0
;
j
<
zp
->
z_nrules
;
++
j
)
{
rp
=
&
zp
->
z_rules
[
j
];
if
(
!
rp
->
r_todo
)
continue
;
eats
(
zp
->
z_filename
,
zp
->
z_linenum
,
rp
->
r_filename
,
rp
->
r_linenum
);
offset
=
rp
->
r_todisgmt
?
0
:
gmtoff
;
if
(
!
rp
->
r_todisstd
)
offset
=
oadd
(
offset
,
stdoff
);
jtime
=
rp
->
r_temp
;
if
(
jtime
==
min_time
||
jtime
==
max_time
)
continue
;
jtime
=
tadd
(
jtime
,
-
offset
);
if
(
k
<
0
||
jtime
<
ktime
)
{
k
=
j
;
ktime
=
jtime
;
}
}
if
(
k
<
0
)
break
;
/* go on to next year */
rp
=
&
zp
->
z_rules
[
k
];
rp
->
r_todo
=
FALSE
;
if
(
useuntil
&&
ktime
>=
untiltime
)
break
;
stdoff
=
rp
->
r_stdoff
;
if
(
usestart
&&
ktime
==
starttime
)
usestart
=
FALSE
;
if
(
usestart
)
{
if
(
ktime
<
starttime
)
{
startoff
=
oadd
(
zp
->
z_gmtoff
,
stdoff
);
doabbr
(
startbuf
,
zp
->
z_format
,
rp
->
r_abbrvar
,
rp
->
r_stdoff
!=
0
);
continue
;
}
if
(
*
startbuf
==
'\0'
&&
startoff
==
oadd
(
zp
->
z_gmtoff
,
stdoff
))
{
doabbr
(
startbuf
,
zp
->
z_format
,
rp
->
r_abbrvar
,
rp
->
r_stdoff
!=
0
);
}
}
}
eats
(
zp
->
z_filename
,
zp
->
z_linenum
,
rp
->
r_filename
,
rp
->
r_linenum
);
doabbr
(
buf
,
zp
->
z_format
,
rp
->
r_abbrvar
,
rp
->
r_stdoff
!=
0
);
offset
=
oadd
(
zp
->
z_gmtoff
,
rp
->
r_stdoff
);
type
=
addtype
(
offset
,
buf
,
rp
->
r_stdoff
!=
0
,
rp
->
r_todisstd
,
rp
->
r_todisgmt
);
addtt
(
ktime
,
type
);
}
}
eats
(
zp
->
z_filename
,
zp
->
z_linenum
,
rp
->
r_filename
,
rp
->
r_linenum
);
doabbr
(
buf
,
zp
->
z_format
,
rp
->
r_abbrvar
,
rp
->
r_stdoff
!=
0
);
offset
=
oadd
(
zp
->
z_gmtoff
,
rp
->
r_stdoff
);
type
=
addtype
(
offset
,
buf
,
rp
->
r_stdoff
!=
0
,
rp
->
r_todisstd
,
rp
->
r_todisgmt
);
addtt
(
ktime
,
type
);
}
}
}
if
(
usestart
)
if
(
usestart
)
{
{
if
(
*
startbuf
==
'\0'
&&
if
(
*
startbuf
==
'\0'
&&
zp
->
z_format
!=
NULL
&&
zp
->
z_format
!=
NULL
&&
strchr
(
zp
->
z_format
,
'%'
)
==
NULL
&&
strchr
(
zp
->
z_format
,
'%'
)
==
NULL
&&
strchr
(
zp
->
z_format
,
'/'
)
==
NULL
)
strchr
(
zp
->
z_format
,
'/'
)
==
NULL
)
(
void
)
strcpy
(
startbuf
,
zp
->
z_format
);
(
void
)
strcpy
(
startbuf
,
zp
->
z_format
);
eat
(
zp
->
z_filename
,
zp
->
z_linenum
);
eat
(
zp
->
z_filename
,
zp
->
z_linenum
);
if
(
*
startbuf
==
'\0'
)
if
(
*
startbuf
==
'\0'
)
error
(
_
(
"can't determine time zone abbreviation to use just after until time"
));
error
(
_
(
"can't determine time zone abbreviation to use just after until time"
));
else
addtt
(
starttime
,
else
addtype
(
startoff
,
startbuf
,
addtt
(
starttime
,
startoff
!=
zp
->
z_gmtoff
,
addtype
(
startoff
,
startbuf
,
startttisstd
,
startoff
!=
zp
->
z_gmtoff
,
startttisgmt
));
startttisstd
,
startttisgmt
));
}
}
/*
/*
** Now we may get to set starttime for the next zone line.
* * Now we may get to set starttime for the next zone line.
*/
*/
if
(
useuntil
)
{
if
(
useuntil
)
{
startttisstd
=
zp
->
z_untilrule
.
r_todisstd
;
startttisstd
=
zp
->
z_untilrule
.
r_todisstd
;
startttisgmt
=
zp
->
z_untilrule
.
r_todisgmt
;
startttisgmt
=
zp
->
z_untilrule
.
r_todisgmt
;
starttime
=
zp
->
z_untiltime
;
starttime
=
zp
->
z_untiltime
;
...
@@ -1689,10 +1901,12 @@ error(_("can't determine time zone abbreviation to use just after until time"));
...
@@ -1689,10 +1901,12 @@ error(_("can't determine time zone abbreviation to use just after until time"));
writezone
(
zpfirst
->
z_name
);
writezone
(
zpfirst
->
z_name
);
}
}
static
void
addtt
(
const
time_t
starttime
,
int
type
)
static
void
addtt
(
const
time_t
starttime
,
int
type
)
{
{
if
(
starttime
<=
min_time
||
if
(
starttime
<=
min_time
||
(
timecnt
==
1
&&
attypes
[
0
].
at
<
min_time
))
{
(
timecnt
==
1
&&
attypes
[
0
].
at
<
min_time
))
{
gmtoffs
[
0
]
=
gmtoffs
[
type
];
gmtoffs
[
0
]
=
gmtoffs
[
type
];
isdsts
[
0
]
=
isdsts
[
type
];
isdsts
[
0
]
=
isdsts
[
type
];
ttisstds
[
0
]
=
ttisstds
[
type
];
ttisstds
[
0
]
=
ttisstds
[
type
];
...
@@ -1705,7 +1919,8 @@ static void addtt(const time_t starttime, int type)
...
@@ -1705,7 +1919,8 @@ static void addtt(const time_t starttime, int type)
timecnt
=
0
;
timecnt
=
0
;
type
=
0
;
type
=
0
;
}
}
if
(
timecnt
>=
TZ_MAX_TIMES
)
{
if
(
timecnt
>=
TZ_MAX_TIMES
)
{
error
(
_
(
"too many transitions?!"
));
error
(
_
(
"too many transitions?!"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
...
@@ -1714,38 +1929,47 @@ static void addtt(const time_t starttime, int type)
...
@@ -1714,38 +1929,47 @@ static void addtt(const time_t starttime, int type)
++
timecnt
;
++
timecnt
;
}
}
static
int
addtype
(
const
long
gmtoff
,
const
char
*
abbr
,
const
int
isdst
,
const
int
ttisstd
,
const
int
ttisgmt
)
static
int
addtype
(
const
long
gmtoff
,
const
char
*
abbr
,
const
int
isdst
,
const
int
ttisstd
,
const
int
ttisgmt
)
{
{
register
int
i
,
j
;
register
int
i
,
j
;
if
(
isdst
!=
TRUE
&&
isdst
!=
FALSE
)
{
if
(
isdst
!=
TRUE
&&
isdst
!=
FALSE
)
{
error
(
_
(
"internal error - addtype called with bad isdst"
));
error
(
_
(
"internal error - addtype called with bad isdst"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
if
(
ttisstd
!=
TRUE
&&
ttisstd
!=
FALSE
)
{
if
(
ttisstd
!=
TRUE
&&
ttisstd
!=
FALSE
)
{
error
(
_
(
"internal error - addtype called with bad ttisstd"
));
error
(
_
(
"internal error - addtype called with bad ttisstd"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
if
(
ttisgmt
!=
TRUE
&&
ttisgmt
!=
FALSE
)
{
if
(
ttisgmt
!=
TRUE
&&
ttisgmt
!=
FALSE
)
{
error
(
_
(
"internal error - addtype called with bad ttisgmt"
));
error
(
_
(
"internal error - addtype called with bad ttisgmt"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
/*
/*
** See if there's already an entry for this zone type.
* * See if there's already an entry for this zone type. * If so, just
** If so, just return its index.
* return its index.
*/
*/
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
{
for
(
i
=
0
;
i
<
typecnt
;
++
i
)
{
if
(
gmtoff
==
gmtoffs
[
i
]
&&
isdst
==
isdsts
[
i
]
&&
if
(
gmtoff
==
gmtoffs
[
i
]
&&
isdst
==
isdsts
[
i
]
&&
strcmp
(
abbr
,
&
chars
[
abbrinds
[
i
]])
==
0
&&
strcmp
(
abbr
,
&
chars
[
abbrinds
[
i
]])
==
0
&&
ttisstd
==
ttisstds
[
i
]
&&
ttisstd
==
ttisstds
[
i
]
&&
ttisgmt
==
ttisgmts
[
i
])
ttisgmt
==
ttisgmts
[
i
])
return
i
;
return
i
;
}
}
/*
/*
** There isn't one; add a new one, unless there are already too
* * There isn't one; add a new one, unless there are already too *
** many.
* many.
*/
*/
if
(
typecnt
>=
TZ_MAX_TYPES
)
{
if
(
typecnt
>=
TZ_MAX_TYPES
)
{
error
(
_
(
"too many local time types"
));
error
(
_
(
"too many local time types"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
...
@@ -1764,24 +1988,31 @@ static int addtype(const long gmtoff, const char *abbr, const int isdst, const i
...
@@ -1764,24 +1988,31 @@ static int addtype(const long gmtoff, const char *abbr, const int isdst, const i
return
i
;
return
i
;
}
}
static
void
leapadd
(
const
time_t
t
,
const
int
positive
,
const
int
rolling
,
int
count
)
static
void
leapadd
(
const
time_t
t
,
const
int
positive
,
const
int
rolling
,
int
count
)
{
{
register
int
i
,
j
;
register
int
i
,
j
;
if
(
leapcnt
+
(
positive
?
count
:
1
)
>
TZ_MAX_LEAPS
)
{
if
(
leapcnt
+
(
positive
?
count
:
1
)
>
TZ_MAX_LEAPS
)
{
error
(
_
(
"too many leap seconds"
));
error
(
_
(
"too many leap seconds"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
for
(
i
=
0
;
i
<
leapcnt
;
++
i
)
for
(
i
=
0
;
i
<
leapcnt
;
++
i
)
if
(
t
<=
trans
[
i
])
{
if
(
t
<=
trans
[
i
])
if
(
t
==
trans
[
i
])
{
{
if
(
t
==
trans
[
i
])
{
error
(
_
(
"repeated leap second moment"
));
error
(
_
(
"repeated leap second moment"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
break
;
break
;
}
}
do
{
do
for
(
j
=
leapcnt
;
j
>
i
;
--
j
)
{
{
for
(
j
=
leapcnt
;
j
>
i
;
--
j
)
{
trans
[
j
]
=
trans
[
j
-
1
];
trans
[
j
]
=
trans
[
j
-
1
];
corr
[
j
]
=
corr
[
j
-
1
];
corr
[
j
]
=
corr
[
j
-
1
];
roll
[
j
]
=
roll
[
j
-
1
];
roll
[
j
]
=
roll
[
j
-
1
];
...
@@ -1793,50 +2024,57 @@ static void leapadd(const time_t t, const int positive, const int rolling, int c
...
@@ -1793,50 +2024,57 @@ static void leapadd(const time_t t, const int positive, const int rolling, int c
}
while
(
positive
&&
--
count
!=
0
);
}
while
(
positive
&&
--
count
!=
0
);
}
}
static
void
adjleap
(
void
)
static
void
adjleap
(
void
)
{
{
register
int
i
;
register
int
i
;
register
long
last
=
0
;
register
long
last
=
0
;
/*
/*
** propagate leap seconds forward
* * propagate leap seconds forward
*/
*/
for
(
i
=
0
;
i
<
leapcnt
;
++
i
)
{
for
(
i
=
0
;
i
<
leapcnt
;
++
i
)
{
trans
[
i
]
=
tadd
(
trans
[
i
],
last
);
trans
[
i
]
=
tadd
(
trans
[
i
],
last
);
last
=
corr
[
i
]
+=
last
;
last
=
corr
[
i
]
+=
last
;
}
}
}
}
static
int
yearistype
(
const
int
year
,
const
char
*
type
)
static
int
yearistype
(
const
int
year
,
const
char
*
type
)
{
{
static
char
*
buf
;
static
char
*
buf
;
int
result
;
int
result
;
if
(
type
==
NULL
||
*
type
==
'\0'
)
if
(
type
==
NULL
||
*
type
==
'\0'
)
return
TRUE
;
return
TRUE
;
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
strlen
(
yitcommand
)
+
strlen
(
type
)));
buf
=
erealloc
(
buf
,
(
int
)
(
132
+
strlen
(
yitcommand
)
+
strlen
(
type
)));
(
void
)
sprintf
(
buf
,
"%s %d %s"
,
yitcommand
,
year
,
type
);
(
void
)
sprintf
(
buf
,
"%s %d %s"
,
yitcommand
,
year
,
type
);
result
=
system
(
buf
);
result
=
system
(
buf
);
if
(
WIFEXITED
(
result
))
switch
(
WEXITSTATUS
(
result
))
{
if
(
WIFEXITED
(
result
))
case
0
:
switch
(
WEXITSTATUS
(
result
))
return
TRUE
;
{
case
1
:
case
0
:
return
FALSE
;
return
TRUE
;
}
case
1
:
return
FALSE
;
}
error
(
_
(
"Wild result from command execution"
));
error
(
_
(
"Wild result from command execution"
));
(
void
)
fprintf
(
stderr
,
_
(
"%s: command was '%s', result was %d
\n
"
),
(
void
)
fprintf
(
stderr
,
_
(
"%s: command was '%s', result was %d
\n
"
),
progname
,
buf
,
result
);
progname
,
buf
,
result
);
for
(
;
;
)
for
(
;;
)
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
static
int
lowerit
(
int
a
)
static
int
lowerit
(
int
a
)
{
{
a
=
(
unsigned
char
)
a
;
a
=
(
unsigned
char
)
a
;
return
(
isascii
(
a
)
&&
isupper
(
a
))
?
tolower
(
a
)
:
a
;
return
(
isascii
(
a
)
&&
isupper
(
a
))
?
tolower
(
a
)
:
a
;
}
}
static
int
ciequal
(
register
const
char
*
ap
,
register
const
char
*
bp
)
static
int
ciequal
(
register
const
char
*
ap
,
register
const
char
*
bp
)
{
{
while
(
lowerit
(
*
ap
)
==
lowerit
(
*
bp
++
))
while
(
lowerit
(
*
ap
)
==
lowerit
(
*
bp
++
))
if
(
*
ap
++
==
'\0'
)
if
(
*
ap
++
==
'\0'
)
...
@@ -1844,71 +2082,83 @@ static int ciequal(register const char *ap, register const char *bp)
...
@@ -1844,71 +2082,83 @@ static int ciequal(register const char *ap, register const char *bp)
return
FALSE
;
return
FALSE
;
}
}
static
int
itsabbr
(
register
const
char
*
abbr
,
register
const
char
*
word
)
static
int
itsabbr
(
register
const
char
*
abbr
,
register
const
char
*
word
)
{
{
if
(
lowerit
(
*
abbr
)
!=
lowerit
(
*
word
))
if
(
lowerit
(
*
abbr
)
!=
lowerit
(
*
word
))
return
FALSE
;
return
FALSE
;
++
word
;
++
word
;
while
(
*++
abbr
!=
'\0'
)
while
(
*++
abbr
!=
'\0'
)
do
{
do
{
if
(
*
word
==
'\0'
)
if
(
*
word
==
'\0'
)
return
FALSE
;
return
FALSE
;
}
while
(
lowerit
(
*
word
++
)
!=
lowerit
(
*
abbr
));
}
while
(
lowerit
(
*
word
++
)
!=
lowerit
(
*
abbr
));
return
TRUE
;
return
TRUE
;
}
}
static
const
struct
lookup
*
byword
(
register
const
char
*
word
,
register
const
struct
lookup
*
table
)
static
const
struct
lookup
*
byword
(
register
const
char
*
word
,
register
const
struct
lookup
*
table
)
{
{
register
const
struct
lookup
*
foundlp
;
register
const
struct
lookup
*
foundlp
;
register
const
struct
lookup
*
lp
;
register
const
struct
lookup
*
lp
;
if
(
word
==
NULL
||
table
==
NULL
)
if
(
word
==
NULL
||
table
==
NULL
)
return
NULL
;
return
NULL
;
/*
/*
*
* Look for exact match.
*
* Look for exact match.
*/
*/
for
(
lp
=
table
;
lp
->
l_word
!=
NULL
;
++
lp
)
for
(
lp
=
table
;
lp
->
l_word
!=
NULL
;
++
lp
)
if
(
ciequal
(
word
,
lp
->
l_word
))
if
(
ciequal
(
word
,
lp
->
l_word
))
return
lp
;
return
lp
;
/*
/*
*
* Look for inexact match.
*
* Look for inexact match.
*/
*/
foundlp
=
NULL
;
foundlp
=
NULL
;
for
(
lp
=
table
;
lp
->
l_word
!=
NULL
;
++
lp
)
for
(
lp
=
table
;
lp
->
l_word
!=
NULL
;
++
lp
)
if
(
itsabbr
(
word
,
lp
->
l_word
))
{
if
(
itsabbr
(
word
,
lp
->
l_word
))
{
if
(
foundlp
==
NULL
)
if
(
foundlp
==
NULL
)
foundlp
=
lp
;
foundlp
=
lp
;
else
return
NULL
;
/* multiple inexact matches */
else
return
NULL
;
/* multiple inexact matches */
}
}
return
foundlp
;
return
foundlp
;
}
}
static
char
**
getfields
(
register
char
*
cp
)
static
char
**
getfields
(
register
char
*
cp
)
{
{
register
char
*
dp
;
register
char
*
dp
;
register
char
**
array
;
register
char
**
array
;
register
int
nsubs
;
register
int
nsubs
;
if
(
cp
==
NULL
)
if
(
cp
==
NULL
)
return
NULL
;
return
NULL
;
array
=
(
char
**
)
(
void
*
)
array
=
(
char
**
)
(
void
*
)
emalloc
((
int
)
((
strlen
(
cp
)
+
1
)
*
sizeof
*
array
));
emalloc
((
int
)
((
strlen
(
cp
)
+
1
)
*
sizeof
*
array
));
nsubs
=
0
;
nsubs
=
0
;
for
(
;
;
)
{
for
(;;)
{
while
(
isascii
(
*
cp
)
&&
isspace
((
unsigned
char
)
*
cp
))
while
(
isascii
(
*
cp
)
&&
isspace
((
unsigned
char
)
*
cp
))
++
cp
;
++
cp
;
if
(
*
cp
==
'\0'
||
*
cp
==
'#'
)
if
(
*
cp
==
'\0'
||
*
cp
==
'#'
)
break
;
break
;
array
[
nsubs
++
]
=
dp
=
cp
;
array
[
nsubs
++
]
=
dp
=
cp
;
do
{
do
{
if
((
*
dp
=
*
cp
++
)
!=
'"'
)
if
((
*
dp
=
*
cp
++
)
!=
'"'
)
++
dp
;
++
dp
;
else
while
((
*
dp
=
*
cp
++
)
!=
'"'
)
else
if
(
*
dp
!=
'\0'
)
while
((
*
dp
=
*
cp
++
)
!=
'"'
)
++
dp
;
if
(
*
dp
!=
'\0'
)
else
error
(
_
(
"Odd number of quotation marks"
));
++
dp
;
else
error
(
_
(
"Odd number of quotation marks"
));
}
while
(
*
cp
!=
'\0'
&&
*
cp
!=
'#'
&&
}
while
(
*
cp
!=
'\0'
&&
*
cp
!=
'#'
&&
(
!
isascii
(
*
cp
)
||
!
isspace
((
unsigned
char
)
*
cp
)));
(
!
isascii
(
*
cp
)
||
!
isspace
((
unsigned
char
)
*
cp
)));
if
(
isascii
(
*
cp
)
&&
isspace
((
unsigned
char
)
*
cp
))
if
(
isascii
(
*
cp
)
&&
isspace
((
unsigned
char
)
*
cp
))
++
cp
;
++
cp
;
*
dp
=
'\0'
;
*
dp
=
'\0'
;
...
@@ -1917,28 +2167,32 @@ static char **getfields(register char *cp)
...
@@ -1917,28 +2167,32 @@ static char **getfields(register char *cp)
return
array
;
return
array
;
}
}
static
long
oadd
(
const
long
t1
,
const
long
t2
)
static
long
oadd
(
const
long
t1
,
const
long
t2
)
{
{
register
long
t
;
register
long
t
;
t
=
t1
+
t2
;
t
=
t1
+
t2
;
if
((
t2
>
0
&&
t
<=
t1
)
||
(
t2
<
0
&&
t
>=
t1
))
{
if
((
t2
>
0
&&
t
<=
t1
)
||
(
t2
<
0
&&
t
>=
t1
))
{
error
(
_
(
"time overflow"
));
error
(
_
(
"time overflow"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
return
t
;
return
t
;
}
}
static
time_t
tadd
(
const
time_t
t1
,
const
long
t2
)
static
time_t
tadd
(
const
time_t
t1
,
const
long
t2
)
{
{
register
time_t
t
;
register
time_t
t
;
if
(
t1
==
max_time
&&
t2
>
0
)
if
(
t1
==
max_time
&&
t2
>
0
)
return
max_time
;
return
max_time
;
if
(
t1
==
min_time
&&
t2
<
0
)
if
(
t1
==
min_time
&&
t2
<
0
)
return
min_time
;
return
min_time
;
t
=
t1
+
t2
;
t
=
t1
+
t2
;
if
((
t2
>
0
&&
t
<=
t1
)
||
(
t2
<
0
&&
t
>=
t1
))
{
if
((
t2
>
0
&&
t
<=
t1
)
||
(
t2
<
0
&&
t
>=
t1
))
{
error
(
_
(
"time overflow"
));
error
(
_
(
"time overflow"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
...
@@ -1950,11 +2204,14 @@ static time_t tadd(const time_t t1, const long t2)
...
@@ -1950,11 +2204,14 @@ static time_t tadd(const time_t t1, const long t2)
** 1970, 00:00 LOCAL time - in that year that the rule refers to.
** 1970, 00:00 LOCAL time - in that year that the rule refers to.
*/
*/
static
time_t
rpytime
(
register
const
struct
rule
*
rp
,
register
const
int
wantedy
)
static
time_t
rpytime
(
register
const
struct
rule
*
rp
,
register
const
int
wantedy
)
{
{
register
int
y
,
m
,
i
;
register
int
y
,
register
long
dayoff
;
/* with a nod to Margaret O. */
m
,
register
time_t
t
;
i
;
register
long
dayoff
;
/* with a nod to Margaret O. */
register
time_t
t
;
if
(
wantedy
==
INT_MIN
)
if
(
wantedy
==
INT_MIN
)
return
min_time
;
return
min_time
;
...
@@ -1963,60 +2220,74 @@ static time_t rpytime(register const struct rule *rp, register const int wantedy
...
@@ -1963,60 +2220,74 @@ static time_t rpytime(register const struct rule *rp, register const int wantedy
dayoff
=
0
;
dayoff
=
0
;
m
=
TM_JANUARY
;
m
=
TM_JANUARY
;
y
=
EPOCH_YEAR
;
y
=
EPOCH_YEAR
;
while
(
wantedy
!=
y
)
{
while
(
wantedy
!=
y
)
if
(
wantedy
>
y
)
{
{
if
(
wantedy
>
y
)
{
i
=
len_years
[
isleap
(
y
)];
i
=
len_years
[
isleap
(
y
)];
++
y
;
++
y
;
}
else
{
}
else
{
--
y
;
--
y
;
i
=
-
len_years
[
isleap
(
y
)];
i
=
-
len_years
[
isleap
(
y
)];
}
}
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
}
}
while
(
m
!=
rp
->
r_month
)
{
while
(
m
!=
rp
->
r_month
)
{
i
=
len_months
[
isleap
(
y
)][
m
];
i
=
len_months
[
isleap
(
y
)][
m
];
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
++
m
;
++
m
;
}
}
i
=
rp
->
r_dayofmonth
;
i
=
rp
->
r_dayofmonth
;
if
(
m
==
TM_FEBRUARY
&&
i
==
29
&&
!
isleap
(
y
))
{
if
(
m
==
TM_FEBRUARY
&&
i
==
29
&&
!
isleap
(
y
))
{
if
(
rp
->
r_dycode
==
DC_DOWLEQ
)
if
(
rp
->
r_dycode
==
DC_DOWLEQ
)
--
i
;
--
i
;
else
{
else
{
error
(
_
(
"use of 2/29 in non leap-year"
));
error
(
_
(
"use of 2/29 in non leap-year"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
}
}
--
i
;
--
i
;
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
dayoff
=
oadd
(
dayoff
,
eitol
(
i
));
if
(
rp
->
r_dycode
==
DC_DOWGEQ
||
rp
->
r_dycode
==
DC_DOWLEQ
)
{
if
(
rp
->
r_dycode
==
DC_DOWGEQ
||
rp
->
r_dycode
==
DC_DOWLEQ
)
register
long
wday
;
{
register
long
wday
;
#define LDAYSPERWEEK ((long) DAYSPERWEEK)
#define LDAYSPERWEEK ((long) DAYSPERWEEK)
wday
=
eitol
(
EPOCH_WDAY
);
wday
=
eitol
(
EPOCH_WDAY
);
/*
/*
*
* Don't trust mod of negative numbers.
*
* Don't trust mod of negative numbers.
*/
*/
if
(
dayoff
>=
0
)
if
(
dayoff
>=
0
)
wday
=
(
wday
+
dayoff
)
%
LDAYSPERWEEK
;
wday
=
(
wday
+
dayoff
)
%
LDAYSPERWEEK
;
else
{
else
{
wday
-=
((
-
dayoff
)
%
LDAYSPERWEEK
);
wday
-=
((
-
dayoff
)
%
LDAYSPERWEEK
);
if
(
wday
<
0
)
if
(
wday
<
0
)
wday
+=
LDAYSPERWEEK
;
wday
+=
LDAYSPERWEEK
;
}
}
while
(
wday
!=
eitol
(
rp
->
r_wday
))
while
(
wday
!=
eitol
(
rp
->
r_wday
))
if
(
rp
->
r_dycode
==
DC_DOWGEQ
)
{
if
(
rp
->
r_dycode
==
DC_DOWGEQ
)
{
dayoff
=
oadd
(
dayoff
,
(
long
)
1
);
dayoff
=
oadd
(
dayoff
,
(
long
)
1
);
if
(
++
wday
>=
LDAYSPERWEEK
)
if
(
++
wday
>=
LDAYSPERWEEK
)
wday
=
0
;
wday
=
0
;
++
i
;
++
i
;
}
else
{
}
else
{
dayoff
=
oadd
(
dayoff
,
(
long
)
-
1
);
dayoff
=
oadd
(
dayoff
,
(
long
)
-
1
);
if
(
--
wday
<
0
)
if
(
--
wday
<
0
)
wday
=
LDAYSPERWEEK
-
1
;
wday
=
LDAYSPERWEEK
-
1
;
--
i
;
--
i
;
}
}
if
(
i
<
0
||
i
>=
len_months
[
isleap
(
y
)][
m
])
{
if
(
i
<
0
||
i
>=
len_months
[
isleap
(
y
)][
m
])
{
error
(
_
(
"no day in month matches rule"
));
error
(
_
(
"no day in month matches rule"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
...
@@ -2027,16 +2298,19 @@ static time_t rpytime(register const struct rule *rp, register const int wantedy
...
@@ -2027,16 +2298,19 @@ static time_t rpytime(register const struct rule *rp, register const int wantedy
return
min_time
;
return
min_time
;
if
(
dayoff
>
max_time
/
SECSPERDAY
)
if
(
dayoff
>
max_time
/
SECSPERDAY
)
return
max_time
;
return
max_time
;
t
=
(
time_t
)
dayoff
*
SECSPERDAY
;
t
=
(
time_t
)
dayoff
*
SECSPERDAY
;
return
tadd
(
t
,
rp
->
r_tod
);
return
tadd
(
t
,
rp
->
r_tod
);
}
}
static
void
newabbr
(
const
char
*
string
)
static
void
newabbr
(
const
char
*
string
)
{
{
register
int
i
;
register
int
i
;
i
=
strlen
(
string
)
+
1
;
i
=
strlen
(
string
)
+
1
;
if
(
charcnt
+
i
>
TZ_MAX_CHARS
)
{
if
(
charcnt
+
i
>
TZ_MAX_CHARS
)
{
error
(
_
(
"too many, or too long, time zone abbreviations"
));
error
(
_
(
"too many, or too long, time zone abbreviations"
));
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
...
@@ -2044,40 +2318,47 @@ static void newabbr(const char *string)
...
@@ -2044,40 +2318,47 @@ static void newabbr(const char *string)
charcnt
+=
eitol
(
i
);
charcnt
+=
eitol
(
i
);
}
}
static
int
mkdirs
(
char
*
argname
)
static
int
mkdirs
(
char
*
argname
)
{
{
register
char
*
name
;
register
char
*
name
;
register
char
*
cp
;
register
char
*
cp
;
if
(
argname
==
NULL
||
*
argname
==
'\0'
)
if
(
argname
==
NULL
||
*
argname
==
'\0'
)
return
0
;
return
0
;
cp
=
name
=
ecpyalloc
(
argname
);
cp
=
name
=
ecpyalloc
(
argname
);
while
((
cp
=
strchr
(
cp
+
1
,
'/'
))
!=
0
)
{
while
((
cp
=
strchr
(
cp
+
1
,
'/'
))
!=
0
)
{
*
cp
=
'\0'
;
*
cp
=
'\0'
;
#ifdef WIN32
#ifdef WIN32
/*
/*
*
* DOS drive specifier?
*
* DOS drive specifier?
*/
*/
if
(
isalpha
((
unsigned
char
)
name
[
0
])
&&
if
(
isalpha
((
unsigned
char
)
name
[
0
])
&&
name
[
1
]
==
':'
&&
name
[
2
]
==
'\0'
)
{
name
[
1
]
==
':'
&&
name
[
2
]
==
'\0'
)
*
cp
=
'/'
;
{
continue
;
*
cp
=
'/'
;
continue
;
}
}
#endif
/* WIN32 */
#endif
/* WIN32 */
if
(
!
itsdir
(
name
))
{
if
(
!
itsdir
(
name
))
{
/*
/*
** It doesn't seem to exist, so we try to create it.
* * It doesn't seem to exist, so we try to create it. *
** Creation may fail because of the directory being
* Creation may fail because of the directory being * created
** created by some other multiprocessor, so we get
* by some other multiprocessor, so we get * to do extra
** to do extra checking.
* checking.
*/
*/
if
(
mkdir
(
name
,
MKDIR_UMASK
)
!=
0
)
{
if
(
mkdir
(
name
,
MKDIR_UMASK
)
!=
0
)
{
const
char
*
e
=
strerror
(
errno
);
const
char
*
e
=
strerror
(
errno
);
if
(
errno
!=
EEXIST
||
!
itsdir
(
name
))
{
if
(
errno
!=
EEXIST
||
!
itsdir
(
name
))
{
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: Can't create directory %s: %s
\n
"
),
_
(
"%s: Can't create directory %s: %s
\n
"
),
progname
,
name
,
e
);
progname
,
name
,
e
);
ifree
(
name
);
ifree
(
name
);
return
-
1
;
return
-
1
;
}
}
...
@@ -2089,15 +2370,17 @@ _("%s: Can't create directory %s: %s\n"),
...
@@ -2089,15 +2370,17 @@ _("%s: Can't create directory %s: %s\n"),
return
0
;
return
0
;
}
}
static
long
eitol
(
const
int
i
)
static
long
eitol
(
const
int
i
)
{
{
long
l
;
long
l
;
l
=
i
;
l
=
i
;
if
((
i
<
0
&&
l
>=
0
)
||
(
i
==
0
&&
l
!=
0
)
||
(
i
>
0
&&
l
<=
0
))
{
if
((
i
<
0
&&
l
>=
0
)
||
(
i
==
0
&&
l
!=
0
)
||
(
i
>
0
&&
l
<=
0
))
{
(
void
)
fprintf
(
stderr
,
(
void
)
fprintf
(
stderr
,
_
(
"%s: %d did not sign extend correctly
\n
"
),
_
(
"%s: %d did not sign extend correctly
\n
"
),
progname
,
i
);
progname
,
i
);
(
void
)
exit
(
EXIT_FAILURE
);
(
void
)
exit
(
EXIT_FAILURE
);
}
}
return
l
;
return
l
;
...
@@ -2110,12 +2393,13 @@ static long eitol(const int i)
...
@@ -2110,12 +2393,13 @@ static long eitol(const int i)
#ifdef WIN32
#ifdef WIN32
/*
/*
* To run on win32
* To run on win32
*/
*/
int
link
(
const
char
*
oldpath
,
const
char
*
newpath
)
{
int
if
(
!
CopyFileEx
(
oldpath
,
newpath
,
NULL
,
NULL
,
FALSE
,
0
))
{
link
(
const
char
*
oldpath
,
const
char
*
newpath
)
{
if
(
!
CopyFileEx
(
oldpath
,
newpath
,
NULL
,
NULL
,
FALSE
,
0
))
return
-
1
;
return
-
1
;
}
return
0
;
return
0
;
}
}
#endif
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment