/* * C A L E N D A R * * Usage: * calend MM If small, it's a month, if large, a year. * or * calend YYYY MM year/month * or * calend MM YYYY */ /*)BUILD */ #include #include #ifdef decus int $$narg = 1; /* Don't prompt */ #endif #define EOS 0 #define MWIDTH (7*3 + 3) /* Bytes to print a month */ #define WPERMO 6 /* Max. weeks per month */ #define LWIDTH 72 /* Line width */ #define MPERLIN (LWIDTH / MWIDTH) /* Three months per line */ #define WWIDTH (LWIDTH / MPERLIN) /* Bytes in one week */ #define BUFSIZ (WPERMO * LWIDTH) /* Buffer dimension */ char *weekday = " S M Tu W Th F S"; char *monthname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; char buffer[BUFSIZ]; main(argc, argv) int argc; char *argv[]; { register int month; register int year; register int arg1val; int arg1len; int arg2val; int tvec[2]; struct tm *tm; time(&tvec[0]); tm = localtime(&tvec[0]); year = tm->tm_year + 1900; month = tm->tm_mon + 1; if (argc <= 1) /* * No arguments mean do last, this, and next month */ do3months(year, month); else { arg1val = atoi(argv[1]); arg1len = strlen(argv[1]); if (argc == 2) { /* * Only one argument, if small, it's a month. If * large, it's a year. Note: * calend 0082 Year '82 * calend 82 Year 1982 */ if (arg1len <= 2 && arg1val <= 12) do3months(year, arg1val); else { if (arg1len <= 2 && arg1val > 0 && arg1val <= 99) arg1val += 1900; doyear(arg1val); } } else { /* * Two arguments, allow 1980 12 or 12 1980 */ arg2val = atoi(argv[2]); if (arg1len > 2) do3months(arg1val, arg2val); else do3months(arg2val, arg1val); } } } doyear(year) int year; /* * Print a calendar for an entire year. */ { register int month; register int windex; /* Week index */ if (year < 1 || year > 9999) usage("year: %d\n", year); printf("\n\n\n%35d\n\n", year); for (month = 1; month <= 12; month += MPERLIN) { zero(buffer, sizeof buffer); printf("%12s%23s%23s\n", monthname[month-1], monthname[month], monthname[month+1]); printf("%s %s %s\n", weekday, weekday, weekday); calendar(year, month+0, &buffer[(MWIDTH-1)*0], LWIDTH); calendar(year, month+1, &buffer[(MWIDTH-1)*1], LWIDTH); calendar(year, month+2, &buffer[(MWIDTH-1)*2], LWIDTH); for (windex = 0; windex < (WPERMO * LWIDTH); windex += LWIDTH) out(&buffer[windex], LWIDTH); } printf("\n\n\n"); } domonth(year, month) int year; int month; /* * Do one specific month -- note: no longer used */ { register int windex; if (year < 1 || year > 9999) usage("Bad year: %d\n", year); if (month <= 0 || month > 12) usage("month: %d\n", month); printf("%9s%5d\n\n%s\n", monthname[month-1], year, weekday); calendar(year, month, buffer, WWIDTH); for (windex = 0; windex < (WPERMO * WWIDTH); windex += WWIDTH) out(&buffer[windex], WWIDTH); printf("\n\n"); } do3months(thisyear, thismonth) int thisyear; register int thismonth; /* * Do last month, this month, and next months. The parameters * are guaranteed accurate. (and year will not be less than 2 nor * greater than 9998). */ { register int windex; /* Week index */ int lastmonth; int lastyear; int nextmonth; int nextyear; lastyear = nextyear = thisyear; if ((lastmonth = thismonth - 1) == 0) { lastmonth = 12; lastyear--; } if ((nextmonth = thismonth + 1) == 13) { nextmonth = 1; nextyear++; } printf("%9s%5d%18s%5d%18s%5d\n", monthname[lastmonth - 1], lastyear, monthname[thismonth - 1], thisyear, monthname[nextmonth - 1], nextyear); printf("%s %s %s\n", weekday, weekday, weekday); calendar(lastyear, lastmonth, &buffer[(MWIDTH-1)*0], LWIDTH); calendar(thisyear, thismonth, &buffer[(MWIDTH-1)*1], LWIDTH); calendar(nextyear, nextmonth, &buffer[(MWIDTH-1)*2], LWIDTH); for (windex = 0; windex < (WPERMO * LWIDTH); windex += LWIDTH) out(&buffer[windex], LWIDTH); printf("\n\n\n"); } out(text, len) char *text; int len; /* * Clean up and output this line */ { register char *firstp; register char *lastp; lastp = &text[len]; for (firstp = text; firstp < lastp; firstp++) { if (*firstp == EOS) *firstp = ' '; } while (lastp > text && *--lastp == ' '); lastp[1] = EOS; printf("%s\n", text); } usage(format, args) char *format; int args; /* * Fatal parameter error */ { fprintf(stderr, "Calendar parameter error: "); #ifdef decus $$prnt(format, &args, stderr); #else _doprnt(format, &args, stderr); #endif fprintf(stderr, "Usage: \"calend month\" or \"calend year month\"\n"); fprintf(stderr, "Year and month are integers.\n"); exit(1); } /* * Actually generate a calendar */ static char monthdays[] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* Thirty days hath september */ /* Except for 1752 */ calender(year, month, outbuf, offset) int year; int month; char *outbuf; /* Output goes here */ int offset; /* "Distance" to next month */ /* * Build the calendar for this year/month */ { register char *outp; register int dow; /* Day of week */ register int day; /* Day in month */ outp = outbuf; dow = jan1(year); monthdays[2] = 29; /* Assume leap year */ monthdays[9] = 30; /* Assume no magic */ switch((jan1(year + 1) + 7 - dow) % 7) { case 2: /* * Leap year if jan 1 of next year is two days after * this year's jan 1 */ break; case 1: /* * Not a leap year if jan 1 of next year is the next day * after jan 1 of this year. */ monthdays[2] = 28; break; default: /* * Magic year of 1752 when September lost 11 days. */ monthdays[9] = 19; break; } for (day = 1; day < month; day++) dow += monthdays[day]; dow %= 7; /* Weekday of first of month */ outp += (dow * 3); /* Where to start in calendar */ for (day = 1; day <= monthdays[month]; day++) { if (day == 3 && monthdays[month] == 19) { /* * It's magic (September 3 became September 14) * And September 1752 really did have 30 days. */ day += 11; monthdays[month] += 11; } if (day > 9) *outp = (day / 10) + '0'; outp++; *outp++ = (day % 10) + '0'; outp++; if (++dow >= 7) { /* * Sunday, rotate to the next line */ dow = 0; outp = &outbuf[offset]; outbuf = outp; } } } jan1(year) register int year; /* * Return day that jan 1 falls on for this year. */ { register int day; /* * Gregorian calendar: one extra day per four years. */ day = year + 4 + (year + 3) / 4; /* * Julian calendar: Gregorian less three days per 400 */ if (year > 1800) { day -= ((year - 1701) / 100); day += ((year - 1601) / 400); } /* * Calendar changeover year (valid in America only). */ if (year > 1752) day += 3; return (day % 7); }