| /* cal.c - show calendar. |
| * |
| * Copyright 2011 Rob Landley <rob@landley.net> |
| * |
| * See http://opengroup.org/onlinepubs/9699919799/utilities/cal.html |
| |
| USE_CAL(NEWTOY(cal, ">2", TOYFLAG_USR|TOYFLAG_BIN)) |
| |
| config CAL |
| bool "cal" |
| default y |
| help |
| usage: cal [[month] year] |
| |
| Print a calendar. |
| |
| With one argument, prints all months of the specified year. |
| With two arguments, prints calendar for month and year. |
| */ |
| |
| #include "toys.h" |
| |
| // Write calendar into buffer: each line is 20 chars wide, end indicated |
| // by empty string. |
| |
| static char *calstrings(char *buf, struct tm *tm) |
| { |
| char temp[21]; |
| int wday, mday, start, len, line; |
| |
| // header |
| len = strftime(temp, 21, "%B %Y", tm); |
| len += (20-len)/2; |
| buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, ""); |
| buf++; |
| buf += sprintf(buf, "Su Mo Tu We Th Fr Sa "); |
| buf++; |
| |
| // What day of the week does this month start on? |
| if (tm->tm_mday>1) |
| start = (36+tm->tm_wday-tm->tm_mday)%7; |
| else start = tm->tm_wday; |
| |
| // What day does this month end on? Alas, libc doesn't tell us... |
| len = 31; |
| if (tm->tm_mon == 1) { |
| int year = tm->tm_year; |
| len = 28; |
| if (!(year & 3) && !((year&100) && !(year&400))) len++; |
| } else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30; |
| |
| for (mday=line=0;line<6;line++) { |
| for (wday=0; wday<7; wday++) { |
| char *pat = " "; |
| if (!mday ? wday==start : mday<len) { |
| pat = "%2d "; |
| mday++; |
| } |
| buf += sprintf(buf, pat, mday); |
| } |
| buf++; |
| } |
| |
| return buf; |
| } |
| |
| // Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line |
| // plus 8 lines/month plus 12 months, comes to a bit over 2k of our 4k buffer. |
| |
| void cal_main(void) |
| { |
| struct tm *tm; |
| char *buf = toybuf; |
| |
| if (toys.optc) { |
| // Conveniently starts zeroed |
| tm = (struct tm *)toybuf; |
| buf += sizeof(struct tm); |
| |
| // Last argument is year, one before that (if any) is month. |
| tm->tm_year = atolx_range(toys.optargs[--toys.optc], 1, 9999); |
| tm->tm_year -= 1900; |
| tm->tm_mday = 1; |
| tm->tm_hour = 12; // noon to avoid timezone weirdness |
| if (toys.optc) { |
| tm->tm_mon = atolx_range(toys.optargs[--toys.optc], 1, 12); |
| tm->tm_mon--; |
| |
| // Print 12 months of the year |
| |
| } else { |
| char *bufs[12]; |
| int i, j, k; |
| |
| for (i=0; i<12; i++) { |
| tm->tm_mon=i; |
| mktime(tm); |
| buf = calstrings(bufs[i]=buf, tm); |
| } |
| |
| // 4 rows, 6 lines each, 3 columns |
| for (i=0; i<4; i++) { |
| for (j=0; j<8; j++) { |
| for(k=0; k<3; k++) { |
| char **b = bufs+(k+i*3); |
| *b += printf("%s ", *b); |
| } |
| puts(""); |
| } |
| } |
| return; |
| } |
| |
| // What day of the week does that start on? |
| mktime(tm); |
| |
| } else { |
| time_t now; |
| time(&now); |
| tm = localtime(&now); |
| } |
| |
| calstrings(buf, tm); |
| while (*buf) buf += printf("%s\n", buf); |
| } |