[BACK]Return to day.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / calendar

Annotation of src/usr.bin/calendar/day.c, Revision 1.1

1.1     ! millert     1: /*     $OpenBSD: $     */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1989, 1993, 1994
        !             5:  *     The Regents of the University of California.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by the University of
        !            18:  *     California, Berkeley and its contributors.
        !            19:  * 4. Neither the name of the University nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  */
        !            35:
        !            36: #ifndef lint
        !            37: static const char copyright[] =
        !            38: "@(#) Copyright (c) 1989, 1993\n\
        !            39:        The Regents of the University of California.  All rights reserved.\n";
        !            40: #endif /* not lint */
        !            41:
        !            42: #ifndef lint
        !            43: #if 0
        !            44: static const char sccsid[] = "@(#)calendar.c  8.3 (Berkeley) 3/25/94";
        !            45: #else
        !            46: static char rcsid[] = "$OpenBSD: $";
        !            47: #endif
        !            48: #endif /* not lint */
        !            49:
        !            50: #include <sys/types.h>
        !            51: #include <sys/uio.h>
        !            52:
        !            53: #include <ctype.h>
        !            54: #include <err.h>
        !            55: #include <locale.h>
        !            56: #include <stdio.h>
        !            57: #include <stdlib.h>
        !            58: #include <string.h>
        !            59: #include <time.h>
        !            60: #include <tzfile.h>
        !            61:
        !            62: #include "pathnames.h"
        !            63: #include "calendar.h"
        !            64:
        !            65: struct tm *tp;
        !            66: int *cumdays, offset, yrdays;
        !            67: char dayname[10];
        !            68:
        !            69:
        !            70: /* 1-based month, 0-based days, cumulative */
        !            71: int daytab[][14] = {
        !            72:        { 0, -1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364 },
        !            73:        { 0, -1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
        !            74: };
        !            75:
        !            76: static char *days[] = {
        !            77:        "sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL,
        !            78: };
        !            79:
        !            80: static char *months[] = {
        !            81:        "jan", "feb", "mar", "apr", "may", "jun",
        !            82:        "jul", "aug", "sep", "oct", "nov", "dec", NULL,
        !            83: };
        !            84:
        !            85: static struct fixs fndays[8];         /* full national days names */
        !            86: static struct fixs ndays[8];          /* short national days names */
        !            87:
        !            88: static struct fixs fnmonths[13];      /* full national months names */
        !            89: static struct fixs nmonths[13];       /* short national month names */
        !            90:
        !            91:
        !            92: void setnnames(void)
        !            93: {
        !            94:        char buf[80];
        !            95:        int i, l;
        !            96:        struct tm tm;
        !            97:
        !            98:        for (i = 0; i < 7; i++) {
        !            99:                tm.tm_wday = i;
        !           100:                strftime(buf, sizeof(buf), "%a", &tm);
        !           101:                for (l = strlen(buf);
        !           102:                     l > 0 && isspace((int)buf[l - 1]);
        !           103:                     l--)
        !           104:                        ;
        !           105:                buf[l] = '\0';
        !           106:                if (ndays[i].name != NULL)
        !           107:                        free(ndays[i].name);
        !           108:                if ((ndays[i].name = strdup(buf)) == NULL)
        !           109:                        errx(1, "cannot allocate memory");
        !           110:                ndays[i].len = strlen(buf);
        !           111:
        !           112:                strftime(buf, sizeof(buf), "%A", &tm);
        !           113:                for (l = strlen(buf);
        !           114:                     l > 0 && isspace((int)buf[l - 1]);
        !           115:                     l--)
        !           116:                        ;
        !           117:                buf[l] = '\0';
        !           118:                if (fndays[i].name != NULL)
        !           119:                        free(fndays[i].name);
        !           120:                if ((fndays[i].name = strdup(buf)) == NULL)
        !           121:                        errx(1, "cannot allocate memory");
        !           122:                fndays[i].len = strlen(buf);
        !           123:        }
        !           124:
        !           125:        for (i = 0; i < 12; i++) {
        !           126:                tm.tm_mon = i;
        !           127:                strftime(buf, sizeof(buf), "%b", &tm);
        !           128:                for (l = strlen(buf);
        !           129:                     l > 0 && isspace((int)buf[l - 1]);
        !           130:                     l--)
        !           131:                        ;
        !           132:                buf[l] = '\0';
        !           133:                if (nmonths[i].name != NULL)
        !           134:                        free(nmonths[i].name);
        !           135:                if ((nmonths[i].name = strdup(buf)) == NULL)
        !           136:                        errx(1, "cannot allocate memory");
        !           137:                nmonths[i].len = strlen(buf);
        !           138:
        !           139:                strftime(buf, sizeof(buf), "%B", &tm);
        !           140:                for (l = strlen(buf);
        !           141:                     l > 0 && isspace((int)buf[l - 1]);
        !           142:                     l--)
        !           143:                        ;
        !           144:                buf[l] = '\0';
        !           145:                if (fnmonths[i].name != NULL)
        !           146:                        free(fnmonths[i].name);
        !           147:                if ((fnmonths[i].name = strdup(buf)) == NULL)
        !           148:                        errx(1, "cannot allocate memory");
        !           149:                fnmonths[i].len = strlen(buf);
        !           150:        }
        !           151: }
        !           152:
        !           153: void
        !           154: settime(now)
        !           155:        time_t now;
        !           156: {
        !           157:        tp = localtime(&now);
        !           158:        if (isleap(tp->tm_year + 1900)) {
        !           159:                yrdays = DAYSPERLYEAR;
        !           160:                cumdays = daytab[1];
        !           161:        } else {
        !           162:                yrdays = DAYSPERNYEAR;
        !           163:                cumdays = daytab[0];
        !           164:        }
        !           165:        /* Friday displays Monday's events */
        !           166:        offset = tp->tm_wday == 5 ? 3 : 1;
        !           167:        header[5].iov_base = dayname;
        !           168:
        !           169:        (void) setlocale(LC_TIME, "C");
        !           170:        header[5].iov_len = strftime(dayname, sizeof(dayname), "%A", tp);
        !           171:        (void) setlocale(LC_TIME, "");
        !           172:
        !           173:        setnnames();
        !           174: }
        !           175:
        !           176: /* convert Day[/Month][/Year] into unix time (since 1970)
        !           177:  * Day: two digits, Month: two digits, Year: digits
        !           178:  */
        !           179: time_t Mktime (date)
        !           180:     char *date;
        !           181: {
        !           182:     time_t t;
        !           183:     int len;
        !           184:     struct tm tm;
        !           185:
        !           186:     (void)time(&t);
        !           187:     tp = localtime(&t);
        !           188:
        !           189:     len = strlen(date);
        !           190:     tm.tm_sec = 0;
        !           191:     tm.tm_min = 0;
        !           192:     tm.tm_hour = 0;
        !           193:     tm.tm_wday = 0;
        !           194:     tm.tm_mday = tp->tm_mday;
        !           195:     tm.tm_mon = tp->tm_mon;
        !           196:     tm.tm_year = tp->tm_year;
        !           197:
        !           198:
        !           199:     /* day */
        !           200:     *(date+2) = NULL;
        !           201:     tm.tm_mday = atoi(date);
        !           202:
        !           203:     /* month */
        !           204:     if (len >= 4) {
        !           205:        *(date+5) = NULL;
        !           206:        tm.tm_mon = atoi(date+3) - 1;
        !           207:     }
        !           208:
        !           209:     /* Year */
        !           210:     if (len >= 7) {
        !           211:        tm.tm_year = atoi(date+6);
        !           212:
        !           213:        /* tm_year up 1900 ... */
        !           214:        if (tm.tm_year > 1900)
        !           215:            tm.tm_year -= 1900;
        !           216:     }
        !           217:
        !           218: #if DEBUG
        !           219:     printf("Mktime: %d %d %d %s\n", (int)mktime(&tm), (int)t, len,
        !           220:           asctime(&tm));
        !           221: #endif
        !           222:     return(mktime(&tm));
        !           223: }
        !           224:
        !           225: /*
        !           226:  * Possible date formats include any combination of:
        !           227:  *     3-charmonth                     (January, Jan, Jan)
        !           228:  *     3-charweekday                   (Friday, Monday, mon.)
        !           229:  *     numeric month or day            (1, 2, 04)
        !           230:  *
        !           231:  * Any character may separate them, or they may not be separated.  Any line,
        !           232:  * following a line that is matched, that starts with "whitespace", is shown
        !           233:  * along with the matched line.
        !           234:  */
        !           235: int
        !           236: isnow(endp, monthp, dayp, varp)
        !           237:        char    *endp;
        !           238:        int     *monthp;
        !           239:        int     *dayp;
        !           240:        int     *varp;
        !           241: {
        !           242:        int day, flags = 0, month = 0, v1, v2;
        !           243:
        !           244:        /*
        !           245:         * CONVENTION
        !           246:         *
        !           247:         * Month:     1-12
        !           248:         * Monthname: Jan .. Dec
        !           249:         * Day:       1-31
        !           250:         * Weekday:   Mon-Sun
        !           251:         *
        !           252:         */
        !           253:
        !           254:        /* read first field */
        !           255:        /* didn't recognize anything, skip it */
        !           256:        if (!(v1 = getfield(endp, &endp, &flags)))
        !           257:                return (0);
        !           258:
        !           259:        /* Easter or Easter depending days */
        !           260:        if (flags & F_EASTER)
        !           261:            day = v1 - 1; /* days since January 1 [0-365] */
        !           262:
        !           263:         /*
        !           264:          * 1. {Weekday,Day} XYZ ...
        !           265:          *
        !           266:          *    where Day is > 12
        !           267:          */
        !           268:        else if (flags & F_ISDAY || v1 > 12) {
        !           269:
        !           270:                /* found a day; day: 1-31 or weekday: 1-7 */
        !           271:                day = v1;
        !           272:
        !           273:                /* {Day,Weekday} {Month,Monthname} ... */
        !           274:                /* if no recognizable month, assume just a day alone
        !           275:                 * in other words, find month or use current month */
        !           276:                if (!(month = getfield(endp, &endp, &flags)))
        !           277:                        month = tp->tm_mon + 1;
        !           278:        }
        !           279:
        !           280:        /* 2. {Monthname} XYZ ... */
        !           281:        else if (flags & F_ISMONTH) {
        !           282:                month = v1;
        !           283:
        !           284:                /* Monthname {day,weekday} */
        !           285:                /* if no recognizable day, assume the first day in month */
        !           286:                if (!(day = getfield(endp, &endp, &flags)))
        !           287:                        day = 1;
        !           288:        }
        !           289:
        !           290:        /* Hm ... */
        !           291:        else {
        !           292:                v2 = getfield(endp, &endp, &flags);
        !           293:
        !           294:                /*
        !           295:                 * {Day} {Monthname} ...
        !           296:                 * where Day <= 12
        !           297:                 */
        !           298:                if (flags & F_ISMONTH) {
        !           299:                        day = v1;
        !           300:                        month = v2;
        !           301:                        *varp = 0;
        !           302:                }
        !           303:
        !           304:                /* {Month} {Weekday,Day} ...  */
        !           305:                else {
        !           306:                        /* F_ISDAY set, v2 > 12, or no way to tell */
        !           307:                        month = v1;
        !           308:                        /* if no recognizable day, assume the first */
        !           309:                        day = v2 ? v2 : 1;
        !           310:                        *varp = 0;
        !           311:                }
        !           312:        }
        !           313:
        !           314:        /* convert Weekday into *next*  Day,
        !           315:         * e.g.: 'Sunday' -> 22
        !           316:         *       'SunayLast' -> ??
        !           317:         */
        !           318:        if (flags & F_ISDAY) {
        !           319: #if DEBUG
        !           320:            fprintf(stderr, "\nday: %d %s month %d\n", day, endp, month);
        !           321: #endif
        !           322:
        !           323:            *varp = 1;
        !           324:            /* variable weekday, SundayLast, MondayFirst ... */
        !           325:            if (day < 0 || day >= 10) {
        !           326:
        !           327:                /* negative offset; last, -4 .. -1 */
        !           328:                if (day < 0) {
        !           329:                    v1 = day/10 - 1;          /* offset -4 ... -1 */
        !           330:                    day = 10 + (day % 10);    /* day 1 ... 7 */
        !           331:
        !           332:                    /* day, eg '22th' */
        !           333:                    v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
        !           334:
        !           335:                    /* (month length - day) / 7 + 1 */
        !           336:                    if (((int)((cumdays[month+1] -
        !           337:                               cumdays[month] - v2) / 7) + 1) == -v1)
        !           338:                        /* bingo ! */
        !           339:                        day = v2;
        !           340:
        !           341:                    /* set to yesterday */
        !           342:                    else
        !           343:                        day = tp->tm_mday - 1;
        !           344:                }
        !           345:
        !           346:                /* first, second ... +1 ... +5 */
        !           347:                else {
        !           348:                    v1 = day/10;        /* offset: +1 (first Sunday) ... */
        !           349:                    day = day % 10;
        !           350:
        !           351:                    /* day, eg '22th' */
        !           352:                    v2 = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
        !           353:
        !           354:                    /* Hurrah! matched */
        !           355:                    if ( ((v2 - 1 + 7) / 7) == v1 )
        !           356:                        day = v2;
        !           357:
        !           358:                    /* set to yesterday */
        !           359:                    else
        !           360:                        day = tp->tm_mday - 1;
        !           361:                }
        !           362:            }
        !           363:
        !           364:            /* wired */
        !           365:            else {
        !           366:                day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);
        !           367:                *varp = 1;
        !           368:            }
        !           369:        }
        !           370:
        !           371:        if (!(flags & F_EASTER)) {
        !           372:            *monthp = month;
        !           373:            *dayp = day;
        !           374:            day = cumdays[month] + day;
        !           375:        }
        !           376:        else {
        !           377:            for (v1 = 0; day > cumdays[v1]; v1++)
        !           378:                ;
        !           379:            *monthp = v1 - 1;
        !           380:            *dayp = day - cumdays[v1 - 1];
        !           381:            *varp = 1;
        !           382:        }
        !           383:
        !           384: #if DEBUG
        !           385:        fprintf(stderr, "day2: day %d(%d) yday %d\n", *dayp, day, tp->tm_yday);
        !           386: #endif
        !           387:        /* if today or today + offset days */
        !           388:        if (day >= tp->tm_yday - f_dayBefore &&
        !           389:            day <= tp->tm_yday + offset + f_dayAfter)
        !           390:                return (1);
        !           391:
        !           392:        /* if number of days left in this year + days to event in next year */
        !           393:        if (yrdays - tp->tm_yday + day <= offset + f_dayAfter ||
        !           394:            /* a year backward, eg. 6 Jan and 10 days before -> 27. Dec */
        !           395:            tp->tm_yday + day - f_dayBefore < 0
        !           396:            )
        !           397:                return (1);
        !           398:        return (0);
        !           399: }
        !           400:
        !           401:
        !           402: int
        !           403: getmonth(s)
        !           404:        register char *s;
        !           405: {
        !           406:        register char **p;
        !           407:        struct fixs *n;
        !           408:
        !           409:        for (n = fnmonths; n->name; ++n)
        !           410:                if (!strncasecmp(s, n->name, n->len))
        !           411:                        return ((n - fnmonths) + 1);
        !           412:        for (n = nmonths; n->name; ++n)
        !           413:                if (!strncasecmp(s, n->name, n->len))
        !           414:                        return ((n - nmonths) + 1);
        !           415:        for (p = months; *p; ++p)
        !           416:                if (!strncasecmp(s, *p, 3))
        !           417:                        return ((p - months) + 1);
        !           418:        return (0);
        !           419: }
        !           420:
        !           421:
        !           422: int
        !           423: getday(s)
        !           424:        register char *s;
        !           425: {
        !           426:        register char **p;
        !           427:        struct fixs *n;
        !           428:
        !           429:        for (n = fndays; n->name; ++n)
        !           430:                if (!strncasecmp(s, n->name, n->len))
        !           431:                        return ((n - fndays) + 1);
        !           432:        for (n = ndays; n->name; ++n)
        !           433:                if (!strncasecmp(s, n->name, n->len))
        !           434:                        return ((n - ndays) + 1);
        !           435:        for (p = days; *p; ++p)
        !           436:                if (!strncasecmp(s, *p, 3))
        !           437:                        return ((p - days) + 1);
        !           438:        return (0);
        !           439: }
        !           440:
        !           441: /* return offset for variable weekdays
        !           442:  * -1 -> last weekday in month
        !           443:  * +1 -> first weekday in month
        !           444:  * ... etc ...
        !           445:  */
        !           446: int
        !           447: getdayvar(s)
        !           448:        register char *s;
        !           449: {
        !           450:        register int offset;
        !           451:
        !           452:
        !           453:        offset = strlen(s);
        !           454:
        !           455:
        !           456:        /* Sun+1 or Wednesday-2
        !           457:         *    ^              ^   */
        !           458:
        !           459:        /* printf ("x: %s %s %d\n", s, s + offset - 2, offset); */
        !           460:        switch(*(s + offset - 2)) {
        !           461:        case '-':
        !           462:            return(-(atoi(s + offset - 1)));
        !           463:            break;
        !           464:        case '+':
        !           465:            return(atoi(s + offset - 1));
        !           466:            break;
        !           467:        }
        !           468:
        !           469:
        !           470:        /*
        !           471:         * some aliases: last, first, second, third, fourth
        !           472:         */
        !           473:
        !           474:        /* last */
        !           475:        if      (offset > 4 && !strcasecmp(s + offset - 4, "last"))
        !           476:            return(-1);
        !           477:        else if (offset > 5 && !strcasecmp(s + offset - 5, "first"))
        !           478:            return(+1);
        !           479:        else if (offset > 6 && !strcasecmp(s + offset - 6, "second"))
        !           480:            return(+2);
        !           481:        else if (offset > 5 && !strcasecmp(s + offset - 5, "third"))
        !           482:            return(+3);
        !           483:        else if (offset > 6 && !strcasecmp(s + offset - 6, "fourth"))
        !           484:            return(+4);
        !           485:
        !           486:
        !           487:        /* no offset detected */
        !           488:        return(0);
        !           489: }