137103Sbostic /*
2*61193Sbostic * Copyright (c) 1989, 1993
3*61193Sbostic * The Regents of the University of California. All rights reserved.
437103Sbostic *
542636Sbostic * %sccs.include.redist.c%
637103Sbostic */
737103Sbostic
837103Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*61193Sbostic static char sccsid[] = "@(#)strftime.c 8.1 (Berkeley) 06/04/93";
1037103Sbostic #endif /* LIBC_SCCS and not lint */
1137103Sbostic
1237103Sbostic #include <sys/types.h>
1337103Sbostic #include <sys/time.h>
1437103Sbostic #include <tzfile.h>
1542181Sbostic #include <string.h>
1637103Sbostic
1737103Sbostic static char *afmt[] = {
1837103Sbostic "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
1937103Sbostic };
2037103Sbostic static char *Afmt[] = {
2137103Sbostic "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
2237103Sbostic "Saturday",
2337103Sbostic };
2437103Sbostic static char *bfmt[] = {
2537103Sbostic "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
2637103Sbostic "Oct", "Nov", "Dec",
2737103Sbostic };
2837103Sbostic static char *Bfmt[] = {
2937103Sbostic "January", "February", "March", "April", "May", "June", "July",
3037103Sbostic "August", "September", "October", "November", "December",
3137103Sbostic };
3237103Sbostic
3337103Sbostic static size_t gsize;
3437103Sbostic static char *pt;
3556417Sbostic static int _add __P((char *));
3656419Sbostic static int _conv __P((int, int, int));
3756417Sbostic static int _secs __P((const struct tm *));
3856417Sbostic static size_t _fmt __P((const char *, const struct tm *));
3937103Sbostic
4037103Sbostic size_t
strftime(s,maxsize,format,t)4137103Sbostic strftime(s, maxsize, format, t)
4237103Sbostic char *s;
4337103Sbostic size_t maxsize;
4446613Sbostic const char *format;
4546613Sbostic const struct tm *t;
4637103Sbostic {
4737103Sbostic
4837103Sbostic pt = s;
4937103Sbostic if ((gsize = maxsize) < 1)
5037103Sbostic return(0);
5137103Sbostic if (_fmt(format, t)) {
5237103Sbostic *pt = '\0';
5337103Sbostic return(maxsize - gsize);
5437103Sbostic }
5537103Sbostic return(0);
5637103Sbostic }
5737103Sbostic
5837103Sbostic static size_t
_fmt(format,t)5937103Sbostic _fmt(format, t)
6056417Sbostic register const char *format;
6156417Sbostic const struct tm *t;
6237103Sbostic {
6337103Sbostic for (; *format; ++format) {
6437103Sbostic if (*format == '%')
6537103Sbostic switch(*++format) {
6637176Sbostic case '\0':
6737176Sbostic --format;
6837176Sbostic break;
6937103Sbostic case 'A':
7037176Sbostic if (t->tm_wday < 0 || t->tm_wday > 6)
7137103Sbostic return(0);
7237176Sbostic if (!_add(Afmt[t->tm_wday]))
7337176Sbostic return(0);
7437103Sbostic continue;
7537103Sbostic case 'a':
7637176Sbostic if (t->tm_wday < 0 || t->tm_wday > 6)
7737103Sbostic return(0);
7837176Sbostic if (!_add(afmt[t->tm_wday]))
7937176Sbostic return(0);
8037103Sbostic continue;
8137103Sbostic case 'B':
8237176Sbostic if (t->tm_mon < 0 || t->tm_mon > 11)
8337176Sbostic return(0);
8437103Sbostic if (!_add(Bfmt[t->tm_mon]))
8537103Sbostic return(0);
8637103Sbostic continue;
8737103Sbostic case 'b':
8837137Sbostic case 'h':
8937176Sbostic if (t->tm_mon < 0 || t->tm_mon > 11)
9037176Sbostic return(0);
9137103Sbostic if (!_add(bfmt[t->tm_mon]))
9237103Sbostic return(0);
9337103Sbostic continue;
9437346Sbostic case 'C':
9537346Sbostic if (!_fmt("%a %b %e %H:%M:%S %Y", t))
9637346Sbostic return(0);
9737346Sbostic continue;
9837103Sbostic case 'c':
9937344Sbostic if (!_fmt("%m/%d/%y %H:%M:%S", t))
10037103Sbostic return(0);
10137103Sbostic continue;
10237137Sbostic case 'D':
10337137Sbostic if (!_fmt("%m/%d/%y", t))
10437137Sbostic return(0);
10537137Sbostic continue;
10637103Sbostic case 'd':
10737346Sbostic if (!_conv(t->tm_mday, 2, '0'))
10837103Sbostic return(0);
10937103Sbostic continue;
11045668Sbostic case 'e':
11145668Sbostic if (!_conv(t->tm_mday, 2, ' '))
11245668Sbostic return(0);
11345668Sbostic continue;
11437103Sbostic case 'H':
11537346Sbostic if (!_conv(t->tm_hour, 2, '0'))
11637103Sbostic return(0);
11737103Sbostic continue;
11837103Sbostic case 'I':
11937176Sbostic if (!_conv(t->tm_hour % 12 ?
12037346Sbostic t->tm_hour % 12 : 12, 2, '0'))
12137103Sbostic return(0);
12237103Sbostic continue;
12337103Sbostic case 'j':
12437346Sbostic if (!_conv(t->tm_yday + 1, 3, '0'))
12537103Sbostic return(0);
12637103Sbostic continue;
12737346Sbostic case 'k':
12837346Sbostic if (!_conv(t->tm_hour, 2, ' '))
12937346Sbostic return(0);
13037346Sbostic continue;
13137346Sbostic case 'l':
13237346Sbostic if (!_conv(t->tm_hour % 12 ?
13337346Sbostic t->tm_hour % 12 : 12, 2, ' '))
13437346Sbostic return(0);
13537346Sbostic continue;
13637103Sbostic case 'M':
13737346Sbostic if (!_conv(t->tm_min, 2, '0'))
13837103Sbostic return(0);
13937103Sbostic continue;
14037103Sbostic case 'm':
14137346Sbostic if (!_conv(t->tm_mon + 1, 2, '0'))
14237103Sbostic return(0);
14337103Sbostic continue;
14437137Sbostic case 'n':
14537137Sbostic if (!_add("\n"))
14637137Sbostic return(0);
14737137Sbostic continue;
14837103Sbostic case 'p':
14937176Sbostic if (!_add(t->tm_hour >= 12 ? "PM" : "AM"))
15037103Sbostic return(0);
15137103Sbostic continue;
15237137Sbostic case 'R':
15337137Sbostic if (!_fmt("%H:%M", t))
15437137Sbostic return(0);
15537137Sbostic continue;
15637137Sbostic case 'r':
15737137Sbostic if (!_fmt("%I:%M:%S %p", t))
15837137Sbostic return(0);
15937137Sbostic continue;
16037103Sbostic case 'S':
16137346Sbostic if (!_conv(t->tm_sec, 2, '0'))
16237103Sbostic return(0);
16337103Sbostic continue;
16445668Sbostic case 's':
16545668Sbostic if (!_secs(t))
16645668Sbostic return(0);
16745668Sbostic continue;
16837137Sbostic case 'T':
16937137Sbostic case 'X':
17037137Sbostic if (!_fmt("%H:%M:%S", t))
17137137Sbostic return(0);
17237137Sbostic continue;
17337137Sbostic case 't':
17437137Sbostic if (!_add("\t"))
17537137Sbostic return(0);
17637137Sbostic continue;
17737103Sbostic case 'U':
17837103Sbostic if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7,
17937346Sbostic 2, '0'))
18037103Sbostic return(0);
18137103Sbostic continue;
18237103Sbostic case 'W':
18337103Sbostic if (!_conv((t->tm_yday + 7 -
18437176Sbostic (t->tm_wday ? (t->tm_wday - 1) : 6))
18537346Sbostic / 7, 2, '0'))
18637103Sbostic return(0);
18737103Sbostic continue;
18837103Sbostic case 'w':
18937346Sbostic if (!_conv(t->tm_wday, 1, '0'))
19037103Sbostic return(0);
19137103Sbostic continue;
19237103Sbostic case 'x':
19337344Sbostic if (!_fmt("%m/%d/%y", t))
19437103Sbostic return(0);
19537103Sbostic continue;
19637103Sbostic case 'y':
19737103Sbostic if (!_conv((t->tm_year + TM_YEAR_BASE)
19837346Sbostic % 100, 2, '0'))
19937103Sbostic return(0);
20037103Sbostic continue;
20137103Sbostic case 'Y':
20237346Sbostic if (!_conv(t->tm_year + TM_YEAR_BASE, 4, '0'))
20337103Sbostic return(0);
20437103Sbostic continue;
20537103Sbostic case 'Z':
20637176Sbostic if (!t->tm_zone || !_add(t->tm_zone))
20737103Sbostic return(0);
20837103Sbostic continue;
20937103Sbostic case '%':
21037103Sbostic /*
21137103Sbostic * X311J/88-090 (4.12.3.5): if conversion char is
21237103Sbostic * undefined, behavior is undefined. Print out the
21337346Sbostic * character itself as printf(3) does.
21437103Sbostic */
21537103Sbostic default:
21637103Sbostic break;
21737103Sbostic }
21837103Sbostic if (!gsize--)
21937103Sbostic return(0);
22037103Sbostic *pt++ = *format;
22137103Sbostic }
22237103Sbostic return(gsize);
22337103Sbostic }
22437103Sbostic
22556417Sbostic static int
_secs(t)22645668Sbostic _secs(t)
22756417Sbostic const struct tm *t;
22845668Sbostic {
22945668Sbostic static char buf[15];
23045668Sbostic register time_t s;
23145668Sbostic register char *p;
23245693Sbostic struct tm tmp;
23345668Sbostic
23445693Sbostic /* Make a copy, mktime(3) modifies the tm struct. */
23545693Sbostic tmp = *t;
23645693Sbostic s = mktime(&tmp);
23745668Sbostic for (p = buf + sizeof(buf) - 2; s > 0 && p > buf; s /= 10)
23845668Sbostic *p-- = s % 10 + '0';
23945668Sbostic return(_add(++p));
24045668Sbostic }
24145668Sbostic
24256417Sbostic static int
_conv(n,digits,pad)24337346Sbostic _conv(n, digits, pad)
24456419Sbostic int n, digits, pad;
24537103Sbostic {
24637103Sbostic static char buf[10];
24737103Sbostic register char *p;
24837103Sbostic
24937103Sbostic for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits)
25037103Sbostic *p-- = n % 10 + '0';
25137103Sbostic while (p > buf && digits-- > 0)
25237346Sbostic *p-- = pad;
25337103Sbostic return(_add(++p));
25437103Sbostic }
25537103Sbostic
25656417Sbostic static int
_add(str)25737103Sbostic _add(str)
25837103Sbostic register char *str;
25937103Sbostic {
26037103Sbostic for (;; ++pt, --gsize) {
26137103Sbostic if (!gsize)
26237103Sbostic return(0);
26337103Sbostic if (!(*pt = *str++))
26437103Sbostic return(1);
26537103Sbostic }
26637103Sbostic }
267