137103Sbostic /* 237103Sbostic * Copyright (c) 1989 The Regents of the University of California. 337103Sbostic * All rights reserved. 437103Sbostic * 537103Sbostic * Redistribution and use in source and binary forms are permitted 637103Sbostic * provided that the above copyright notice and this paragraph are 737103Sbostic * duplicated in all such forms and that any documentation, 837103Sbostic * advertising materials, and other materials related to such 937103Sbostic * distribution and use acknowledge that the software was developed 1037103Sbostic * by the University of California, Berkeley. The name of the 1137103Sbostic * University may not be used to endorse or promote products derived 1237103Sbostic * from this software without specific prior written permission. 1337103Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437103Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537103Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637103Sbostic */ 1737103Sbostic 1837103Sbostic #if defined(LIBC_SCCS) && !defined(lint) 19*37344Sbostic static char sccsid[] = "@(#)strftime.c 5.5 (Berkeley) 04/09/89"; 2037103Sbostic #endif /* LIBC_SCCS and not lint */ 2137103Sbostic 2237103Sbostic #include <sys/types.h> 2337103Sbostic #include <sys/time.h> 2437103Sbostic #include <tzfile.h> 2537103Sbostic 2637103Sbostic static char *afmt[] = { 2737103Sbostic "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 2837103Sbostic }; 2937103Sbostic static char *Afmt[] = { 3037103Sbostic "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 3137103Sbostic "Saturday", 3237103Sbostic }; 3337103Sbostic static char *bfmt[] = { 3437103Sbostic "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", 3537103Sbostic "Oct", "Nov", "Dec", 3637103Sbostic }; 3737103Sbostic static char *Bfmt[] = { 3837103Sbostic "January", "February", "March", "April", "May", "June", "July", 3937103Sbostic "August", "September", "October", "November", "December", 4037103Sbostic }; 4137103Sbostic 4237103Sbostic static size_t gsize; 4337103Sbostic static char *pt; 4437103Sbostic 4537103Sbostic size_t 4637103Sbostic strftime(s, maxsize, format, t) 4737103Sbostic char *s; 4837103Sbostic char *format; 4937103Sbostic size_t maxsize; 5037103Sbostic struct tm *t; 5137103Sbostic { 5237103Sbostic size_t _fmt(); 5337103Sbostic 5437103Sbostic pt = s; 5537103Sbostic if ((gsize = maxsize) < 1) 5637103Sbostic return(0); 5737103Sbostic if (_fmt(format, t)) { 5837103Sbostic *pt = '\0'; 5937103Sbostic return(maxsize - gsize); 6037103Sbostic } 6137103Sbostic return(0); 6237103Sbostic } 6337103Sbostic 6437103Sbostic static size_t 6537103Sbostic _fmt(format, t) 6637103Sbostic register char *format; 6737103Sbostic struct tm *t; 6837103Sbostic { 6937103Sbostic for (; *format; ++format) { 7037103Sbostic if (*format == '%') 7137103Sbostic switch(*++format) { 7237176Sbostic case '\0': 7337176Sbostic --format; 7437176Sbostic break; 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 'a': 8237176Sbostic if (t->tm_wday < 0 || t->tm_wday > 6) 8337103Sbostic return(0); 8437176Sbostic if (!_add(afmt[t->tm_wday])) 8537176Sbostic return(0); 8637103Sbostic continue; 8737103Sbostic case 'B': 8837176Sbostic if (t->tm_mon < 0 || t->tm_mon > 11) 8937176Sbostic return(0); 9037103Sbostic if (!_add(Bfmt[t->tm_mon])) 9137103Sbostic return(0); 9237103Sbostic continue; 9337103Sbostic case 'b': 9437137Sbostic case 'h': 9537176Sbostic if (t->tm_mon < 0 || t->tm_mon > 11) 9637176Sbostic return(0); 9737103Sbostic if (!_add(bfmt[t->tm_mon])) 9837103Sbostic return(0); 9937103Sbostic continue; 10037103Sbostic case 'c': 101*37344Sbostic if (!_fmt("%m/%d/%y %H:%M:%S", t)) 10237103Sbostic return(0); 10337103Sbostic continue; 10437137Sbostic case 'D': 10537137Sbostic if (!_fmt("%m/%d/%y", t)) 10637137Sbostic return(0); 10737137Sbostic continue; 10837103Sbostic case 'd': 10937103Sbostic if (!_conv(t->tm_mday, 2)) 11037103Sbostic return(0); 11137103Sbostic continue; 11237103Sbostic case 'H': 11337103Sbostic if (!_conv(t->tm_hour, 2)) 11437103Sbostic return(0); 11537103Sbostic continue; 11637103Sbostic case 'I': 11737176Sbostic if (!_conv(t->tm_hour % 12 ? 11837176Sbostic t->tm_hour % 12 : 12, 2)) 11937103Sbostic return(0); 12037103Sbostic continue; 12137103Sbostic case 'j': 12237103Sbostic if (!_conv(t->tm_yday + 1, 3)) 12337103Sbostic return(0); 12437103Sbostic continue; 12537103Sbostic case 'M': 12637103Sbostic if (!_conv(t->tm_min, 2)) 12737103Sbostic return(0); 12837103Sbostic continue; 12937103Sbostic case 'm': 13037103Sbostic if (!_conv(t->tm_mon + 1, 2)) 13137103Sbostic return(0); 13237103Sbostic continue; 13337137Sbostic case 'n': 13437137Sbostic if (!_add("\n")) 13537137Sbostic return(0); 13637137Sbostic continue; 13737103Sbostic case 'p': 13837176Sbostic if (!_add(t->tm_hour >= 12 ? "PM" : "AM")) 13937103Sbostic return(0); 14037103Sbostic continue; 14137137Sbostic case 'R': 14237137Sbostic if (!_fmt("%H:%M", t)) 14337137Sbostic return(0); 14437137Sbostic continue; 14537137Sbostic case 'r': 14637137Sbostic if (!_fmt("%I:%M:%S %p", t)) 14737137Sbostic return(0); 14837137Sbostic continue; 14937103Sbostic case 'S': 15037103Sbostic if (!_conv(t->tm_sec, 2)) 15137103Sbostic return(0); 15237103Sbostic continue; 15337137Sbostic case 'T': 15437137Sbostic case 'X': 15537137Sbostic if (!_fmt("%H:%M:%S", t)) 15637137Sbostic return(0); 15737137Sbostic continue; 15837137Sbostic case 't': 15937137Sbostic if (!_add("\t")) 16037137Sbostic return(0); 16137137Sbostic continue; 16237103Sbostic case 'U': 16337103Sbostic if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, 16437103Sbostic 2)) 16537103Sbostic return(0); 16637103Sbostic continue; 16737103Sbostic case 'W': 16837103Sbostic if (!_conv((t->tm_yday + 7 - 16937176Sbostic (t->tm_wday ? (t->tm_wday - 1) : 6)) 17037176Sbostic / 7, 2)) 17137103Sbostic return(0); 17237103Sbostic continue; 17337103Sbostic case 'w': 17437103Sbostic if (!_conv(t->tm_wday, 1)) 17537103Sbostic return(0); 17637103Sbostic continue; 17737103Sbostic case 'x': 178*37344Sbostic if (!_fmt("%m/%d/%y", t)) 17937103Sbostic return(0); 18037103Sbostic continue; 18137103Sbostic case 'y': 18237103Sbostic if (!_conv((t->tm_year + TM_YEAR_BASE) 18337103Sbostic % 100, 2)) 18437103Sbostic return(0); 18537103Sbostic continue; 18637103Sbostic case 'Y': 18737103Sbostic if (!_conv(t->tm_year + TM_YEAR_BASE, 4)) 18837103Sbostic return(0); 18937103Sbostic continue; 19037103Sbostic case 'Z': 19137176Sbostic if (!t->tm_zone || !_add(t->tm_zone)) 19237103Sbostic return(0); 19337103Sbostic continue; 19437103Sbostic case '%': 19537103Sbostic /* 19637103Sbostic * X311J/88-090 (4.12.3.5): if conversion char is 19737103Sbostic * undefined, behavior is undefined. Print out the 19837103Sbostic * character itself as printf(3) also does. 19937103Sbostic */ 20037103Sbostic default: 20137103Sbostic break; 20237103Sbostic } 20337103Sbostic if (!gsize--) 20437103Sbostic return(0); 20537103Sbostic *pt++ = *format; 20637103Sbostic } 20737103Sbostic return(gsize); 20837103Sbostic } 20937103Sbostic 21037103Sbostic static 21137103Sbostic _conv(n, digits) 21237103Sbostic int n, digits; 21337103Sbostic { 21437103Sbostic static char buf[10]; 21537103Sbostic register char *p; 21637103Sbostic 21737103Sbostic for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) 21837103Sbostic *p-- = n % 10 + '0'; 21937103Sbostic while (p > buf && digits-- > 0) 22037103Sbostic *p-- = '0'; 22137103Sbostic return(_add(++p)); 22237103Sbostic } 22337103Sbostic 22437103Sbostic static 22537103Sbostic _add(str) 22637103Sbostic register char *str; 22737103Sbostic { 22837103Sbostic for (;; ++pt, --gsize) { 22937103Sbostic if (!gsize) 23037103Sbostic return(0); 23137103Sbostic if (!(*pt = *str++)) 23237103Sbostic return(1); 23337103Sbostic } 23437103Sbostic } 235