1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** This file is in the public domain, so clarified as of
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** 1996-06-05 by Arthur David Olson.
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** Avoid the temptation to punt entirely to strftime;
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** the output of strftime is supposed to be locale specific
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** whereas the output of asctime is supposed to be constant.
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifndef lint
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifndef NOID
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char	elsieid[] = "@(#)asctime.c	8.2";
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* !defined NOID */
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* !defined lint */
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*LINTLIBRARY*/
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "private.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "tzfile.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** Some systems only handle "%.2d"; others only handle "%02d";
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** "%02.2d" makes (most) everybody happy.
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** At least some versions of gcc warn about the %02.2d;
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** we conditionalize below to avoid the warning.
28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** All years associated with 32-bit time_t values are exactly four digits long;
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** some years associated with 64-bit time_t values are not.
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** Vintage programs are coded for years that are always four digits long
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** and may assume that the newline always lands in the same place.
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** For years that are less than four digits, we pad the output with
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** leading zeroes to get the newline in the traditional place.
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** The -4 ensures that we get four characters of output even if
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** we call a strftime variant that produces fewer characters for some years.
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** but many implementations pad anyway; most likely the standards are buggy.
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef __GNUC__
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ASCTIME_FMT	"%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else /* !defined __GNUC__ */
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ASCTIME_FMT	"%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* !defined __GNUC__ */
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** For years that are more than four digits we put extra spaces before the year
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** so that code trying to overwrite the newline won't end up overwriting
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** a digit within a year and truncating the year (operating on the assumption
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** that no output is better than wrong output).
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef __GNUC__
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ASCTIME_FMT_B	"%.3s %.3s%3d %2.2d:%2.2d:%2.2d     %s\n"
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else /* !defined __GNUC__ */
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ASCTIME_FMT_B	"%.3s %.3s%3d %02.2d:%02.2d:%02.2d     %s\n"
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* !defined __GNUC__ */
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define STD_ASCTIME_BUF_SIZE	26
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** Big enough for something such as
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** ??? ???-2147483648 -2147483648:-2147483648:-2147483648     -2147483648\n
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** (two three-character abbreviations, five strings denoting integers,
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** seven explicit spaces, two explicit colons, a newline,
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** and a trailing ASCII nul).
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** The values above are for systems where an int is 32 bits and are provided
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** as an example; the define below calculates the maximum for the system at
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** hand.
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define MAX_ASCTIME_BUF_SIZE	(2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1)
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic char	buf_asctime[MAX_ASCTIME_BUF_SIZE];
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruchar *
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruasctime_r(timeptr, buf)
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruregister const struct tm *	timeptr;
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruchar *				buf;
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	static const char	wday_name[][3] = {
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	};
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	static const char	mon_name[][3] = {
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	};
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	register const char *	wn;
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	register const char *	mn;
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	char			year[INT_STRLEN_MAXIMUM(int) + 2];
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	char			result[MAX_ASCTIME_BUF_SIZE];
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		wn = "???";
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	else	wn = wday_name[timeptr->tm_wday];
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		mn = "???";
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	else	mn = mon_name[timeptr->tm_mon];
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	/*
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	** Use strftime's %Y to generate the year, to avoid overflow problems
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	** when computing timeptr->tm_year + TM_YEAR_BASE.
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	** Assume that strftime is unaffected by other out-of-range members
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	** (e.g., timeptr->tm_mday) when processing "%Y".
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	*/
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	(void) strftime(year, sizeof year, "%Y", timeptr);
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	/*
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	** We avoid using snprintf since it's not available on all systems.
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	*/
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	(void) sprintf(result,
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		wn, mn,
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		timeptr->tm_mday, timeptr->tm_hour,
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		timeptr->tm_min, timeptr->tm_sec,
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		year);
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime) {
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		(void) strcpy(buf, result);
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		return buf;
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	} else {
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef EOVERFLOW
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		errno = EOVERFLOW;
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else /* !defined EOVERFLOW */
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		errno = EINVAL;
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* !defined EOVERFLOW */
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru		return NULL;
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	}
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruchar *
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruasctime(timeptr)
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruregister const struct tm *	timeptr;
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru	return asctime_r(timeptr, buf_asctime);
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
139