1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #if defined(LIBC_SCCS) && !defined(lint) 19 static char sccsid[] = "@(#)strftime.c 5.2 (Berkeley) 03/12/89"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/types.h> 23 #include <sys/time.h> 24 #include <tzfile.h> 25 26 static char *afmt[] = { 27 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 28 }; 29 static char *Afmt[] = { 30 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", 31 "Saturday", 32 }; 33 static char *bfmt[] = { 34 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", 35 "Oct", "Nov", "Dec", 36 }; 37 static char *Bfmt[] = { 38 "January", "February", "March", "April", "May", "June", "July", 39 "August", "September", "October", "November", "December", 40 }; 41 42 static size_t gsize; 43 static char *pt; 44 45 size_t 46 strftime(s, maxsize, format, t) 47 char *s; 48 char *format; 49 size_t maxsize; 50 struct tm *t; 51 { 52 size_t _fmt(); 53 54 pt = s; 55 if ((gsize = maxsize) < 1) 56 return(0); 57 if (_fmt(format, t)) { 58 *pt = '\0'; 59 return(maxsize - gsize); 60 } 61 return(0); 62 } 63 64 static size_t 65 _fmt(format, t) 66 register char *format; 67 struct tm *t; 68 { 69 char *timezone(); 70 71 for (; *format; ++format) { 72 if (*format == '%') 73 switch(*++format) { 74 case 'A': 75 if (!_add(Afmt[t->tm_mon])) 76 return(0); 77 continue; 78 case 'a': 79 if (!_add(afmt[t->tm_mon])) 80 return(0); 81 continue; 82 case 'B': 83 if (!_add(Bfmt[t->tm_mon])) 84 return(0); 85 continue; 86 case 'b': 87 case 'h': 88 if (!_add(bfmt[t->tm_mon])) 89 return(0); 90 continue; 91 case 'c': 92 if (!_fmt("%x %X %Z %Y", t)) 93 return(0); 94 continue; 95 case 'D': 96 if (!_fmt("%m/%d/%y", t)) 97 return(0); 98 continue; 99 case 'd': 100 if (!_conv(t->tm_mday, 2)) 101 return(0); 102 continue; 103 case 'H': 104 if (!_conv(t->tm_hour, 2)) 105 return(0); 106 continue; 107 case 'I': 108 if (!_conv((t->tm_hour - 1) % 12 + 1, 2)) 109 return(0); 110 continue; 111 case 'j': 112 if (!_conv(t->tm_yday + 1, 3)) 113 return(0); 114 continue; 115 case 'M': 116 if (!_conv(t->tm_min, 2)) 117 return(0); 118 continue; 119 case 'm': 120 if (!_conv(t->tm_mon + 1, 2)) 121 return(0); 122 continue; 123 case 'n': 124 if (!_add("\n")) 125 return(0); 126 continue; 127 case 'p': 128 if (!_add(t->tm_hour >= 12 ? "AM" : "PM")) 129 return(0); 130 continue; 131 case 'R': 132 if (!_fmt("%H:%M", t)) 133 return(0); 134 continue; 135 case 'r': 136 if (!_fmt("%I:%M:%S %p", t)) 137 return(0); 138 continue; 139 case 'S': 140 if (!_conv(t->tm_sec, 2)) 141 return(0); 142 continue; 143 case 'T': 144 case 'X': 145 if (!_fmt("%H:%M:%S", t)) 146 return(0); 147 continue; 148 case 't': 149 if (!_add("\t")) 150 return(0); 151 continue; 152 case 'U': 153 if (!_conv((t->tm_yday + 7 - t->tm_wday) / 7, 154 2)) 155 return(0); 156 continue; 157 case 'W': 158 if (!_conv((t->tm_yday + 7 - 159 (t->tm_wday ? t->tm_wday : 6)) / 7, 2)) 160 return(0); 161 continue; 162 case 'w': 163 if (!_conv(t->tm_wday, 1)) 164 return(0); 165 continue; 166 case 'x': 167 if (!_fmt("%a %b %d", t)) 168 return(0); 169 continue; 170 case 'y': 171 if (!_conv((t->tm_year + TM_YEAR_BASE) 172 % 100, 2)) 173 return(0); 174 continue; 175 case 'Y': 176 if (!_conv(t->tm_year + TM_YEAR_BASE, 4)) 177 return(0); 178 continue; 179 case 'Z': 180 if (!_add(t->tm_zone)) 181 return(0); 182 continue; 183 case '%': 184 /* 185 * X311J/88-090 (4.12.3.5): if conversion char is 186 * undefined, behavior is undefined. Print out the 187 * character itself as printf(3) also does. 188 */ 189 default: 190 break; 191 } 192 if (!gsize--) 193 return(0); 194 *pt++ = *format; 195 } 196 return(gsize); 197 } 198 199 static 200 _conv(n, digits) 201 int n, digits; 202 { 203 static char buf[10]; 204 register char *p; 205 206 for (p = buf + sizeof(buf) - 2; n > 0 && p > buf; n /= 10, --digits) 207 *p-- = n % 10 + '0'; 208 while (p > buf && digits-- > 0) 209 *p-- = '0'; 210 return(_add(++p)); 211 } 212 213 static 214 _add(str) 215 register char *str; 216 { 217 for (;; ++pt, --gsize) { 218 if (!gsize) 219 return(0); 220 if (!(*pt = *str++)) 221 return(1); 222 } 223 } 224