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 Landleyvoid xcheckrange(long val, long low, long high) 6882895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley{ 697aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *err = "%ld %s than %ld"; 7082895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 717aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (val < low) error_exit(err, val, "less", low); 727aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (val > high) error_exit(err, val, "greater", high); 7382895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley} 7482895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 7582895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley// Worst case scenario toybuf usage: sizeof(struct tm) plus 21 bytes/line 7682895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley// plus 8 lines/month plus 12 months, comes to a bit over 2k of our 4k buffer. 7782895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley 7882895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landleyvoid cal_main(void) 7982895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley{ 807aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley struct tm *tm; 817aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *buf = toybuf; 827aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 837aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optc) { 847aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Conveniently starts zeroed 857aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm = (struct tm *)toybuf; 867aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf += sizeof(struct tm); 877aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 887aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Last argument is year, one before that (if any) is month. 897aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley xcheckrange(tm->tm_year = atol(toys.optargs[--toys.optc]),1,9999); 907aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_year -= 1900; 917aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_mday = 1; 927aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_hour = 12; // noon to avoid timezone weirdness 937aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley if (toys.optc) { 947aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley xcheckrange(tm->tm_mon = atol(toys.optargs[--toys.optc]),1,12); 957aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_mon--; 967aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 977aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // Print 12 months of the year 987aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 997aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else { 1007aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char *bufs[12]; 1017aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley int i, j, k; 1027aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1037aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (i=0; i<12; i++) { 1047aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm->tm_mon=i; 1057aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley mktime(tm); 1067aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley buf = calstrings(bufs[i]=buf, tm); 1077aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1087aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1097aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // 4 rows, 6 lines each, 3 columns 1107aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (i=0; i<4; i++) { 1117aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for (j=0; j<8; j++) { 1127aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley for(k=0; k<3; k++) { 1137aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley char **b = bufs+(k+i*3); 1147aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley *b += printf("%s ", *b); 1157aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1167aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley puts(""); 1177aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1187aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1197aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley return; 1207aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1217aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1227aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley // What day of the week does that start on? 1237aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley mktime(tm); 1247aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1257aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } else { 1267aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley time_t now; 1277aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley time(&now); 1287aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley tm = localtime(&now); 1297aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley } 1307aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley 1317aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley calstrings(buf, tm); 1327aa651a6a4496d848f86de9b1e6b3a003256a01fRob Landley while (*buf) buf += printf("%s\n", buf); 13382895f6cf412a958d71ed1a0eefcebd435e06f31Rob Landley} 134