/* * Compute the number of days from date, obey the switch from * Julian to Gregorian as used by UK and her colonies. */ int sndaysb(struct date *d) { if (nswitchb < ndaysj(d)) return (ndaysg(d)); else return (ndaysj(d)); }
/* * Compute the number of days from date, obey the local switch from * Julian to Gregorian if specified by the user. */ int sndaysr(struct date *d) { if (nswitch != 0) if (nswitch < ndaysj(d)) return (ndaysg(d)); else return (ndaysj(d)); else return ndaysg(d); }
/* Compute the day number of Easter Sunday in Julian Calendar */ static int easterodn(int y) { /* * Table for the easter limits in one metonic (19-year) cycle. 21 * to 31 is in March, 1 through 18 in April. Easter is the first * sunday after the easter limit. */ int mc[] = {5, 25, 13, 2, 22, 10, 30, 18, 7, 27, 15, 4, 24, 12, 1, 21, 9, 29, 17}; /* Offset from a weekday to next sunday */ int ns[] = {6, 5, 4, 3, 2, 1, 7}; date dt; int dn; /* Assign the easter limit of y to dt */ dt.d = mc[y % 19]; if (dt.d < 21) dt.m = 4; else dt.m = 3; dt.y = y; /* Return the next sunday after the easter limit */ dn = ndaysj(&dt); return (dn + ns[weekday(dn)]); }
int main(int argc, char *argv[]) { struct djswitch *p, *q; /* to search user defined switch date */ date never = {10000, 1, 1}; /* outside valid range of dates */ date ukswitch = {1752, 9, 2};/* switch date for Great Britain */ date dt; int ch; /* holds the option character */ int m = 0; /* month */ int y = 0; /* year */ int flag_backward = 0; /* user called cal--backward compat. */ int flag_wholeyear = 0; /* user wants the whole year */ int flag_julian_cal = 0; /* user wants Julian Calendar */ int flag_julian_day = 0; /* user wants the Julian day numbers */ int flag_orthodox = 0; /* user wants Orthodox easter */ int flag_easter = 0; /* user wants easter date */ int flag_3months = 0; /* user wants 3 month display (-3) */ int flag_after = 0; /* user wants to see months after */ int flag_before = 0; /* user wants to see months before */ int flag_specifiedmonth = 0;/* user wants to see this month (-m) */ int flag_givenmonth = 0; /* user has specified month [n] */ int flag_givenyear = 0; /* user has specified year [n] */ char *cp; /* character pointer */ char *flag_today = NULL; /* debug: use date as being today */ char *flag_month = NULL; /* requested month as string */ char *flag_highlightdate = NULL; /* debug: date to highlight */ int before, after; const char *locale; /* locale to get country code */ flag_nohighlight = 0; flag_weeks = 0; /* * Use locale to determine the country code, * and use the country code to determine the default * switchdate and date format from the switches table. */ if (setlocale(LC_ALL, "") == NULL) warn("setlocale"); locale = setlocale(LC_TIME, NULL); if (locale == NULL || strcmp(locale, "C") == 0 || strcmp(locale, "POSIX") == 0 || strcmp(locale, "ASCII") == 0 || strcmp(locale, "US-ASCII") == 0) locale = "_US"; q = switches + sizeof(switches) / sizeof(struct djswitch); for (p = switches; p != q; p++) if ((cp = strstr(locale, p->cc)) != NULL && *(cp - 1) == '_') break; if (p == q) { nswitch = ndaysj(&dftswitch->dt); } else { nswitch = ndaysj(&p->dt); dftswitch = p; } /* * Get the filename portion of argv[0] and set flag_backward if * this program is called "cal". */ if (strncmp(basename(argv[0]), "cal", strlen("cal")) == 0) flag_backward = 1; /* Set the switch date to United Kingdom if backwards compatible */ if (flag_backward) nswitchb = ndaysj(&ukswitch); before = after = -1; while ((ch = getopt(argc, argv, "3A:B:Cd:eH:hjJm:Nops:wy")) != -1) switch (ch) { case '3': flag_3months = 1; break; case 'A': if (flag_after > 0) errx(EX_USAGE, "Double -A specified"); flag_after = strtol(optarg, NULL, 10); if (flag_after <= 0) errx(EX_USAGE, "Argument to -A must be positive"); break; case 'B': if (flag_before > 0) errx(EX_USAGE, "Double -A specified"); flag_before = strtol(optarg, NULL, 10); if (flag_before <= 0) errx(EX_USAGE, "Argument to -B must be positive"); break; case 'J': if (flag_backward) usage(); nswitch = ndaysj(&never); flag_julian_cal = 1; break; case 'C': flag_backward = 1; break; case 'N': flag_backward = 0; break; case 'd': flag_today = optarg; break; case 'H': flag_highlightdate = optarg; break; case 'h': flag_nohighlight = 1; break; case 'e': if (flag_backward) usage(); flag_easter = 1; break; case 'j': flag_julian_day = 1; break; case 'm': if (flag_specifiedmonth) errx(EX_USAGE, "Double -m specified"); flag_month = optarg; flag_specifiedmonth = 1; break; case 'o': if (flag_backward) usage(); flag_orthodox = 1; flag_easter = 1; break; case 'p': if (flag_backward) usage(); printcc(); return (0); break; case 's': if (flag_backward) usage(); q = switches + sizeof(switches) / sizeof(struct djswitch); for (p = switches; p != q && strcmp(p->cc, optarg) != 0; p++) ; if (p == q) errx(EX_USAGE, "%s: invalid country code", optarg); nswitch = ndaysj(&(p->dt)); break; case 'w': if (flag_backward) usage(); flag_weeks = 1; break; case 'y': flag_wholeyear = 1; break; default: usage(); } argc -= optind; argv += optind; switch (argc) { case 2: if (flag_easter) usage(); flag_month = *argv++; flag_givenmonth = 1; m = strtol(flag_month, NULL, 10); /* FALLTHROUGH */ case 1: y = atoi(*argv); if (y < 1 || y > 9999) errx(EX_USAGE, "year `%s' not in range 1..9999", *argv); argv++; flag_givenyear = 1; break; case 0: if (flag_today != NULL) { y = strtol(flag_today, NULL, 10); m = strtol(flag_today + 5, NULL, 10); } else { time_t t; struct tm *tm; t = time(NULL); tm = localtime(&t); y = tm->tm_year + 1900; m = tm->tm_mon + 1; } break; default: usage(); } if (flag_month != NULL) { if (parsemonth(flag_month, &m, &y)) { errx(EX_USAGE, "%s is neither a month number (1..12) nor a name", flag_month); } } /* * What is not supported: * -3 with -A or -B * -3 displays 3 months, -A and -B change that behaviour. * -3 with -y * -3 displays 3 months, -y says display a whole year. * -3 with a given year but no given month or without -m * -3 displays 3 months, no month specified doesn't make clear * which three months. * -m with a given month * conflicting arguments, both specify the same field. * -y with -m * -y displays the whole year, -m displays a single month. * -y with a given month * -y displays the whole year, the given month displays a single * month. * -y with -A or -B * -y displays the whole year, -A and -B display extra months. */ /* -3 together with -A or -B. */ if (flag_3months && (flag_after || flag_before)) errx(EX_USAGE, "-3 together with -A and -B is not supported."); /* -3 together with -y. */ if (flag_3months && flag_wholeyear) errx(EX_USAGE, "-3 together with -y is not supported."); /* -3 together with givenyear but no givenmonth. */ if (flag_3months && flag_givenyear && !(flag_givenmonth || flag_specifiedmonth)) errx(EX_USAGE, "-3 together with a given year but no given month is " "not supported."); /* -m together with xx xxxx. */ if (flag_specifiedmonth && flag_givenmonth) errx(EX_USAGE, "-m together with a given month is not supported."); /* -y together with -m. */ if (flag_wholeyear && flag_specifiedmonth) errx(EX_USAGE, "-y together with -m is not supported."); /* -y together with xx xxxx. */ if (flag_wholeyear && flag_givenmonth) errx(EX_USAGE, "-y together a given month is not supported."); /* -y together with -A or -B. */ if (flag_wholeyear && (flag_before > 0 || flag_after > 0)) errx(EX_USAGE, "-y together a -A or -B is not supported."); /* The rest should be fine. */ /* Select the period to display, in order of increasing priority .*/ if (flag_wholeyear || (flag_givenyear && !(flag_givenmonth || flag_specifiedmonth))) { m = 1; before = 0; after = 11; } if (flag_givenyear && flag_givenmonth) { before = 0; after = 0; } if (flag_specifiedmonth) { before = 0; after = 0; } if (flag_before) { before = flag_before; } if (flag_after) { after = flag_after; } if (flag_3months) { before = 1; after = 1; } if (after == -1) after = 0; if (before == -1) before = 0; /* Highlight a specified day or today .*/ if (flag_highlightdate != NULL) { dt.y = strtol(flag_highlightdate, NULL, 10); dt.m = strtol(flag_highlightdate + 5, NULL, 10); dt.d = strtol(flag_highlightdate + 8, NULL, 10); } else { time_t t; struct tm *tm1; t = time(NULL); tm1 = localtime(&t); dt.y = tm1->tm_year + 1900; dt.m = tm1->tm_mon + 1; dt.d = tm1->tm_mday; } highlightdate = sndaysb(&dt); /* And now we finally start to calculate and output calendars. */ if (flag_easter) printeaster(y, flag_julian_cal, flag_orthodox); else if (flag_backward) monthrangeb(y, m, flag_julian_day, before, after); else monthranger(y, m, flag_julian_day, before, after); return (0); }