1 /* cal.c - show calendar.
3 * Copyright 2011 Rob Landley <rob@landley.net>
5 * See http://opengroup.org/onlinepubs/9699919799/utilities/cal.html
7 USE_CAL(NEWTOY(cal, ">2", TOYFLAG_USR|TOYFLAG_BIN))
13 usage: cal [[month] year]
17 With one argument, prints all months of the specified year.
18 With two arguments, prints calendar for month and year.
23 // Write calendar into buffer: each line is 20 chars wide, end indicated
26 static char *calstrings(char *buf, struct tm *tm)
29 int wday, mday, start, len, line;
32 len = strftime(temp, 21, "%B %Y", tm);
34 buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, "");
36 buf += sprintf(buf, "Su Mo Tu We Th Fr Sa ");
39 // What day of the week does this month start on?
41 start = (36+tm->tm_wday-tm->tm_mday)%7;
42 else start = tm->tm_wday;
44 // What day does this month end on? Alas, libc doesn't tell us...
46 if (tm->tm_mon == 1) {
47 int year = tm->tm_year;
49 if (!(year & 3) && !((year&100) && !(year&400))) len++;
50 } else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30;
52 for (mday=line=0;line<6;line++) {
53 for (wday=0; wday<7; wday++) {
55 if (!mday ? wday==start : mday<len) {
59 buf += sprintf(buf, pat, mday);
67 // Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line
68 // plus 8 lines/month plus 12 months, comes to a bit over 2k of our 4k buffer.
76 // Conveniently starts zeroed
77 tm = (struct tm *)toybuf;
78 buf += sizeof(struct tm);
80 // Last argument is year, one before that (if any) is month.
81 tm->tm_year = atolx_range(toys.optargs[--toys.optc], 1, 9999);
84 tm->tm_hour = 12; // noon to avoid timezone weirdness
86 tm->tm_mon = atolx_range(toys.optargs[--toys.optc], 1, 12);
89 // Print 12 months of the year
95 for (i=0; i<12; i++) {
98 buf = calstrings(bufs[i]=buf, tm);
101 // 4 rows, 6 lines each, 3 columns
102 for (i=0; i<4; i++) {
103 for (j=0; j<8; j++) {
105 char **b = bufs+(k+i*3);
106 *b += printf("%s ", *b);
114 // What day of the week does that start on?
120 tm = localtime(&now);
124 while (*buf) buf += printf("%s\n", buf);