|  | #include <u.h> | 
|  | #include <libc.h> | 
|  | #include <bio.h> | 
|  |  | 
|  | char	dayw[] = | 
|  | { | 
|  | " S  M Tu  W Th  F  S" | 
|  | }; | 
|  | 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; | 
|  |  | 
|  | 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); | 
|  |  | 
|  | void | 
|  | main(int argc, char *argv[]) | 
|  | { | 
|  | int y, i, j, m; | 
|  |  | 
|  | if(argc > 3) { | 
|  | fprint(2, "usage: cal [month] [year]\n"); | 
|  | exits("usage"); | 
|  | } | 
|  | Binit(&bout, 1, OWRITE); | 
|  |  | 
|  | /* | 
|  | * no arg, print current month | 
|  | */ | 
|  | if(argc == 1) { | 
|  | m = curmo(); | 
|  | y = curyr(); | 
|  | goto xshort; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * one arg | 
|  | *	if looks like a month, print month | 
|  | *	else print year | 
|  | */ | 
|  | if(argc == 2) { | 
|  | y = number(argv[1]); | 
|  | 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[1]); | 
|  | if(m < 0) | 
|  | m = -m; | 
|  | y = number(argv[2]); | 
|  | 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(0); | 
|  |  | 
|  | /* | 
|  | *	print out complete year | 
|  | */ | 
|  | xlong: | 
|  | y = number(argv[1]); | 
|  | 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(0); | 
|  |  | 
|  | 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; | 
|  | 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; | 
|  | } |