Annotation of coherent/d/bin/cal.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Print calendar for specified year (and month).
                      3:  * Allows month to be numeric or alphabetic.
                      4:  */
                      5: 
                      6: #include <stdio.h>
                      7: #include <ctype.h>
                      8: #include <time.h>
                      9: 
                     10: #define        GREGYEAR 1752           /* Year of start of Gregorian calendar */
                     11: #define        GREGMON  SEP            /* Month of above */
                     12: #define        GREGDAY 3               /* day of month of changeover */
                     13: #define        GREGADJ 11              /* Adjustment of cal. (days) for Gregorian */
                     14:        /* The calendar skipped 11 days after
                     15:         * September 3, 1752 in England.
                     16:         * That made the date jump 12 days
                     17:         * forward rather than the usual 1.
                     18:         * The original Gregorian reform was in
                     19:         * 1582, at which time only 10 days were
                     20:         * suppressed.  France and Russia adopted
                     21:         * the Gregorian calendar after 1752.
                     22:         * My calculations, which don't make
                     23:         * complete sense, suggest that the
                     24:         * corrections would be:
                     25:         *      12 days after 1800
                     26:         *      13 days after 1900
                     27:         * and  14 days after 2100
                     28:         * because the Gregorian calendar skips
                     29:         * leap years which fall on century years
                     30:         * unless they are quadracents and not
                     31:         * 4000 AD.
                     32:         */
                     33: #define        TMYBIAS 1900            /* bias of year field in struct tm */
                     34: 
                     35: char   *mnames[] = {
                     36:        "January", "February", "March", "April", "May", "June",
                     37:        "July", "August", "September", "October", "November", "December"
                     38: };
                     39: 
                     40: /*
                     41:  * Days per month array (non-leap).
                     42:  * January is at dpm[1].
                     43:  */
                     44: char   dpm[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                     45: 
                     46: char   dayhead[] = " Su Mo Tu We Th Fr Sa";
                     47: 
                     48: #define        DAYWIDTH        (sizeof dayhead -1)
                     49: #define        GAP     5                       /* Gap between months */
                     50: #define        CENTRE  ((3*DAYWIDTH+2*GAP)/2+2) /* Centred 4 digit year pos. */
                     51: #define        MPL     3                       /* Months per line */
                     52: #define        JAN     1
                     53: #define        FEB     2
                     54: #define        MAR     3
                     55: #define        APR     4
                     56: #define        MAY     5
                     57: #define        JUN     6
                     58: #define        JUL     7
                     59: #define        AUG     8
                     60: #define        SEP     9
                     61: #define        OCT     10
                     62: #define        NOV     11
                     63: #define        DEC     12
                     64: 
                     65: 
                     66: char   caldays[MPL][6][7],             /* 3 per line, 6 lines, 7 days */
                     67:        outbuf[BUFSIZ];                 /* stdout setbuf */
                     68: int    baseday;                        /* Weekday of current year's Jan. 1 */
                     69: 
                     70: main(argc, argv)
                     71: register char  *argv[];
                     72: {
                     73:        int             month;
                     74:        unsigned        year;
                     75:        struct tm       *now;
                     76:        long            intime;
                     77:        long            time();
                     78: 
                     79:        setbuf(stdout, outbuf);
                     80:        intime = time(NULL);
                     81:        now = localtime(&intime);
                     82:        month = 0;
                     83:        year = now->tm_year + TMYBIAS;
                     84:        ++argv;
                     85:        switch (argc) {
                     86:        case 1:
                     87:                month = now->tm_mon + 1;
                     88:                break;
                     89:        case 2:
                     90:                if (isdigit(**argv))
                     91:                        year = atoi(*argv);
                     92:                else
                     93:                        month = getmon(*argv);
                     94:                break;
                     95:        case 3:
                     96:                if (!isdigit(*argv[0]))
                     97:                        month = getmon(*argv++);
                     98:                else if (isdigit(*argv[1])) {
                     99:                        month = atoi(*argv++);
                    100:                        if (month == 0)
                    101:                                month = -1;
                    102:                } else
                    103:                        month = getmon(argv[1]);
                    104:                year = atoi(*argv);
                    105:                break;
                    106:        default:
                    107:                usage();
                    108:        }
                    109:        if (month < 0 || month > 12 || year <= 0 || year > 9999)
                    110:                usage();
                    111:        cal(year, month);
                    112:        exit(0);
                    113: }
                    114: 
                    115: /*
                    116:  * Produce a calendar for the specifed year and month.
                    117:  * (If month is zero, then do whole year.)
                    118:  * Setup baseday for fillcal to speed it up a lot.
                    119:  */
                    120: cal(yr, mon)
                    121: {
                    122:        register xmon, pos;
                    123:        register wday;
                    124: 
                    125:        /*
                    126:         * Start at 1 January, 1 which was a Saturday.
                    127:         */
                    128:        wday = 6;
                    129:        for (pos=1; pos<yr; pos++) {
                    130:                if (pos == GREGYEAR)
                    131:                        wday -= GREGADJ;
                    132:                wday = (wday + (isleap(pos) ? 366 : 365)) % 7;
                    133:        }
                    134:        baseday = wday;
                    135:        if (mon != 0)  {
                    136:                fillcal(0, mon, yr);
                    137:                outcal(mon, 1);
                    138:        } else {
                    139:                printf("\n%*d\n", CENTRE, yr);
                    140:                pos = 0;
                    141:                for (xmon = 1; xmon <= 12; xmon++) {
                    142:                        fillcal(pos, xmon, yr);
                    143:                        if (++pos >= MPL) {
                    144:                                outcal(xmon-MPL+1, MPL);
                    145:                                pos = 0;
                    146:                        }
                    147:                }
                    148:        }
                    149: }
                    150: 
                    151: /*
                    152:  * Fill the caldays array element for the particular month
                    153:  * and year specified.
                    154:  */
                    155: fillcal(pos, month, year)
                    156: {
                    157:        register i, j, day;
                    158:        int wday, special, mdays;
                    159: 
                    160:        for (i=0; i<6; i++)
                    161:                for (j=0; j<7; j++)
                    162:                        caldays[pos][i][j] = 0;
                    163:        wday = baseday;
                    164:        dpm[FEB] = isleap(year) ? 29 : 28;
                    165:        special = (year==GREGYEAR);
                    166:        for (i=1; i<month; i++) {
                    167:                if (special && i==GREGMON)
                    168:                        wday -= GREGADJ;
                    169:                wday = (wday + dpm[i]) % 7;
                    170:        }
                    171:        special = (special && month==GREGMON);
                    172:        mdays = dpm[month];
                    173:        i = 0;
                    174:        j = wday;
                    175:        for (day = 1; day <= mdays; day++) {
                    176:                caldays[pos][i][j] = day;
                    177:                if (special && day==GREGDAY)
                    178:                        day += GREGADJ;
                    179:                if (++j >= 7) {
                    180:                        j = 0;
                    181:                        i++;
                    182:                }
                    183:        }
                    184: }
                    185: 
                    186: /*
                    187:  * Put out `n' months from caldays, starting at month `mon'.
                    188:  */
                    189: outcal(mon, n)
                    190: {
                    191:        register i, j, k;
                    192:        int left, cent;
                    193:        int val;
                    194:        char *name;
                    195: 
                    196:        mon--;
                    197:        lput('\n');
                    198:        for (i=1; i<=n; i++) {
                    199:                name = mnames[mon++];
                    200:                cent = strlen(name);
                    201:                left = (DAYWIDTH-cent)/2;
                    202:                spaceover(left);
                    203:                lputs(name);
                    204:                spaceover(DAYWIDTH+GAP-left-cent);
                    205:        }
                    206:        lput('\n');
                    207:        for (i=1; i<=n; i++) {
                    208:                lputs(dayhead);
                    209:                spaceover(GAP);
                    210:        }
                    211:        lput('\n');
                    212:        for (j=0; j<6; j++) {
                    213:                for (i=0; i<n; i++) {
                    214:                        for (k=0; k<7; k++) {
                    215:                                lput(' ');
                    216:                                val = caldays[i][j][k];
                    217:                                lput(val>=10 ? val/10 + '0' : ' ');
                    218:                                if (val)
                    219:                                        lput(val%10 + '0');
                    220:                                else
                    221:                                        lput(' ');
                    222:                        }
                    223:                        spaceover(GAP);
                    224:                }
                    225:                lput('\n');
                    226:        }
                    227: }
                    228: 
                    229: /*
                    230:  * Put out calendar characters saving them up until a
                    231:  * newline so that trailing blanks can be stripped.
                    232:  */
                    233: 
                    234: static char    lline[100];
                    235: static char    *lp = lline;
                    236: lput(c)
                    237: register c;
                    238: {
                    239:        register char *cp;
                    240: 
                    241:        if (c != '\n')
                    242:                *lp++ = c;
                    243:        else {
                    244:                for (cp = lp; *--cp == ' '; )
                    245:                        ;
                    246:                *++cp = '\n';
                    247:                *++cp = '\0';
                    248:                printf("%s", lp = lline);
                    249:        }
                    250: }
                    251: 
                    252: /*
                    253:  * Put out a string using `lput'.
                    254:  */
                    255: lputs(s)
                    256: register char *s;
                    257: {
                    258:        while (*s != '\0')
                    259:                lput(*s++);
                    260: }
                    261: 
                    262: spaceover(n)
                    263: register n;
                    264: {
                    265:        if (n>0)
                    266:                do {
                    267:                        lput(' ');
                    268:                } while (--n);
                    269: }
                    270: 
                    271: /*
                    272:  * Return 1 on leap years; 0 otherwise.
                    273:  */
                    274: isleap(yr)
                    275: register yr;
                    276: {
                    277:        if (yr<=GREGYEAR)
                    278:                return (yr%4 == 0);
                    279:        if (yr%4000 == 0)
                    280:                return (0);
                    281:        if (yr%400==0 || (yr%100!=0 && yr%4==0))
                    282:                return (1);
                    283:        return (0);
                    284: }
                    285: 
                    286: /*
                    287:  * Return the month (1-12) from `mname' which is
                    288:  * roman numeric, the name in ascii of a month, or wrong.
                    289:  * Trailing '.' is accepted as are upper case letters.
                    290:  */
                    291: struct months {
                    292:        char    *m_name;
                    293:        int     m_num;
                    294: }      months[] = {
                    295:        "i",            JAN,    "jan",          JAN,    "january",      JAN,
                    296:        "janvier",      JAN,    "ii",           FEB,    "feb",          FEB,
                    297:        "february",     FEB,    "fevrier",      FEB,    "iii",          MAR,
                    298:        "mar",          MAR,    "march",        MAR,    "mars",         MAR,
                    299:        "iv",           APR,    "apr",          APR,    "april",        APR,
                    300:        "avril",        APR,    "v",            MAY,    "may",          MAY,
                    301:        "mai",          MAY,    "vi",           JUN,    "jun",          JUN,
                    302:        "june",         JUN,    "juin",         JUN,    "vii",          JUL,
                    303:        "jul",          JUL,    "july",         JUL,    "juillet",      JUL,
                    304:        "viii",         AUG,    "iix",          AUG,    "aug",          AUG,
                    305:        "august",       AUG,    "aout",         AUG,    "ix",           SEP,
                    306:        "sep",          SEP,    "sept",         SEP,    "september",    SEP,
                    307:        "septembre",    SEP,    "x",            OCT,    "oct",          OCT,
                    308:        "october",      OCT,    "octobre",      OCT,    "xi",           NOV,
                    309:        "nov",          NOV,    "november",     NOV,    "novembre",     NOV,
                    310:        "xii",          DEC,    "dec",          DEC,    "december",     DEC,
                    311:        "decembre",     DEC,    NULL
                    312: };
                    313: 
                    314: getmon(mname)
                    315: char *mname;
                    316: {
                    317:        register struct months *mp;
                    318:        register char *p1, *p2;
                    319: 
                    320:        for (p1 = mname; *p1 != '\0'; p1 += 1)
                    321:                if (isupper(*p1))
                    322:                        *p1 = tolower(*p1);
                    323:        if (*--p1 == '.')
                    324:                *p1 = '\0';
                    325:        for (mp = months; mp->m_name != NULL; mp++) {
                    326:                p1 = mname;
                    327:                p2 = mp->m_name;
                    328:                while (*p1 == *p2 && *p1 != '\0' && *p2 != 0)
                    329:                        p1 += 1, p2 += 1;
                    330:                if (*p1 == *p2)
                    331:                        return (mp->m_num);
                    332:        }
                    333:        return (-1);
                    334: }
                    335: 
                    336: usage()
                    337: {
                    338:        fprintf(stderr, "Usage: cal [month] [year]\n");
                    339:        exit(1);
                    340: }
                    341: 

unix.superglobalmegacorp.com

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