#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
char day_sym[] = "MTWTFSS";
enum { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec };
int opt_c;
int opt_h;
int
leap_year(int year)
{
if (year % 400 == 0)
return 1;
else
if (year % 100 == 0)
return 0;
else
if (year % 4 == 0)
return 1;
else
return 0;
}
int
days_year(int year)
{
return leap_year(year) ? 366 : 365;
}
int
days_month(int m, int y)
{
/* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
int days[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (m == Feb)
return leap_year(y) ? 29 : 28;
else
return days[m];
}
int
cal(int m, int y)
{
int a, i;
a = Sat;
for (i = 2000; i < y; i++)
a = (a + days_year(i)) % 7;
for (i = 0; i < m; i++)
a = (a + days_month(i, y)) % 7;
return a;
}
void
print_month(int d, int n)
{
int i;
for (i = 0; i < n; i++) {
printf(" %c", day_sym[d++]);
if (d == 7)
d = 0; }
putchar('\n');
}
void
head(void)
{
int i, j;
fputs(" ", stdout);
for (i = 0; i < 3; i++) {
for (j = 0; j < 9; j++)
fputs(" ", stdout);
printf(" %d", i + 1); }
putchar('\n');
fputs(" ", stdout);
for (i = 0; i < 31; i++)
printf(" %d", (i + 1) % 10);
putchar('\n');
}
void
print_range(int from_m, int from_y, int to_m, int to_y)
{
char *mon_name[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
const int f = from_y * 12 + from_m;
const int t = to_y * 12 + to_m;
int i, m, y;
int day = cal(from_m, from_y);
for (i = f; i <= t; i++) {
y = i / 12;
m = i % 12;
fputs(mon_name[m], stdout);
if (opt_h)
printf(" %4d", y);
print_month(day, days_month(m, y));
day = (day + days_month(m, y)) % 7; }
}
void
check_routine(int m, int y)
{
int c, d, i;
for (i = 2000; i <= y; i++) {
c = cal(0, i);
d = days_year(i);
printf("%c(%d) %d %d %d\n", day_sym[c], c, i, d, d % 7); }
for (i = 0; i <= m; i++) {
c = cal(i, y);
d = days_month(i, y);
printf("%c(%d) %d %d %d\n", day_sym[c], c, i, d, d % 7); }
}
int
parse_range(char * const s)
{
int fy, fm, ty, tm;
char *t = s;
fy = strtol(t, &t, 10);
if (*t++ != '-') return 0;
fm = strtol(t, &t, 10);
if (!*t) {
ty = fy, tm = fm; goto L0; }
if (*t++ != '/') goto err;
ty = strtol(t, &t, 10);
if (!*t) {
tm = ty, ty = fy; goto L0; }
if (*t++ != '-') goto err;
tm = strtol(t, &t, 10);
if (*t) goto err;
L0:
if (fm == 0 || fm > 12 || tm == 0 || tm > 12) goto err;
fm--; tm--;
if (fy * 12 + fm > ty * 12 + tm) goto err;
if (opt_c)
check_routine(fm, fy);
print_range(fm, fy, tm, ty);
return 1;
err:
fprintf(stderr, "invalid range: %s\n", s);
return 1;
}
void
print_year(int y)
{
if (opt_c)
check_routine(0, y);
if (!opt_h) {
printf("\n%d\n", y);
head(); }
print_range(0, y, 11, y);
}
int
main(int argc, char **argv)
{
int i, j, y, err = 0;
for (i = 1; i < argc; i++) {
if (*argv[i] == '-')
for (j = 1; argv[i][j]; j++)
switch (argv[i][j]) {
case 'c':
opt_c = 1;
break;
case 'h':
opt_h = 1;
break;
default:
fprintf(stderr, "invalid opt: %c\n", argv[i][j]);
err = 1;
break; }
else if (parse_range(argv[i]))
;
else if ((y = atoi(argv[i])) >= 2000) {
print_year(y); }
else {
fprintf(stderr, "invalid arg: %s\n", argv[i]);
err = 1; } }
return err;
}