123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- /*
- * Calendar program - one page per month (writes to standard output)
- *
- * calen [month] year [len] [-o]
- *
- * If one of the numeric arguments {month, year, len} is specified, it
- * is assumed to be the year; calendar generated is for entire year.
- * (Note: Unlike the UN*X 'cal', nn is treated as 19nn.)
- *
- * If two numeric arguments are specified, first is assumed to be the
- * month (1-12) and second the year; calendar generated is for that
- * month/year only.
- *
- * If all are specified, calendar generated is for 'len' consecutive
- * months starting at month/year.
- *
- * If last argument is '-o' flag, output will contain backspaces and
- * overstrikes to emphasize month and year. (Not all printers can
- * handle this; check local conventions before printing. If using
- * 'lp' on PWB, use its '-o' flag to convert the backspaces to
- * overstruck lines.)
- *
- * Author: AW Rogers
- *
- * Originally written in Fortran-IV on GE Timesharing, 10/65
- * Converted to C/UN*X, 3/83
- */
- /*
- * Constant definitions:
- */
- #define MIN 1753 /* Valid years (1753: start of Gregorian calendar) */
- #define MAX 9999
- #define JAN 1 /* Significant months and weekdays */
- #define DEC 12
- #define SUN 0
- #define SAT 6
- #define SINGLE "*" /* Normal and overstrike (XIH*) character sequences */
- #define OVERSTRIKE "X\bI\bH\b*"
- /*
- * Macro definitions:
- */
- #define day_of_week(I) ((I) % 7)
- /*
- * Global declarations:
- */
- char output_seq[8]; /* either SINGLE or OVERSTRIKE; used in PrintChar */
- /*
- * Main(argc, argv)
- *
- * Gets and checks command line arguments; prints desired calendar(s)
- */
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int mon, year, len; /* Command line arguments */
- /*
- * Get and verify command line arguments (see above)
- */
- /* Check for -o as last command line argument (ignore erroneous flags) */
- if (argv[argc-1][0] == '-' && argv[--argc][1] == 'o')
- strcpy(output_seq, OVERSTRIKE);
- else
- strcpy(output_seq, SINGLE);
- /* Supply defaults for numeric arguments as described above */
- switch (argc) {
- case 2: /* 1 argument supplied (year) */
- sscanf(argv[1], "%d", &year);
- mon = JAN;
- len = 12;
- break;
- case 3: /* 2-3 arguments supplied (mon year [len]) */
- case 4:
- sscanf(argv[1], "%d", &mon);
- sscanf(argv[2], "%d", &year);
- if (argc == 3)
- len = 1;
- else
- sscanf(argv[3], "%d", &len);
- break;
- default:
- printf("usage: %s [month] year [len] [-o]\n", argv[0]);
- return;
- } /* end switch */
- /* Validate month and year; quit if invalid */
- if (year > 0 && year < 100) /* Convert nn to 19nn first */
- year += 1900;
- if (year < MIN || year > MAX || mon < JAN || mon > DEC) {
- printf("valid months: %d..%d; valid years: %d..%d\n", JAN, DEC,
- MIN, MAX);
- return;
- }
- /*
- * Main loop: prints calendar for each requested month
- */
- while (len-- > 0) {
- PrintCal(mon, year);
- /* Prepare for next month's calendar */
- if (++mon > DEC) { /* Bump month (and year) */
- mon = JAN;
- if (++year > MAX) /* Quit if year too big */
- return;
- }
- } /* end calendar generation loop */
- } /* end main */
- /*
- * PrintCal(mon, year)
- *
- * Prints calendar for specified month and year (assumed valid)
- */
- PrintCal(mon, year)
- int mon, year;
- {
- int i, j, k, /* General-purpose loop indices */
- start, end, /* Range of calendar boxes containing dates */
- date = 0, /* Date to print inside box */
- chars; /* Length of current month name */
- static char blanks[36] = " ";
- /* String of blanks for centering heading */
- char digits[5], /* Individual digits of year (for printing) */
- *padding; /* Pointer to effective start of 'blanks' */
- /*
- * Names and lengths of months (first element is dummy):
- */
- static struct {
- char *name; /* name of month */
- char len[2]; /* number of days (non-leap, leap) */
- char first[2]; /* first of month wrt 1/1 (same) */
- } month[13] = { {"", {0,0}, {0,0}},
- {"JANUARY", {31,31}, {0,0}}, {"FEBRUARY", {28,29}, {3,3}},
- {"MARCH", {31,31}, {3,4}}, {"APRIL", {30,30}, {6,0}},
- {"MAY", {31,31}, {1,2}}, {"JUNE" , {30,30}, {4,5}},
- {"JULY", {31,31}, {6,0}}, {"AUGUST", {31,31}, {2,3}},
- {"SEPTEMBER", {30,30}, {5,6}}, {"OCTOBER", {31,31}, {0,1}},
- {"NOVEMBER", {30,30}, {3,4}}, {"DECEMBER", {31,31}, {5,6}}};
- /*
- * Names of weekdays, centered (roughly) in 9-character field:
- */
- static char weekday[7][10] = {" SUNDAY ", "MONDAY ", " TUESDAY ",
- "WEDNESDAY", "THURSDAY ", " FRIDAY ", "SATURDAY "};
- /*
- * 5 x 7 dot-matrix representations of letters A-Z and digits 0-9.
- * Printed as large characters (using ' ' and '*'); see PrintChar.
- */
- static char large_letters[26][7] = {
- 14,17,17,31,17,17,17, 30,17,17,30,17,17,30, 14,17,16,16,16,17,14,
- 30,17,17,17,17,17,30, 31,16,16,30,16,16,31, 31,16,16,30,16,16,16,
- 14,17,16,23,17,17,14, 17,17,17,31,17,17,17, 31,4,4,4,4,4,31,
- 1,1,1,1,1,17,14, 17,18,20,24,20,18,17, 16,16,16,16,16,16,31,
- 17,27,21,21,17,17,17, 17,17,25,21,19,17,17, 14,17,17,17,17,17,14,
- 30,17,17,30,16,16,16, 14,17,17,17,21,18,13, 30,17,17,30,20,18,17,
- 14,17,16,14,1,17,14, 31,4,4,4,4,4,4, 17,17,17,17,17,17,14,
- 17,17,17,17,17,10,4, 17,17,17,17,21,21,10, 17,17,10,4,10,17,17,
- 17,17,17,14,4,4,4, 31,1,2,4,8,16,31};
- static char large_digits[10][7] = {
- 14,17,17,17,17,17,14, 2,6,10,2,2,2,31, 14,17,2,4,8,16,31,
- 14,17,1,14,1,17,14, 2,6,10,31,2,2,2, 31,16,16,30,1,17,14,
- 14,17,16,30,17,17,14, 31,1,2,4,8,16,16, 14,17,17,14,17,17,14,
- 14,17,17,15,1,17,14};
- /*
- * Initialize starting weekday of first month (first box to contain a
- * date) and digits in year (for printing in 5x7 format):
- */
- start = year + (year - 1)/4 - (year - 1)/100 + (year - 1)/400;
- start = day_of_week(start + month[mon].first[IsLeap(year)]);
- sprintf(digits, "%4d", year);
- /*
- * Print heading with month and year in large letters/digits
- */
- printf("\f\n\n\n");
- SolidLine(2);
- BorderLine(2);
- /* Create a string of blanks for centering month/year */
- chars = strlen(month[mon].name);
- padding = &blanks[3 * (chars - 3)];
- /* Print 7 lines containing the month and year in large characters */
- for (j = 0; j <= 6; ++j) {
- printf(" **%s", padding);
- for (k = 0; k <= chars - 1; ++k) /* Letters in month name */
- PrintChar(large_letters[month[mon].name[k] - 'A'][j]);
- printf("%12s", " ");
- for (k = 0; k <= 3; ++k) /* Digits in year */
- PrintChar(large_digits[digits[k] - '0'][j]);
- printf(" %s**\n", padding);
- }
- /* Print names of weekdays above calendar boxes */
- BorderLine(2);
- SolidLine(2);
- BoxLine(1);
- printf(" **");
- for (j = SUN; j <= SAT; ++j)
- printf("%13s%5s", weekday[j], "*");
- printf("*\n");
- /*
- * Print body of calendar
- */
- end = start + month[mon].len[IsLeap(year)] - 1; /* Last date to print */
- /* Print first 5 weeks of calendar */
- for (j = 0; j <= 34; ++j) {
- if (day_of_week(j) == SUN) { /* Top and left border */
- BoxLine(1);
- SolidLine(1);
- printf(" **");
- }
- if (j >= start && j <= end) /* Date or blank */
- printf("%3d%15s", ++date, "*");
- else
- printf("%18s", "*");
- if (day_of_week(j) == SAT) { /* Right border and bottom */
- printf("*\n");
- BoxLine(5);
- }
- }
- /* Print last line (with 30/31 if needed) and bottom border */
- printf(" **");
- for (j = 35; j <= 41; ++j)
- if (j <= end) /* Print date or blank */
- printf("%16d%2s", ++date, "*");
- else
- printf("%18s", "*");
- printf("*\n");
- SolidLine(2);
- } /* end PrintCal */
- /*
- * IsLeap(y)
- *
- * Return 1 if year y is leap; 0 if not
- */
- int IsLeap(y)
- int y;
- {
- return y % 4 == 0 && y % 100 != 0 || y % 400 == 0;
- } /* end IsLeap */
- /*
- * PrintChar(i)
- *
- * Prints least significant 6 bits of i in binary representation,
- * using ' ' for 0 and '*' for 1.
- */
- PrintChar(i)
- char i;
- {
- int msk = 32; /* Output field width = log2(msk)+1 = 6 */
- for (; msk > 0; msk /= 2)
- if (i & msk)
- printf(output_seq); /* Globally defined */
- else
- printf(" ");
- } /* end PrintChar */
- /*
- * BorderLine(n)
- *
- * Print n border lines (** 125 spaces **)
- */
- BorderLine(n)
- int n;
- {
- static char c[] = "**";
- while (n--)
- printf(" %2s%127s\n", c, c);
- } /* end BorderLine */
- /*
- * BoxLine(n)
- *
- * Print n box lines (** 17 spaces * 17 spaces .. **)
- */
- BoxLine(n)
- int n;
- {
- static char c[] = "*";
- while (n--)
- printf(" **%18s%18s%18s%18s%18s%18s%18s*\n", c, c, c, c, c, c, c);
- } /* end BoxLine */
- /*
- * SolidLine(n)
- *
- * Print n solid lines (129 *)
- */
- SolidLine(n)
- int n;
- {
- static char c[] = "*******************************************";
- while (n--)
- printf(" %43s%43s%43s\n", c, c, c);
- } /* end SolidLine */
|