17aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley/* cal.c - show calendar. 282895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley * 382895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley * Copyright 2011 Rob Landley <rob@landley.net> 482895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley * 582895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley * See http://opengroup.org/onlinepubs/9699919799/utilities/cal.html 682895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 782895f6cf412a958d71ed1a0eefcebd435e06f31Rob LandleyUSE_CAL(NEWTOY(cal, ">2", TOYFLAG_USR|TOYFLAG_BIN)) 882895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 982895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landleyconfig CAL 107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley bool "cal" 117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley default y 127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley help 137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley usage: cal [[month] year] 14314f19e4d2099eb19824df49d71953946486f78fRob Landley 157aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley Print a calendar. 167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 177aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley With one argument, prints all months of the specified year. 187aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley With two arguments, prints calendar for month and year. 1982895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley*/ 2082895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 2182895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley#include "toys.h" 2282895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 2382895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley// Write calendar into buffer: each line is 20 chars wide, end indicated 2482895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley// by empty string. 2582895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 2682895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landleystatic char *calstrings(char *buf, struct tm *tm) 2782895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley{ 287aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char temp[21]; 297aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley int wday, mday, start, len, line; 307aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 317aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // header 327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley len = strftime(temp, 21, "%B %Y", tm); 337aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley len += (20-len)/2; 347aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf += sprintf(buf, "%*s%*s ", len, temp, 20-len, ""); 357aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf++; 367aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf += sprintf(buf, "Su Mo Tu We Th Fr Sa "); 377aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf++; 387aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 397aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // What day of the week does this month start on? 407aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (tm->tm_mday>1) 417aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley start = (36+tm->tm_wday-tm->tm_mday)%7; 427aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley else start = tm->tm_wday; 437aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 447aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // What day does this month end on? Alas, libc doesn't tell us... 457aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley len = 31; 467aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (tm->tm_mon == 1) { 477aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley int year = tm->tm_year; 487aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley len = 28; 497aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!(year & 3) && !((year&100) && !(year&400))) len++; 507aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else if ((tm->tm_mon+(tm->tm_mon>6 ? 1 : 0)) & 1) len = 30; 517aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 527aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (mday=line=0;line<6;line++) { 537aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (wday=0; wday<7; wday++) { 547aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *pat = " "; 557aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (!mday ? wday==start : mday<len) { 567aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley pat = "%2d "; 577aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley mday++; 587aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 597aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf += sprintf(buf, pat, mday); 607aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 617aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf++; 627aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 637aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 647aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return buf; 6582895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley} 6682895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 6782895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley// Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line 6882895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley// plus 8 lines/month plus 12 months, comes to a bit over 2k of our 4k buffer. 6982895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 7082895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landleyvoid cal_main(void) 7182895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley{ 727aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct tm *tm; 737aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *buf = toybuf; 747aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 757aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optc) { 767aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Conveniently starts zeroed 777aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm = (struct tm *)toybuf; 787aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf += sizeof(struct tm); 797aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 807aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Last argument is year, one before that (if any) is month. 815c6766a3ae30770784d054ffbf47faf290dee80eRob Landley tm->tm_year = atolx_range(toys.optargs[--toys.optc], 1, 9999); 827aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_year -= 1900; 837aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_mday = 1; 847aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_hour = 12; // noon to avoid timezone weirdness 857aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optc) { 865c6766a3ae30770784d054ffbf47faf290dee80eRob Landley tm->tm_mon = atolx_range(toys.optargs[--toys.optc], 1, 12); 877aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_mon--; 887aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 897aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Print 12 months of the year 907aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 917aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else { 927aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *bufs[12]; 937aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley int i, j, k; 947aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 957aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (i=0; i<12; i++) { 967aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_mon=i; 977aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley mktime(tm); 987aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf = calstrings(bufs[i]=buf, tm); 997aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1007aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // 4 rows, 6 lines each, 3 columns 1027aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (i=0; i<4; i++) { 1037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (j=0; j<8; j++) { 1047aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for(k=0; k<3; k++) { 1057aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char **b = bufs+(k+i*3); 1067aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley *b += printf("%s ", *b); 1077aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1087aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley puts(""); 1097aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return; 1127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // What day of the week does that start on? 1157aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley mktime(tm); 1167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1177aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else { 1187aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley time_t now; 1197aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley time(&now); 1207aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm = localtime(&now); 1217aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1227aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1237aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley calstrings(buf, tm); 1247aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley while (*buf) buf += printf("%s\n", buf); 12582895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley} 126