137103Sbostic /* 237103Sbostic * Copyright (c) 1989 The Regents of the University of California. 337103Sbostic * All rights reserved. 437103Sbostic * 542636Sbostic * %sccs.include.redist.c% 637103Sbostic */ 737103Sbostic 837103Sbostic #if defined(LIBC_SCCS) && !defined(lint) 9*56417Sbostic static char sccsid[] = "@(#)strftime.c 5.12 (Berkeley) 10/04/92"; 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; 35*56417Sbostic static int _add __P((char *)); 36*56417Sbostic static int _conv __P((int, int, char)); 37*56417Sbostic static int _secs __P((const struct tm *)); 38*56417Sbostic static size_t _fmt __P((const char *, const struct tm *)); 3937103Sbostic 4037103Sbostic size_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 5937103Sbostic _fmt(format, t) 60*56417Sbostic register const char *format; 61*56417Sbostic 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 225*56417Sbostic static int 22645668Sbostic _secs(t) 227*56417Sbostic 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 242*56417Sbostic static int 24337346Sbostic _conv(n, digits, pad) 24437103Sbostic int n, digits; 24537346Sbostic char pad; 24637103Sbostic { 24737103Sbostic static char buf[10]; 24837103Sbostic register char *p; 24937103Sbostic 25037103Sbostic for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) 25137103Sbostic *p-- = n % 10 + '0'; 25237103Sbostic while (p > buf && digits-- > 0) 25337346Sbostic *p-- = pad; 25437103Sbostic return(_add(++p)); 25537103Sbostic } 25637103Sbostic 257*56417Sbostic static int 25837103Sbostic _add(str) 25937103Sbostic register char *str; 26037103Sbostic { 26137103Sbostic for (;; ++pt, --gsize) { 26237103Sbostic if (!gsize) 26337103Sbostic return(0); 26437103Sbostic if (!(*pt = *str++)) 26537103Sbostic return(1); 26637103Sbostic } 26737103Sbostic } 268