Annotation of coherent/d/bin/cal.c, revision 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.