ref: a1c3c34c70431447a89fbe08c3475dbfaee7b672
dir: /sys/src/cmd/cal.c/
#include <u.h> #include <libc.h> #include <bio.h> char dayws[] = { "Su M Tu W Th F Sa Su M Tu W Th F Sa", }; char *smon[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", }; char mon[] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, }; char string[432]; Biobuf bout; int wstart; void main(int argc, char *argv[]); int number(char *str); void pstr(char *str, int n); void cal(int m, int y, char *p, int w); int jan1(int yr); int curmo(void); int curyr(void); static void usage(void) { fprint(2, "usage: cal [-s 1..7] [month] [year]\n"); exits("usage"); } void main(int argc, char *argv[]) { int y, i, j, m; char *dayw; ARGBEGIN{ case 's': wstart = atoi(EARGF(usage())); if(wstart < 0 || wstart > 7) usage(); wstart %= 7; break; default: usage(); }ARGEND if(argc > 2) usage(); Binit(&bout, 1, OWRITE); dayw = dayws + 3*wstart; dayw[(3*7)-1] = '\0'; /* * no arg, print current month */ if(argc == 0) { m = curmo(); y = curyr(); goto xshort; } /* * one arg * if looks like a month, print month * else print year */ if(argc == 1) { y = number(argv[0]); if(y < 0) y = -y; if(y >= 1 && y <= 12) { m = y; y = curyr(); goto xshort; } goto xlong; } /* * two arg, month and year */ m = number(argv[0]); if(m < 0) m = -m; y = number(argv[1]); goto xshort; /* * print out just month */ xshort: if(m < 1 || m > 12) goto badarg; if(y < 1 || y > 9999) goto badarg; Bprint(&bout, " %s %ud\n", smon[m-1], y); Bprint(&bout, "%s\n", dayw); cal(m, y, string, 24); for(i=0; i<6*24; i+=24) pstr(string+i, 24); exits(nil); /* * print out complete year */ xlong: if(y<1 || y>9999) goto badarg; Bprint(&bout, "\n\n\n"); Bprint(&bout, " %ud\n", y); Bprint(&bout, "\n"); for(i=0; i<12; i+=3) { for(j=0; j<6*72; j++) string[j] = '\0'; Bprint(&bout, " %.3s", smon[i]); Bprint(&bout, " %.3s", smon[i+1]); Bprint(&bout, " %.3s\n", smon[i+2]); Bprint(&bout, "%s %s %s\n", dayw, dayw, dayw); cal(i+1, y, string, 72); cal(i+2, y, string+23, 72); cal(i+3, y, string+46, 72); for(j=0; j<6*72; j+=72) pstr(string+j, 72); } Bprint(&bout, "\n\n\n"); exits(nil); badarg: Bprint(&bout, "cal: bad argument\n"); } struct { char* word; int val; } dict[] = { "jan", 1, "january", 1, "feb", 2, "february", 2, "mar", 3, "march", 3, "apr", 4, "april", 4, "may", 5, "jun", 6, "june", 6, "jul", 7, "july", 7, "aug", 8, "august", 8, "sep", 9, "sept", 9, "september", 9, "oct", 10, "october", 10, "nov", 11, "november", 11, "dec", 12, "december", 12, 0 }; /* * convert to a number. * if its a dictionary word, * return negative number */ int number(char *str) { int n, c; char *s; for(n=0; s=dict[n].word; n++) if(strcmp(s, str) == 0) return -dict[n].val; n = 0; s = str; while(c = *s++) { if(c<'0' || c>'9') return 0; n = n*10 + c-'0'; } return n; } void pstr(char *str, int n) { int i; char *s; s = str; i = n; while(i--) if(*s++ == '\0') s[-1] = ' '; i = n+1; while(i--) if(*--s != ' ') break; s[1] = '\0'; Bprint(&bout, "%s\n", str); } void cal(int m, int y, char *p, int w) { int d, i; char *s; s = p; d = jan1(y); mon[2] = 29; mon[9] = 30; switch((jan1(y+1)+7-d)%7) { /* * non-leap year */ case 1: mon[2] = 28; break; /* * 1752 */ default: mon[9] = 19; break; /* * leap year */ case 2: ; } for(i=1; i<m; i++) d += mon[i]; d += 7 - wstart; d %= 7; s += 3*d; for(i=1; i<=mon[m]; i++) { if(i==3 && mon[m]==19) { i += 11; mon[m] += 11; } if(i > 9) *s = i/10+'0'; s++; *s++ = i%10+'0'; s++; if(++d == 7) { d = 0; s = p+w; p = s; } } } /* * return day of the week * of jan 1 of given year */ int jan1(int yr) { int y, d; /* * normal gregorian calendar * one extra day per four years */ y = yr; d = 4+y+(y+3)/4; /* * julian calendar * regular gregorian * less three days per 400 */ if(y > 1800) { d -= (y-1701)/100; d += (y-1601)/400; } /* * great calendar changeover instant */ if(y > 1752) d += 3; return d%7; } /* * system dependent * get current month and year */ int curmo(void) { Tm *tm; tm = localtime(time(0)); return tm->mon+1; } int curyr(void) { Tm *tm; tm = localtime(time(0)); return tm->year+1900; }