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