Annotation of 43BSDReno/usr.bin/cal/cal.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.