blob: 113069b692739a12c58550a88d5b548806a098d8 [file] [log] [blame]
#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;
}