Annotation of embedaddon/trafshow/strftime.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 1989, 1993
        !             3:  *     The Regents of the University of California.  All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  */
        !            33: 
        !            34: #if defined(LIBC_SCCS) && !defined(lint)
        !            35: static char sccsid[] = "@(#)strftime.c 8.1 (Berkeley) 6/4/93";
        !            36: #endif /* LIBC_SCCS and not lint */
        !            37: 
        !            38: #include <sys/types.h>
        !            39: #include <sys/time.h>
        !            40: #include <tzfile.h>
        !            41: #include <limits.h>
        !            42: #include <stdio.h>
        !            43: 
        !            44: /*
        !            45: ** 302 / 1000 is log10(2.0) rounded up.
        !            46: ** Subtract one for the sign bit;
        !            47: ** add one for integer division truncation;
        !            48: ** add one more for a minus sign.
        !            49: */
        !            50: #define INT_STRLEN_MAXIMUM(type) \
        !            51:        ((sizeof(type) * CHAR_BIT - 1) * 302 / 1000 + 2)
        !            52: 
        !            53: /*
        !            54: ** Based on elsieid[] = "@(#)strftime.c        7.15"
        !            55: **
        !            56: ** This is ANSIish only when time is treated identically in all locales and
        !            57: ** when "multibyte character == plain character".
        !            58: */
        !            59: 
        !            60: static const char afmt[][4] = {
        !            61:        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
        !            62: };
        !            63: static const char Afmt[][10] = {
        !            64:        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
        !            65:        "Saturday"
        !            66: };
        !            67: static const char bfmt[][4] = {
        !            68:        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
        !            69:        "Oct", "Nov", "Dec"
        !            70: };
        !            71: static const char Bfmt[][10] = {
        !            72:        "January", "February", "March", "April", "May", "June", "July",
        !            73:        "August", "September", "October", "November", "December"
        !            74: };
        !            75: 
        !            76: static char *_add __P((const char *, char *, const char *));
        !            77: static char *_conv __P((int, const char *, char *, const char *));
        !            78: static char *_secs __P((const struct tm *, char *, const char *));
        !            79: static char *_fmt __P((const char *, const struct tm *, char *, const char *));
        !            80: 
        !            81: extern char *tzname[];
        !            82: 
        !            83: size_t
        !            84: strftime(s, maxsize, format, t)
        !            85:        char *s;
        !            86:        size_t maxsize;
        !            87:        const char *format;
        !            88:        const struct tm *t;
        !            89: {
        !            90:        char *p;
        !            91: 
        !            92:        p = _fmt(format, t, s, s + maxsize);
        !            93:        if (p == s + maxsize)
        !            94:                return (0);
        !            95:        *p = '\0';
        !            96:        return (p - s);
        !            97: }
        !            98: 
        !            99: static char *
        !           100: _fmt(format, t, pt, ptlim)
        !           101:        const char *format;
        !           102:        const struct tm *t;
        !           103:        char *pt;
        !           104:        const char *ptlim;
        !           105: {
        !           106:        for (; *format; ++format) {
        !           107:                if (*format == '%') {
        !           108: label:
        !           109:                        switch(*++format) {
        !           110:                        case '\0':
        !           111:                                --format;
        !           112:                                break;
        !           113:                        case 'A':
        !           114:                                pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
        !           115:                                        "?" : Afmt[t->tm_wday], pt, ptlim);
        !           116:                                continue;
        !           117:                        case 'a':
        !           118:                                pt = _add((t->tm_wday < 0 || t->tm_wday > 6) ?
        !           119:                                        "?" : afmt[t->tm_wday], pt, ptlim);
        !           120:                                continue;
        !           121:                        case 'B':
        !           122:                                pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
        !           123:                                        "?" : Bfmt[t->tm_mon], pt, ptlim);
        !           124:                                continue;
        !           125:                        case 'b':
        !           126:                        case 'h':
        !           127:                                pt = _add((t->tm_mon < 0 || t->tm_mon > 11) ?
        !           128:                                        "?" : bfmt[t->tm_mon], pt, ptlim);
        !           129:                                continue;
        !           130:                        case 'c':
        !           131:                                pt = _fmt("%D %X", t, pt, ptlim);
        !           132:                                continue;
        !           133:                        case 'C':
        !           134:                                /*
        !           135:                                ** %C used to do a...
        !           136:                                **      _fmt("%a %b %e %X %Y", t);
        !           137:                                ** ...whereas now POSIX 1003.2 calls for
        !           138:                                ** something completely different.
        !           139:                                ** (ado, 5/24/93)
        !           140:                                */
        !           141:                                pt = _conv((t->tm_year + TM_YEAR_BASE) / 100,
        !           142:                                        "%02d", pt, ptlim);
        !           143:                                continue;
        !           144:                        case 'D':
        !           145:                                pt = _fmt("%m/%d/%y", t, pt, ptlim);
        !           146:                                continue;
        !           147:                        case 'x':
        !           148:                                /*
        !           149:                                ** Version 3.0 of strftime from Arnold Robbins
        !           150:                                ** (arnold@skeeve.atl.ga.us) does the
        !           151:                                ** equivalent of...
        !           152:                                **      _fmt("%a %b %e %Y");
        !           153:                                ** ...for %x; since the X3J11 C language
        !           154:                                ** standard calls for "date, using locale's
        !           155:                                ** date format," anything goes.  Using just
        !           156:                                ** numbers (as here) makes Quakers happier.
        !           157:                                ** Word from Paul Eggert (eggert@twinsun.com)
        !           158:                                ** is that %Y-%m-%d is the ISO standard date
        !           159:                                ** format, specified in ISO 2014 and later
        !           160:                                ** ISO 8601:1988, with a summary available in
        !           161:                                ** pub/doc/ISO/english/ISO8601.ps.Z on
        !           162:                                ** ftp.uni-erlangen.de.
        !           163:                                ** (ado, 5/30/93)
        !           164:                                */
        !           165:                                pt = _fmt("%m/%d/%y", t, pt, ptlim);
        !           166:                                continue;
        !           167:                        case 'd':
        !           168:                                pt = _conv(t->tm_mday, "%02d", pt, ptlim);
        !           169:                                continue;
        !           170:                        case 'E':
        !           171:                        case 'O':
        !           172:                                /*
        !           173:                                ** POSIX locale extensions, a la
        !           174:                                ** Arnold Robbins' strftime version 3.0.
        !           175:                                ** The sequences
        !           176:                                **      %Ec %EC %Ex %Ey %EY
        !           177:                                **      %Od %oe %OH %OI %Om %OM
        !           178:                                **      %OS %Ou %OU %OV %Ow %OW %Oy
        !           179:                                ** are supposed to provide alternate
        !           180:                                ** representations.
        !           181:                                ** (ado, 5/24/93)
        !           182:                                */
        !           183:                                goto label;
        !           184:                        case 'e':
        !           185:                                pt = _conv(t->tm_mday, "%2d", pt, ptlim);
        !           186:                                continue;
        !           187:                        case 'H':
        !           188:                                pt = _conv(t->tm_hour, "%02d", pt, ptlim);
        !           189:                                continue;
        !           190:                        case 'I':
        !           191:                                pt = _conv((t->tm_hour % 12) ?
        !           192:                                        (t->tm_hour % 12) : 12,
        !           193:                                        "%02d", pt, ptlim);
        !           194:                                continue;
        !           195:                        case 'j':
        !           196:                                pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
        !           197:                                continue;
        !           198:                        case 'k':
        !           199:                                /*
        !           200:                                ** This used to be...
        !           201:                                **      _conv(t->tm_hour % 12 ?
        !           202:                                **              t->tm_hour % 12 : 12, 2, ' ');
        !           203:                                ** ...and has been changed to the below to
        !           204:                                ** match SunOS 4.1.1 and Arnold Robbins'
        !           205:                                ** strftime version 3.0.  That is, "%k" and
        !           206:                                ** "%l" have been swapped.
        !           207:                                ** (ado, 5/24/93)
        !           208:                                */
        !           209:                                pt = _conv(t->tm_hour, "%2d", pt, ptlim);
        !           210:                                continue;
        !           211: #ifdef KITCHEN_SINK
        !           212:                        case 'K':
        !           213:                                /*
        !           214:                                ** After all this time, still unclaimed!
        !           215:                                */
        !           216:                                pt = _add("kitchen sink", pt, ptlim);
        !           217:                                continue;
        !           218: #endif /* defined KITCHEN_SINK */
        !           219:                        case 'l':
        !           220:                                /*
        !           221:                                ** This used to be...
        !           222:                                **      _conv(t->tm_hour, 2, ' ');
        !           223:                                ** ...and has been changed to the below to
        !           224:                                ** match SunOS 4.1.1 and Arnold Robbin's
        !           225:                                ** strftime version 3.0.  That is, "%k" and
        !           226:                                ** "%l" have been swapped.
        !           227:                                ** (ado, 5/24/93)
        !           228:                                */
        !           229:                                pt = _conv((t->tm_hour % 12) ?
        !           230:                                        (t->tm_hour % 12) : 12,
        !           231:                                        "%2d", pt, ptlim);
        !           232:                                continue;
        !           233:                        case 'M':
        !           234:                                pt = _conv(t->tm_min, "%02d", pt, ptlim);
        !           235:                                continue;
        !           236:                        case 'm':
        !           237:                                pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
        !           238:                                continue;
        !           239:                        case 'n':
        !           240:                                pt = _add("\n", pt, ptlim);
        !           241:                                continue;
        !           242:                        case 'p':
        !           243:                                pt = _add(t->tm_hour >= 12 ? "PM" : "AM",
        !           244:                                        pt, ptlim);
        !           245:                                continue;
        !           246:                        case 'R':
        !           247:                                pt = _fmt("%H:%M", t, pt, ptlim);
        !           248:                                continue;
        !           249:                        case 'r':
        !           250:                                pt = _fmt("%I:%M:%S %p", t, pt, ptlim);
        !           251:                                continue;
        !           252:                        case 'S':
        !           253:                                pt = _conv(t->tm_sec, "%02d", pt, ptlim);
        !           254:                                continue;
        !           255:                        case 's':
        !           256:                                pt = _secs(t, pt, ptlim);
        !           257:                                continue;
        !           258:                        case 'T':
        !           259:                        case 'X':
        !           260:                                pt = _fmt("%H:%M:%S", t, pt, ptlim);
        !           261:                                continue;
        !           262:                        case 't':
        !           263:                                pt = _add("\t", pt, ptlim);
        !           264:                                continue;
        !           265:                        case 'U':
        !           266:                                pt = _conv((t->tm_yday + 7 - t->tm_wday) / 7,
        !           267:                                        "%02d", pt, ptlim);
        !           268:                                continue;
        !           269:                        case 'u':
        !           270:                                /*
        !           271:                                ** From Arnold Robbins' strftime version 3.0:
        !           272:                                ** "ISO 8601: Weekday as a decimal number
        !           273:                                ** [1 (Monday) - 7]"
        !           274:                                ** (ado, 5/24/93)
        !           275:                                */
        !           276:                                pt = _conv((t->tm_wday == 0) ? 7 : t->tm_wday,
        !           277:                                        "%d", pt, ptlim);
        !           278:                                continue;
        !           279:                        case 'V':
        !           280:                                /*
        !           281:                                ** From Arnold Robbins' strftime version 3.0:
        !           282:                                ** "the week number of the year (the first
        !           283:                                ** Monday as the first day of week 1) as a
        !           284:                                ** decimal number (01-53).  The method for
        !           285:                                ** determining the week number is as specified
        !           286:                                ** by ISO 8601 (to wit: if the week containing
        !           287:                                ** January 1 has four or more days in the new
        !           288:                                ** year, then it is week 1, otherwise it is
        !           289:                                ** week 53 of the previous year and the next
        !           290:                                ** week is week 1)."
        !           291:                                ** (ado, 5/24/93)
        !           292:                                */
        !           293:                                /*
        !           294:                                ** XXX--If January 1 falls on a Friday,
        !           295:                                ** January 1-3 are part of week 53 of the
        !           296:                                ** previous year.  By analogy, if January
        !           297:                                ** 1 falls on a Thursday, are December 29-31
        !           298:                                ** of the PREVIOUS year part of week 1???
        !           299:                                ** (ado 5/24/93)
        !           300:                                **
        !           301:                                ** You are understood not to expect this.
        !           302:                                */
        !           303:                                {
        !           304:                                        int i;
        !           305: 
        !           306:                                        i = (t->tm_yday + 10 - (t->tm_wday ?
        !           307:                                                (t->tm_wday - 1) : 6)) / 7;
        !           308:                                        pt = _conv((i == 0) ? 53 : i,
        !           309:                                                "%02d", pt, ptlim);
        !           310:                                }
        !           311:                                continue;
        !           312: #ifdef notdef
        !           313:                                /* Not in POSIX date(1), System V or ANSI C. */
        !           314:                        case 'v':
        !           315:                                /*
        !           316:                                ** From Arnold Robbins' strftime version 3.0:
        !           317:                                ** "date as dd-bbb-YYYY"
        !           318:                                ** (ado, 5/24/93)
        !           319:                                */
        !           320:                                pt = _fmt("%e-%b-%Y", t, pt, ptlim);
        !           321:                                continue;
        !           322: #endif
        !           323:                        case 'W':
        !           324:                                pt = _conv((t->tm_yday + 7 -
        !           325:                                        (t->tm_wday ?
        !           326:                                        (t->tm_wday - 1) : 6)) / 7,
        !           327:                                        "%02d", pt, ptlim);
        !           328:                                continue;
        !           329:                        case 'w':
        !           330:                                pt = _conv(t->tm_wday, "%d", pt, ptlim);
        !           331:                                continue;
        !           332:                        case 'y':
        !           333:                                pt = _conv((t->tm_year + TM_YEAR_BASE) % 100,
        !           334:                                        "%02d", pt, ptlim);
        !           335:                                continue;
        !           336:                        case 'Y':
        !           337:                                pt = _conv(t->tm_year + TM_YEAR_BASE, "%04d",
        !           338:                                        pt, ptlim);
        !           339:                                continue;
        !           340:                        case 'Z':
        !           341: #ifdef TM_ZONE
        !           342:                                if (t->TM_ZONE)
        !           343:                                        pt = _add(t->TM_ZONE, pt, ptlim);
        !           344:                                else
        !           345: #endif /* defined TM_ZONE */
        !           346:                                if (t->tm_isdst == 0 || t->tm_isdst == 1) {
        !           347:                                        pt = _add(tzname[t->tm_isdst],
        !           348:                                                pt, ptlim);
        !           349:                                } else  pt = _add("?", pt, ptlim);
        !           350:                                continue;
        !           351:                        case '%':
        !           352:                        /*
        !           353:                         * X311J/88-090 (4.12.3.5): if conversion char is
        !           354:                         * undefined, behavior is undefined.  Print out the
        !           355:                         * character itself as printf(3) does.
        !           356:                         */
        !           357:                        default:
        !           358:                                break;
        !           359:                        }
        !           360:                }
        !           361:                if (pt == ptlim)
        !           362:                        break;
        !           363:                *pt++ = *format;
        !           364:        }
        !           365:        return (pt);
        !           366: }
        !           367: 
        !           368: static char *
        !           369: _secs(t, pt, ptlim)
        !           370:        const struct tm *t;
        !           371:        char *pt;
        !           372:        const char *ptlim;
        !           373: {
        !           374:        struct tm tmp;
        !           375:        time_t s;
        !           376: 
        !           377:        tmp = *t;
        !           378:        s = mktime(&tmp);
        !           379:        return (_conv((int)s, "%d", pt, ptlim));
        !           380: }
        !           381: 
        !           382: static char *
        !           383: _conv(n, format, pt, ptlim)
        !           384:        int n;
        !           385:        const char *format;
        !           386:        char *pt;
        !           387:        const char *ptlim;
        !           388: {
        !           389:        char buf[INT_STRLEN_MAXIMUM(int) + 1];
        !           390: 
        !           391:        (void) sprintf(buf, format, n);
        !           392:        return (_add(buf, pt, ptlim));
        !           393: }
        !           394: 
        !           395: static char *
        !           396: _add(str, pt, ptlim)
        !           397:        const char *str;
        !           398:        char *pt;
        !           399:        const char *ptlim;
        !           400: {
        !           401: 
        !           402:        while (pt < ptlim && (*pt = *str++) != '\0')
        !           403:                ++pt;
        !           404:        return (pt);
        !           405: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>