123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- /*
- * 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 <stdio.h>
- #include <sys/time.h>
- #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) {
- bzero(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 */
- calendar(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);
- }
|