day.c (200470) | day.c (205821) |
---|---|
1/* | 1/*- |
2 * Copyright (c) 1989, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 17 unchanged lines hidden (view full) --- 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> | 2 * Copyright (c) 1989, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. --- 17 unchanged lines hidden (view full) --- 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#include <sys/cdefs.h> |
35__FBSDID("$FreeBSD: head/usr.bin/calendar/day.c 200470 2009-12-13 04:50:11Z delphij $"); | 35__FBSDID("$FreeBSD: head/usr.bin/calendar/day.c 205821 2010-03-29 06:49:20Z edwin $"); |
36 | 36 |
37#include <sys/types.h> 38#include <sys/uio.h> 39#include <ctype.h> | |
40#include <err.h> 41#include <locale.h> 42#include <stdio.h> 43#include <stdlib.h> 44#include <string.h> 45#include <time.h> 46 47#include "calendar.h" 48 | 37#include <err.h> 38#include <locale.h> 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <time.h> 43 44#include "calendar.h" 45 |
49struct tm *tp; 50static const struct tm tm0; 51int *cumdays, yrdays; 52char dayname[10]; | 46time_t time1, time2; 47const struct tm tm0; 48char dayname[100]; 49int year1, year2; |
53 54 | 50 51 |
55/* 1-based month, 0-based days, cumulative */ 56int daytab[][14] = { 57 {0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364}, 58 {0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}, 59}; 60 61static char const *days[] = { 62 "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL, 63}; 64 65static const char *months[] = { 66 "jan", "feb", "mar", "apr", "may", "jun", 67 "jul", "aug", "sep", "oct", "nov", "dec", NULL, 68}; 69 70static struct fixs fndays[8]; /* full national days names */ 71static struct fixs ndays[8]; /* short national days names */ 72 73static struct fixs fnmonths[13]; /* full national months names */ 74static struct fixs nmonths[13]; /* short national month names */ 75 76 | |
77void | 52void |
78setnnames(void) | 53settimes(time_t now, int before, int after, int friday, struct tm *tp1, struct tm *tp2) |
79{ | 54{ |
80 char buf[80]; 81 int i, l; 82 struct tm tm; | 55 char *oldl, *lbufp; 56 struct tm tp; |
83 | 57 |
84 for (i = 0; i < 7; i++) { 85 tm.tm_wday = i; 86 strftime(buf, sizeof(buf), "%a", &tm); 87 for (l = strlen(buf); 88 l > 0 && isspace((unsigned char)buf[l - 1]); 89 l--) 90 ; 91 buf[l] = '\0'; 92 if (ndays[i].name != NULL) 93 free(ndays[i].name); 94 if ((ndays[i].name = strdup(buf)) == NULL) 95 errx(1, "cannot allocate memory"); 96 ndays[i].len = strlen(buf); | 58 localtime_r(&now, &tp); |
97 | 59 |
98 strftime(buf, sizeof(buf), "%A", &tm); 99 for (l = strlen(buf); 100 l > 0 && isspace((unsigned char)buf[l - 1]); 101 l--) 102 ; 103 buf[l] = '\0'; 104 if (fndays[i].name != NULL) 105 free(fndays[i].name); 106 if ((fndays[i].name = strdup(buf)) == NULL) 107 errx(1, "cannot allocate memory"); 108 fndays[i].len = strlen(buf); 109 } | 60 /* Friday displays Monday's events */ 61 if (after == 0 && before == 0 && friday != -1) 62 after = tp.tm_wday == friday ? 3 : 1; |
110 | 63 |
111 for (i = 0; i < 12; i++) { 112 tm.tm_mon = i; 113 strftime(buf, sizeof(buf), "%b", &tm); 114 for (l = strlen(buf); 115 l > 0 && isspace((unsigned char)buf[l - 1]); 116 l--) 117 ; 118 buf[l] = '\0'; 119 if (nmonths[i].name != NULL) 120 free(nmonths[i].name); 121 if ((nmonths[i].name = strdup(buf)) == NULL) 122 errx(1, "cannot allocate memory"); 123 nmonths[i].len = strlen(buf); | 64 time1 = now - SECSPERDAY * before; 65 localtime_r(&time1, tp1); 66 year1 = 1900 + tp1->tm_year; 67 time2 = now + SECSPERDAY * after; 68 localtime_r(&time2, tp2); 69 year2 = 1900 + tp2->tm_year; |
124 | 70 |
125 strftime(buf, sizeof(buf), "%B", &tm); 126 for (l = strlen(buf); 127 l > 0 && isspace((unsigned char)buf[l - 1]); 128 l--) 129 ; 130 buf[l] = '\0'; 131 if (fnmonths[i].name != NULL) 132 free(fnmonths[i].name); 133 if ((fnmonths[i].name = strdup(buf)) == NULL) 134 errx(1, "cannot allocate memory"); 135 fnmonths[i].len = strlen(buf); 136 } 137} | 71 strftime(dayname, sizeof(dayname) - 1, "%A, %d %B %Y", tp1); |
138 | 72 |
139void 140settime(time_t now) 141{ 142 char *oldl, *lbufp; 143 144 tp = localtime(&now); 145 if (isleap(tp->tm_year + 1900)) { 146 yrdays = 366; 147 cumdays = daytab[1]; 148 } else { 149 yrdays = 365; 150 cumdays = daytab[0]; 151 } 152 /* Friday displays Monday's events */ 153 if (f_dayAfter == 0 && f_dayBefore == 0 && Friday != -1) 154 f_dayAfter = tp->tm_wday == Friday ? 3 : 1; 155 header[5].iov_base = dayname; 156 | |
157 oldl = NULL; 158 lbufp = setlocale(LC_TIME, NULL); 159 if (lbufp != NULL && (oldl = strdup(lbufp)) == NULL) 160 errx(1, "cannot allocate memory"); 161 (void)setlocale(LC_TIME, "C"); | 73 oldl = NULL; 74 lbufp = setlocale(LC_TIME, NULL); 75 if (lbufp != NULL && (oldl = strdup(lbufp)) == NULL) 76 errx(1, "cannot allocate memory"); 77 (void)setlocale(LC_TIME, "C"); |
162 header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp); | |
163 (void)setlocale(LC_TIME, (oldl != NULL ? oldl : "")); 164 if (oldl != NULL) 165 free(oldl); 166 167 setnnames(); 168} 169 170/* convert Day[/Month][/Year] into unix time (since 1970) 171 * Day: two digits, Month: two digits, Year: digits 172 */ 173time_t 174Mktime(char *dp) 175{ 176 time_t t; 177 int d, m, y; | 78 (void)setlocale(LC_TIME, (oldl != NULL ? oldl : "")); 79 if (oldl != NULL) 80 free(oldl); 81 82 setnnames(); 83} 84 85/* convert Day[/Month][/Year] into unix time (since 1970) 86 * Day: two digits, Month: two digits, Year: digits 87 */ 88time_t 89Mktime(char *dp) 90{ 91 time_t t; 92 int d, m, y; |
178 struct tm tm; | 93 struct tm tm, tp; |
179 180 (void)time(&t); | 94 95 (void)time(&t); |
181 tp = localtime(&t); | 96 localtime_r(&t, &tp); |
182 183 tm = tm0; | 97 98 tm = tm0; |
184 tm.tm_mday = tp->tm_mday; 185 tm.tm_mon = tp->tm_mon; 186 tm.tm_year = tp->tm_year; | 99 tm.tm_mday = tp.tm_mday; 100 tm.tm_mon = tp.tm_mon; 101 tm.tm_year = tp.tm_year; |
187 188 switch (sscanf(dp, "%d.%d.%d", &d, &m, &y)) { 189 case 3: 190 if (y > 1900) 191 y -= 1900; 192 tm.tm_year = y; 193 /* FALLTHROUGH */ 194 case 2: --- 4 unchanged lines hidden (view full) --- 199 } 200 201#ifdef DEBUG 202 fprintf(stderr, "Mktime: %d %d %s\n", 203 (int)mktime(&tm), (int)t, asctime(&tm)); 204#endif 205 return (mktime(&tm)); 206} | 102 103 switch (sscanf(dp, "%d.%d.%d", &d, &m, &y)) { 104 case 3: 105 if (y > 1900) 106 y -= 1900; 107 tm.tm_year = y; 108 /* FALLTHROUGH */ 109 case 2: --- 4 unchanged lines hidden (view full) --- 114 } 115 116#ifdef DEBUG 117 fprintf(stderr, "Mktime: %d %d %s\n", 118 (int)mktime(&tm), (int)t, asctime(&tm)); 119#endif 120 return (mktime(&tm)); 121} |
207 208/* 209 * Possible date formats include any combination of: 210 * 3-charmonth (January, Jan, Jan) 211 * 3-charweekday (Friday, Monday, mon.) 212 * numeric month or day (1, 2, 04) 213 * 214 * Any character may separate them, or they may not be separated. Any line, 215 * following a line that is matched, that starts with "whitespace", is shown 216 * along with the matched line. 217 */ 218int 219isnow(char *endp, int *monthp, int *dayp, int *varp) 220{ 221 int day, flags, month = 0, v1, v2; 222 223 /* 224 * CONVENTION 225 * 226 * Month: 1-12 227 * Monthname: Jan .. Dec 228 * Day: 1-31 229 * Weekday: Mon-Sun 230 * 231 */ 232 233 flags = 0; 234 235 /* read first field */ 236 /* didn't recognize anything, skip it */ 237 if (!(v1 = getfield(endp, &endp, &flags))) 238 return (0); 239 240 /* Easter or Easter depending days */ 241 if (flags & F_EASTER) 242 day = v1 - 1; /* days since January 1 [0-365] */ 243 244 /* 245 * 1. {Weekday,Day} XYZ ... 246 * 247 * where Day is > 12 248 */ 249 else if (flags & F_ISDAY || v1 > 12) { 250 251 /* found a day; day: 1-31 or weekday: 1-7 */ 252 day = v1; 253 254 /* {Day,Weekday} {Month,Monthname} ... */ 255 /* if no recognizable month, assume just a day alone 256 * in other words, find month or use current month */ 257 if (!(month = getfield(endp, &endp, &flags))) 258 month = tp->tm_mon + 1; 259 } 260 261 /* 2. {Monthname} XYZ ... */ 262 else if (flags & F_ISMONTH) { 263 month = v1; 264 265 /* Monthname {day,weekday} */ 266 /* if no recognizable day, assume the first day in month */ 267 if (!(day = getfield(endp, &endp, &flags))) 268 day = 1; 269 } 270 271 /* Hm ... */ 272 else { 273 v2 = getfield(endp, &endp, &flags); 274 275 /* 276 * {Day} {Monthname} ... 277 * where Day <= 12 278 */ 279 if (flags & F_ISMONTH) { 280 day = v1; 281 month = v2; 282 *varp = 0; 283 } 284 285 /* {Month} {Weekday,Day} ... */ 286 else { 287 /* F_ISDAY set, v2 > 12, or no way to tell */ 288 month = v1; 289 /* if no recognizable day, assume the first */ 290 day = v2 ? v2 : 1; 291 *varp = 0; 292 } 293 } 294 295 /* convert Weekday into *next* Day, 296 * e.g.: 'Sunday' -> 22 297 * 'SundayLast' -> ?? 298 */ 299 if (flags & F_ISDAY) { 300#ifdef DEBUG 301 fprintf(stderr, "\nday: %d %s month %d\n", day, endp, month); 302#endif 303 304 *varp = 1; 305 /* variable weekday, SundayLast, MondayFirst ... */ 306 if (day < 0 || day >= 10) { 307 308 /* negative offset; last, -4 .. -1 */ 309 if (day < 0) { 310 v1 = day / 10 - 1; /* offset -4 ... -1 */ 311 day = 10 + (day % 10); /* day 1 ... 7 */ 312 313 /* day, eg '22nd' */ 314 v2 = tp->tm_mday + 315 (((day - 1) - tp->tm_wday + 7) % 7); 316 317 /* (month length - day) / 7 + 1 */ 318 if (cumdays[month + 1] - cumdays[month] >= v2 319 && ((int)((cumdays[month + 1] - 320 cumdays[month] - v2) / 7) + 1) == -v1) 321 day = v2; /* bingo ! */ 322 323 /* set to yesterday */ 324 else { 325 day = tp->tm_mday - 1; 326 if (day == 0) 327 return (0); 328 } 329 } 330 331 /* first, second ... +1 ... +5 */ 332 else { 333 /* offset: +1 (first Sunday) ... */ 334 v1 = day / 10; 335 day = day % 10; 336 337 /* day, eg '22th' */ 338 v2 = tp->tm_mday + 339 (((day - 1) - tp->tm_wday + 7) % 7); 340 341 /* Hurrah! matched */ 342 if (((v2 - 1 + 7) / 7) == v1 ) 343 day = v2; 344 345 else { 346 /* set to yesterday */ 347 day = tp->tm_mday - 1; 348 if (day == 0) 349 return (0); 350 } 351 } 352 } else { 353 /* wired */ 354 day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7); 355 *varp = 1; 356 } 357 } 358 359 if (!(flags & F_EASTER)) { 360 if (day + cumdays[month] > cumdays[month + 1]) { 361 /* off end of month, adjust */ 362 day -= (cumdays[month + 1] - cumdays[month]); 363 /* next year */ 364 if (++month > 12) 365 month = 1; 366 } 367 *monthp = month; 368 *dayp = day; 369 day = cumdays[month] + day; 370 } else { 371 for (v1 = 0; day > cumdays[v1]; v1++) 372 ; 373 *monthp = v1 - 1; 374 *dayp = day - cumdays[v1 - 1]; 375 *varp = 1; 376 } 377 378#ifdef DEBUG 379 fprintf(stderr, "day2: day %d(%d-%d) yday %d\n", 380 *dayp, day, cumdays[month], tp->tm_yday); 381#endif 382 383 /* When days before or days after is specified */ 384 /* no year rollover */ 385 if (day >= tp->tm_yday - f_dayBefore && 386 day <= tp->tm_yday + f_dayAfter) 387 return (1); 388 389 /* next year */ 390 if (tp->tm_yday + f_dayAfter >= yrdays) { 391 int end = tp->tm_yday + f_dayAfter - yrdays; 392 if (day <= end) 393 return (1); 394 } 395 396 /* previous year */ 397 if (tp->tm_yday - f_dayBefore < 0) { 398 int before = yrdays + (tp->tm_yday - f_dayBefore); 399 if (day >= before) 400 return (1); 401 } 402 403 return (0); 404} 405 406 407int 408getmonth(char *s) 409{ 410 const char **p; 411 struct fixs *n; 412 413 for (n = fnmonths; n->name; ++n) 414 if (!strncasecmp(s, n->name, n->len)) 415 return ((n - fnmonths) + 1); 416 for (n = nmonths; n->name; ++n) 417 if (!strncasecmp(s, n->name, n->len)) 418 return ((n - nmonths) + 1); 419 for (p = months; *p; ++p) 420 if (!strncasecmp(s, *p, 3)) 421 return ((p - months) + 1); 422 return (0); 423} 424 425 426int 427getday(char *s) 428{ 429 const char **p; 430 struct fixs *n; 431 432 for (n = fndays; n->name; ++n) 433 if (!strncasecmp(s, n->name, n->len)) 434 return ((n - fndays) + 1); 435 for (n = ndays; n->name; ++n) 436 if (!strncasecmp(s, n->name, n->len)) 437 return ((n - ndays) + 1); 438 for (p = days; *p; ++p) 439 if (!strncasecmp(s, *p, 3)) 440 return ((p - days) + 1); 441 return (0); 442} 443 444/* return offset for variable weekdays 445 * -1 -> last weekday in month 446 * +1 -> first weekday in month 447 * ... etc ... 448 */ 449int 450getdayvar(char *s) 451{ 452 int offs; 453 454 offs = strlen(s); 455 456 /* Sun+1 or Wednesday-2 457 * ^ ^ */ 458 459 /* fprintf(stderr, "x: %s %s %d\n", s, s + offs - 2, offs); */ 460 switch (*(s + offs - 2)) { 461 case '-': 462 return (-(atoi(s + offs - 1))); 463 case '+': 464 return (atoi(s + offs - 1)); 465 } 466 467 /* 468 * some aliases: last, first, second, third, fourth 469 */ 470 471 /* last */ 472 if (offs > 4 && !strcasecmp(s + offs - 4, "last")) 473 return (-1); 474 else if (offs > 5 && !strcasecmp(s + offs - 5, "first")) 475 return (+1); 476 else if (offs > 6 && !strcasecmp(s + offs - 6, "second")) 477 return (+2); 478 else if (offs > 5 && !strcasecmp(s + offs - 5, "third")) 479 return (+3); 480 else if (offs > 6 && !strcasecmp(s + offs - 6, "fourth")) 481 return (+4); 482 483 /* no offset detected */ 484 return (0); 485} | |