|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Kim Letkeman. ! 7: * ! 8: * Redistribution and use in source and binary forms are permitted ! 9: * provided that: (1) source distributions retain this entire copyright ! 10: * notice and comment, and (2) distributions including binaries display ! 11: * the following acknowledgement: ``This product includes software ! 12: * developed by the University of California, Berkeley and its contributors'' ! 13: * in the documentation or other materials provided with the distribution ! 14: * and in all advertising materials mentioning features or use of this ! 15: * software. Neither the name of the University nor the names of its ! 16: * contributors may be used to endorse or promote products derived ! 17: * from this software without specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: char copyright[] = ! 25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\ ! 26: All rights reserved.\n"; ! 27: #endif /* not lint */ ! 28: ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)cal.c 4.8 (Berkeley) 6/1/90"; ! 31: #endif /* not lint */ ! 32: ! 33: #include <sys/types.h> ! 34: #include <sys/time.h> ! 35: #include <stdio.h> ! 36: #include <ctype.h> ! 37: ! 38: #define THURSDAY 4 /* for reformation */ ! 39: #define SATURDAY 6 /* 1 Jan 1 was a Saturday */ ! 40: #define FIRST_MISSING_DAY 639787 /* 3 Sep 1752 */ ! 41: #define NUMBER_MISSING_DAYS 11 /* 11 day correction */ ! 42: #define SPACE -1 /* used in day array */ ! 43: ! 44: static int days_in_month[2][13] = { ! 45: {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, ! 46: {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, ! 47: }; ! 48: ! 49: static int sep1752[42] = { ! 50: SPACE, SPACE, 1, 2, 14, 15, 16, ! 51: 17, 18, 19, 20, 21, 22, 23, ! 52: 24, 25, 26, 27, 28, 29, 30, ! 53: SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, ! 54: SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, ! 55: SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, ! 56: }, j_sep1752[42] = { ! 57: SPACE, SPACE, 245, 246, 258, 259, 260, ! 58: 261, 262, 263, 264, 265, 266, 267, ! 59: 268, 269, 270, 271, 272, 273, 274, ! 60: SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, ! 61: SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, ! 62: SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, ! 63: }; ! 64: ! 65: static char *month_names[12] = { ! 66: "January", "February", "March", "April", "May", "June", ! 67: "July", "August", "September", "October", "November", "December", ! 68: }; ! 69: ! 70: static char *day_headings = " S M Tu W Th F S"; ! 71: static char *j_day_headings = " S M Tu W Th F S"; ! 72: ! 73: /* leap year -- account for gregorian reformation in 1752 */ ! 74: #define leap_year(yr) \ ! 75: ((yr) <= 1752 ? !((yr) % 4) : \ ! 76: !((yr) % 4) && ((yr) % 100) || !((yr) % 400)) ! 77: ! 78: /* number of centuries since 1700, not inclusive */ ! 79: #define centuries_since_1700(yr) \ ! 80: ((yr) > 1700 ? (yr) / 100 - 17 : 0) ! 81: ! 82: /* number of centuries since 1700 whose modulo of 400 is 0 */ ! 83: #define quad_centuries_since_1700(yr) \ ! 84: ((yr) > 1600 ? ((yr) - 1600) / 400 : 0) ! 85: ! 86: /* number of leap years between year 1 and this year, not inclusive */ ! 87: #define leap_years_since_year_1(yr) \ ! 88: ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr)) ! 89: ! 90: int julian; ! 91: ! 92: main(argc, argv) ! 93: int argc; ! 94: char **argv; ! 95: { ! 96: extern char *optarg; ! 97: extern int optind; ! 98: struct tm *local_time; ! 99: time_t now, time(); ! 100: int ch, month, year, yflag; ! 101: ! 102: yflag = 0; ! 103: while ((ch = getopt(argc, argv, "jy")) != EOF) ! 104: switch(ch) { ! 105: case 'j': ! 106: julian = 1; ! 107: break; ! 108: case 'y': ! 109: yflag = 1; ! 110: break; ! 111: case '?': ! 112: default: ! 113: usage(); ! 114: } ! 115: argc -= optind; ! 116: argv += optind; ! 117: ! 118: switch(argc) { ! 119: case 2: ! 120: if ((month = atoi(*argv++)) <= 0 || month > 12) { ! 121: (void)fprintf(stderr, "cal: illegal month value.\n"); ! 122: exit(1); ! 123: } ! 124: /* FALLTHROUGH */ ! 125: case 1: ! 126: if ((year = atoi(*argv)) <= 0 || year > 9999) { ! 127: (void)fprintf(stderr, "cal: illegal year value.\n"); ! 128: exit(1); ! 129: } ! 130: break; ! 131: case 0: ! 132: (void)time(&now); ! 133: local_time = localtime(&now); ! 134: year = local_time->tm_year + 1900; ! 135: if (!yflag) ! 136: month = local_time->tm_mon + 1; ! 137: break; ! 138: default: ! 139: usage(); ! 140: } ! 141: if (month) ! 142: monthly(month, year); ! 143: else if (julian) ! 144: j_yearly(year); ! 145: else ! 146: yearly(year); ! 147: exit(0); ! 148: } ! 149: ! 150: #define DAY_LEN 3 /* 3 spaces per day */ ! 151: #define J_DAY_LEN 4 /* 4 spaces per day */ ! 152: #define WEEK_LEN 20 /* 7 * 3 - one space at the end */ ! 153: #define J_WEEK_LEN 27 /* 7 * 4 - one space at the end */ ! 154: #define HEAD_SEP 2 /* spaces between day headings */ ! 155: #define J_HEAD_SEP 3 ! 156: ! 157: monthly(month, year) ! 158: int month, year; ! 159: { ! 160: register int col, row; ! 161: register char *p; ! 162: int len, days[42]; ! 163: char lineout[30]; ! 164: ! 165: day_array(month, year, days); ! 166: len = sprintf(lineout, "%s %d", month_names[month - 1], year); ! 167: (void)printf("%*s%s\n%s\n", ! 168: ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "", ! 169: lineout, julian ? j_day_headings : day_headings); ! 170: for (row = 0; row < 6; row++) { ! 171: for (col = 0, p = lineout; col < 7; col++, ! 172: p += julian ? J_DAY_LEN : DAY_LEN) ! 173: ascii_day(p, days[row * 7 + col]); ! 174: trim_trailing_spaces(lineout); ! 175: (void)printf("%s\n", lineout); ! 176: } ! 177: } ! 178: ! 179: j_yearly(year) ! 180: int year; ! 181: { ! 182: register int col, *dp, i, month, row, which_cal; ! 183: register char *p; ! 184: int days[12][42]; ! 185: char lineout[80]; ! 186: ! 187: (void)sprintf(lineout, "%d", year); ! 188: center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0); ! 189: (void)printf("\n\n"); ! 190: for (i = 0; i < 12; i++) ! 191: day_array(i + 1, year, &days[i][0]); ! 192: (void)memset(lineout, ' ', sizeof(lineout) - 1); ! 193: lineout[sizeof(lineout) - 1] = '\0'; ! 194: for (month = 0; month < 12; month += 2) { ! 195: center(month_names[month], J_WEEK_LEN, J_HEAD_SEP); ! 196: center(month_names[month + 1], J_WEEK_LEN, 0); ! 197: (void)printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "", ! 198: j_day_headings); ! 199: for (row = 0; row < 6; row++) { ! 200: for (which_cal = 0; which_cal < 2; which_cal++) { ! 201: p = lineout + which_cal * (J_WEEK_LEN + 2); ! 202: dp = &days[month + which_cal][row * 7]; ! 203: for (col = 0; col < 7; col++, p += J_DAY_LEN) ! 204: ascii_day(p, *dp++); ! 205: } ! 206: trim_trailing_spaces(lineout); ! 207: (void)printf("%s\n", lineout); ! 208: } ! 209: } ! 210: (void)printf("\n"); ! 211: } ! 212: ! 213: yearly(year) ! 214: int year; ! 215: { ! 216: register int col, *dp, i, month, row, which_cal; ! 217: register char *p; ! 218: int days[12][42]; ! 219: char lineout[80]; ! 220: ! 221: (void)sprintf(lineout, "%d", year); ! 222: center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0); ! 223: (void)printf("\n\n"); ! 224: for (i = 0; i < 12; i++) ! 225: day_array(i + 1, year, &days[i][0]); ! 226: (void)memset(lineout, ' ', sizeof(lineout) - 1); ! 227: lineout[sizeof(lineout) - 1] = '\0'; ! 228: for (month = 0; month < 12; month += 3) { ! 229: center(month_names[month], WEEK_LEN, HEAD_SEP); ! 230: center(month_names[month + 1], WEEK_LEN, HEAD_SEP); ! 231: center(month_names[month + 2], WEEK_LEN, 0); ! 232: (void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP, ! 233: "", day_headings, HEAD_SEP, "", day_headings); ! 234: for (row = 0; row < 6; row++) { ! 235: for (which_cal = 0; which_cal < 3; which_cal++) { ! 236: p = lineout + which_cal * (WEEK_LEN + 2); ! 237: dp = &days[month + which_cal][row * 7]; ! 238: for (col = 0; col < 7; col++, p += DAY_LEN) ! 239: ascii_day(p, *dp++); ! 240: } ! 241: trim_trailing_spaces(lineout); ! 242: (void)printf("%s\n", lineout); ! 243: } ! 244: } ! 245: (void)printf("\n"); ! 246: } ! 247: ! 248: /* ! 249: * day_array -- ! 250: * Fill in an array of 42 integers with a calendar. Assume for a moment ! 251: * that you took the (maximum) 6 rows in a calendar and stretched them ! 252: * out end to end. You would have 42 numbers or spaces. This routine ! 253: * builds that array for any month from Jan. 1 through Dec. 9999. ! 254: */ ! 255: day_array(month, year, days) ! 256: register int *days; ! 257: int month, year; ! 258: { ! 259: register int i, day, dw, dm, *p; ! 260: ! 261: dm = days_in_month[leap_year(year)][month]; ! 262: dw = day_in_week(1, month, year); ! 263: if (month == 9 && year == 1752) { ! 264: p = julian ? j_sep1752 : sep1752; ! 265: for (i = 0; i < 42; i++) ! 266: *days++ = *p++; ! 267: return; ! 268: } ! 269: for (i = 42, p = days; i--;) ! 270: *p++ = SPACE; ! 271: day = julian ? day_in_year(1, month, year) : 1; ! 272: while (dm--) ! 273: days[dw++] = day++; ! 274: } ! 275: ! 276: /* ! 277: * day_in_year -- ! 278: * return the 1 based day number within the year ! 279: */ ! 280: day_in_year(day, month, year) ! 281: register int day, month; ! 282: int year; ! 283: { ! 284: register int i, leap; ! 285: ! 286: leap = leap_year(year); ! 287: for (i = 1; i < month; i++) ! 288: day += days_in_month[leap][i]; ! 289: return(day); ! 290: } ! 291: ! 292: /* ! 293: * day_in_week ! 294: * return the 0 based day number for any date from 1 Jan. 1 to ! 295: * 31 Dec. 9999. Assumes the Gregorian reformation eliminates ! 296: * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all ! 297: * missing days. ! 298: */ ! 299: day_in_week(day, month, year) ! 300: int day, month, year; ! 301: { ! 302: long temp; ! 303: ! 304: temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1) ! 305: + day_in_year(day, month, year); ! 306: if (temp < FIRST_MISSING_DAY) ! 307: return((temp - 1 + SATURDAY) % 7); ! 308: if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) ! 309: return(((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); ! 310: return(THURSDAY); ! 311: } ! 312: ! 313: ascii_day(p, day) ! 314: register char *p; ! 315: register int day; ! 316: { ! 317: register int display, val; ! 318: ! 319: if (day == SPACE) { ! 320: memset(p, ' ', julian ? 4 : 3); ! 321: return; ! 322: } ! 323: display = 0; ! 324: if (julian) { ! 325: if (val = day / 100) { ! 326: day %= 100; ! 327: *p++ = val + '0'; ! 328: display = 1; ! 329: } else ! 330: *p++ = ' '; ! 331: } ! 332: val = day / 10; ! 333: if (val || display) ! 334: *p++ = val + '0'; ! 335: else ! 336: *p++ = ' '; ! 337: *p++ = day % 10 + '0'; ! 338: *p = ' '; ! 339: } ! 340: ! 341: trim_trailing_spaces(s) ! 342: register char *s; ! 343: { ! 344: register char *p; ! 345: ! 346: for (p = s; *p; ++p); ! 347: while (p > s && isspace(*--p)); ! 348: if (p > s) ! 349: ++p; ! 350: *p = '\0'; ! 351: } ! 352: ! 353: center(str, len, separate) ! 354: char *str; ! 355: register int len; ! 356: int separate; ! 357: { ! 358: len -= strlen(str); ! 359: (void)printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, ""); ! 360: if (separate) ! 361: (void)printf("%*s", separate, ""); ! 362: } ! 363: ! 364: usage() ! 365: { ! 366: (void)fprintf(stderr, "usage: cal [-jy] [[month] year]\n"); ! 367: exit(1); ! 368: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.