[BACK]Return to time.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gnuplot

Annotation of OpenXM_contrib/gnuplot/time.c, Revision 1.1.1.2

1.1       maekawa     1: #ifndef lint
1.1.1.2 ! maekawa     2: static char *RCSid = "$Id: time.c,v 1.5.2.1 1999/08/19 14:35:30 lhecking Exp $";
1.1       maekawa     3: #endif
                      4:
                      5: /* GNUPLOT - time.c */
                      6:
                      7: /*[
                      8:  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
                      9:  *
                     10:  * Permission to use, copy, and distribute this software and its
                     11:  * documentation for any purpose with or without fee is hereby granted,
                     12:  * provided that the above copyright notice appear in all copies and
                     13:  * that both that copyright notice and this permission notice appear
                     14:  * in supporting documentation.
                     15:  *
                     16:  * Permission to modify the software is granted, but not the right to
                     17:  * distribute the complete modified source code.  Modifications are to
                     18:  * be distributed as patches to the released version.  Permission to
                     19:  * distribute binaries produced by compiling modified sources is granted,
                     20:  * provided you
                     21:  *   1. distribute the corresponding source modifications from the
                     22:  *    released version in the form of a patch file along with the binaries,
                     23:  *   2. add special version identification to distinguish your version
                     24:  *    in addition to the base release version number,
                     25:  *   3. provide your name and address as the primary contact for the
                     26:  *    support of your modified version, and
                     27:  *   4. retain our contact information in regard to use of the base
                     28:  *    software.
                     29:  * Permission to distribute the released version of the source code along
                     30:  * with corresponding source modifications in the form of a patch file is
                     31:  * granted with same provisions 2 through 4 for binary distributions.
                     32:  *
                     33:  * This software is provided "as is" without express or implied warranty
                     34:  * to the extent permitted by applicable law.
                     35: ]*/
                     36:
                     37:
                     38: /* some systems may not implement time very well ; in particular,
                     39:  * things might break as the year 2000 approaches.
                     40:  * This module either adds a routine gstrptime() to read a formatted time,
                     41:  * augmenting the standard suite of time routines provided by ansi,
                     42:  * or it completely replaces the whole lot with a new set of routines,
                     43:  * which count time relative to the year 2000. Default is to use the
                     44:  * new routines. define USE_SYSTEM_TIME to use the system routines, at your
                     45:  * own risk. One problem in particular is that not all systems allow
                     46:  * the time with integer value 0 to be represented symbolically, which
                     47:  * prevents use of relative times.
                     48:  */
                     49:
                     50:
                     51: #include "plot.h"
                     52:
                     53: /* build as a standalone test */
                     54:
                     55: #ifdef TEST_TIME
                     56:
                     57: # ifdef HAVE_SYS_TIMEB_H
                     58: #  include <sys/timeb.h>
                     59: #else
                     60: /* declare struct timeb */
                     61: extern int ftime(struct timeb *);
                     62: #endif
                     63:
                     64: # define int_error(x,y) fprintf(stderr, "Error: " x "\n")
                     65: # define int_warn(x,y) fprintf(stderr, "Warn: " x "\n")
                     66:
                     67: /* need (only) these from plot.h */
                     68: # define ZERO_YEAR     2000
                     69: /* 1st jan, 2000 is a Saturday (cal 1 2000 on unix) */
                     70: # define JAN_FIRST_WDAY 6
                     71:
                     72: /*  zero gnuplot (2000) - zero system (1970) */
                     73: # define SEC_OFFS_SYS  946684800.0
                     74:
                     75: /* avg, incl. leap year */
                     76: # define YEAR_SEC      31557600.0
                     77:
                     78: /* YEAR_SEC / 12 */
                     79: # define MON_SEC               2629800.0
                     80:
                     81: # define WEEK_SEC      604800.0
                     82: # define DAY_SEC               86400.0
                     83:
                     84: /*forward decls */
                     85: extern char *abbrev_month_names[];
                     86: extern char *full_month_names[];
                     87: extern char *abbrev_day_names[];
                     88: extern char *full_day_names[];
                     89:
                     90: #else /* TEST_TIME */
                     91:
                     92: # include "setshow.h"          /* for month names etc */
                     93:
                     94: #endif /* TEST_TIME */
                     95:
                     96: static char *read_int __PROTO((char *s, int nr, int *d));
                     97: static int gdysize __PROTO((int yr));
                     98:
                     99:
                    100: static char *
                    101:  read_int(s, nr, d)
                    102: char *s;
                    103: int nr, *d;
                    104: {
                    105:     int result = 0;
                    106:
                    107:     while (--nr >= 0 && *s >= '0' && *s <= '9')
                    108:        result = result * 10 + (*s++ - '0');
                    109:
                    110:     *d = result;
                    111:     return (s);
                    112: }
                    113:
                    114:
                    115:
                    116: #ifndef USE_SYSTEM_TIME
                    117:
                    118: /* a new set of routines to completely replace the ansi ones
                    119:  * Use at your own risk
                    120:  */
                    121:
                    122:
                    123: static int mndday[12] =
                    124: {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
                    125:
                    126: static int xstrftime __PROTO((char *buf, int bufsz, char *fmt, struct tm * tm));
                    127:
                    128: /* days in year */
                    129: static int gdysize(yr)
                    130: int yr;
                    131: {
                    132:
                    133:     if (!(yr % 4)) {
                    134:        if ((!(yr % 100)) && yr % 400)
                    135:            return (365);
                    136:        return (366);
                    137:     }
                    138:     return (365);
                    139: }
                    140:
                    141:
                    142: /* new strptime() and gmtime() to allow time to be read as 24 hour,
                    143:  * and spaces in the format string. time is converted to seconds from
                    144:  * year 2000.... */
                    145:
                    146: char *
                    147:  gstrptime(s, fmt, tm)
                    148: char *s;
                    149: char *fmt;
                    150: struct tm *tm;
                    151: {
                    152:     int yday, date;
                    153:
                    154:     date = yday = 0;
                    155:     tm->tm_mday = 1;
                    156:     tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
                    157:     /* make relative times work (user-defined tic step) */
                    158:     tm->tm_year = ZERO_YEAR;
                    159:
                    160:     /* we do not yet calculate wday or yday, so make them illegal
                    161:      * [but yday will be read by %j]
                    162:      */
                    163:
                    164:     tm->tm_yday = tm->tm_wday = -1;
                    165:
                    166:     while (*fmt) {
                    167:        if (*fmt != '%') {
                    168:            if (*fmt == ' ') {
                    169:                /* space in format means zero or more spaces in input */
                    170:                while (*s == ' ')
                    171:                    ++s;
                    172:                ++fmt;
                    173:                continue;
                    174:            } else if (*fmt == *s) {
                    175:                ++s;
                    176:                ++fmt;
                    177:                continue;
                    178:            } else
                    179:                break;          /* literal match has failed */
                    180:        }
                    181:        /* we are processing a percent escape */
                    182:
                    183:        switch (*++fmt) {
                    184:        case 'b':               /* abbreviated month name */
                    185:            {
                    186:                int m;
                    187:                for (m = 0; m < 12; ++m)
                    188:                    if (strnicmp(s, abbrev_month_names[m], strlen(abbrev_month_names[m])) == 0) {
                    189:                        s += strlen(abbrev_month_names[m]);
                    190:                        goto found_abbrev_mon;
                    191:                    }
                    192:                /* get here => not found */
                    193:                int_warn("Bad abbreviated month name", NO_CARET);
                    194:                m = 0;
                    195:              found_abbrev_mon:
                    196:                tm->tm_mon = m;
                    197:                break;
                    198:            }
                    199:
                    200:        case 'B':               /* full month name */
                    201:            {
                    202:                int m;
                    203:                for (m = 0; m < 12; ++m)
                    204:                    if (strnicmp(s, full_month_names[m], strlen(full_month_names[m])) == 0) {
                    205:                        s += strlen(full_month_names[m]);
                    206:                        goto found_full_mon;
                    207:                    }
                    208:                /* get here => not found */
                    209:                int_warn("Bad full month name", NO_CARET);
                    210:                m = 0;
                    211:              found_full_mon:
                    212:                tm->tm_mon = m;
                    213:                break;
                    214:            }
                    215:
                    216:        case 'd':               /* read a day of month */
                    217:            s = read_int(s, 2, &tm->tm_mday);
                    218:            date++;
                    219:            break;
                    220:
                    221:        case 'm':               /* month number */
                    222:            s = read_int(s, 2, &tm->tm_mon);
                    223:            date++;
                    224:            --tm->tm_mon;
                    225:            break;
                    226:
                    227:        case 'y':               /* year number */
                    228:            s = read_int(s, 2, &tm->tm_year);
1.1.1.2 ! maekawa   229:            /* In line with the current UNIX98 specification by
        !           230:             * The Open Group and major Unix vendors,
        !           231:             * two-digit years 69-99 refer to the 20th century, and
        !           232:             * values in the range 00-68 refer to the 21st century.
        !           233:             */
        !           234:            if (tm->tm_year <= 68)
        !           235:                tm->tm_year += 100;
1.1       maekawa   236:            date++;
                    237:            tm->tm_year += 1900;
                    238:            break;
                    239:
                    240:        case 'Y':
                    241:            s = read_int(s, 4, &tm->tm_year);
                    242:            date++;
                    243:            /* tm->tm_year -= 1900; */
                    244:            /* HOE tm->tm_year %= 100; */
                    245:            break;
                    246:
                    247:        case 'j':
                    248:            s = read_int(s, 3, &tm->tm_yday);
                    249:            tm->tm_yday--;
                    250:            date++;
                    251:            yday++;
                    252:            break;
                    253:
                    254:        case 'H':
                    255:            s = read_int(s, 2, &tm->tm_hour);
                    256:            break;
                    257:
                    258:        case 'M':
                    259:            s = read_int(s, 2, &tm->tm_min);
                    260:            break;
                    261:
                    262:        case 'S':
                    263:            s = read_int(s, 2, &tm->tm_sec);
                    264:            break;
                    265:
                    266:        default:
                    267:            int_warn("Bad time format in string", NO_CARET);
                    268:        }
                    269:        fmt++;
                    270:     }
                    271:
                    272:     FPRINTF((stderr, "read date-time : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
                    273:
                    274:     /* now check the date/time entered, normalising if necessary
                    275:      * read_int cannot read a -ve number, but can read %m=0 then decrement
                    276:      * it to -1
                    277:      */
                    278:
                    279: #define S (tm->tm_sec)
                    280: #define M (tm->tm_min)
                    281: #define H (tm->tm_hour)
                    282:
                    283:     if (S >= 60) {
                    284:        M += S / 60;
                    285:        S %= 60;
                    286:     }
                    287:     if (M >= 60) {
                    288:        H += M / 60;
                    289:        M %= 60;
                    290:     }
                    291:     if (H >= 24) {
                    292:        if (yday)
                    293:            tm->tm_yday += H / 24;
                    294:        tm->tm_mday += H / 24;
                    295:        H %= 24;
                    296:     }
                    297: #undef S
                    298: #undef M
                    299: #undef H
                    300:
                    301:     FPRINTF((stderr, "normalised time : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
                    302:
                    303:     if (date) {
                    304:        if (yday) {
                    305:
                    306:            if (tm->tm_yday < 0)
                    307:                int_error("Illegal day of year", NO_CARET);
                    308:
                    309:            /* we just set month to jan, day to yday, and let the
                    310:             * normalising code do the work.
                    311:             */
                    312:
                    313:            tm->tm_mon = 0;
                    314:            /* yday is 0->365, day is 1->31 */
                    315:            tm->tm_mday = tm->tm_yday + 1;
                    316:        }
                    317:        if (tm->tm_mon < 0) {
                    318:            int_error("illegal month", NO_CARET);
                    319:            return (NULL);
                    320:        }
                    321:        if (tm->tm_mday < 1) {
                    322:            int_error("illegal day of month", NO_CARET);
                    323:            return (NULL);
                    324:        }
                    325:        if (tm->tm_mon > 11) {
                    326:            tm->tm_year += tm->tm_mon / 12;
                    327:            tm->tm_mon %= 12;
                    328:        } {
                    329:            int days_in_month;
                    330:            while (tm->tm_mday > (days_in_month = (mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365))))) {
                    331:                if (++tm->tm_mon == 12) {
                    332:                    ++tm->tm_year;
                    333:                    tm->tm_mon = 0;
                    334:                }
                    335:                tm->tm_mday -= days_in_month;
                    336:            }
                    337:        }
                    338:     }
                    339:     return (s);
                    340: }
                    341:
                    342: int gstrftime(s, bsz, fmt, l_clock)
                    343: char *s;
                    344: int bsz;
                    345: char *fmt;
                    346: double l_clock;
                    347: {
                    348:     struct tm tm;
                    349:
                    350:     ggmtime(&tm, l_clock);
                    351: #if 0
                    352:     if ((tm.tm_zone = (char *) malloc(strlen(xtm->tm_zone) + 1)))
                    353:        strcpy(tm.tm_zone, xtm->tm_zone);
                    354:     /* printf("zone: %s - %s\n",tm.tm_zone,xtm->tm_zone); */
                    355: #endif
                    356:
                    357:     return (xstrftime(s, bsz, fmt, &tm));
                    358: }
                    359:
                    360:
                    361: /* some shorthands : check that there is space in the output string
                    362:  * Odd-looking defn is dangling-else-safe
                    363:  */
                    364: #define CHECK_SPACE(n) if ( (l+(n)) <= bsz) ; else return 0
                    365:
                    366: /* copy a fixed string, checking that there's room */
                    367: #define COPY_STRING(z) CHECK_SPACE(strlen(z)) ; strcpy(s, z)
                    368:
                    369: /* format a string, using default spec if none given
                    370:  * w and z are width and zero-flag
                    371:  * dw and dz are the defaults for these
                    372:  * In fact, CHECK_SPACE(w) is not a sufficient test, since
                    373:  * sprintf("%2d", 365) outputs three characters
                    374:  */
                    375:
                    376: #define FORMAT_STRING(dz, dw, x)           \
                    377:   if (w==0) { w=(dw); if (!z) z=(dz); }    \
                    378:   CHECK_SPACE(w);                          \
                    379:   sprintf(s, z ? "%0*d" : "%*d", w, (x) )
                    380:
                    381: static int xstrftime(str, bsz, fmt, tm)
                    382: char *str;                     /* output buffer */
                    383: int bsz;                       /* space available */
                    384: char *fmt;
                    385: struct tm *tm;
                    386: {
                    387:     int l = 0;                 /* chars written so far */
                    388:
                    389:     char *s = str;
                    390:
                    391:     memset(s, '\0', bsz);
                    392:
                    393:     while (*fmt != '\0') {
                    394:        if (*fmt != '%') {
                    395:            if (l >= bsz)
                    396:                return (0);
                    397:            *s++ = *fmt++;
                    398:            l++;
                    399:        } else {
                    400:
                    401:            /* set up format modifiers */
                    402:            int w = 0;
                    403:            int z = 0;
                    404:            if (*++fmt == '0') {
                    405:                z = 1;
                    406:                ++fmt;
                    407:            }
                    408:            while (*fmt >= '0' && *fmt <= '9') {
                    409:                w = w * 10 + (*fmt - '0');
                    410:                ++fmt;
                    411:            }
                    412:
                    413:            switch (*fmt++) {
                    414:            case '%':
                    415:                CHECK_SPACE(1);
                    416:                *s = '%';
                    417:                break;
                    418:
                    419:            case 'a':
                    420:                COPY_STRING(abbrev_day_names[tm->tm_wday]);
                    421:                break;
                    422:
                    423:            case 'A':
                    424:                COPY_STRING(full_day_names[tm->tm_wday]);
                    425:                break;
                    426:
                    427:            case 'b':
                    428:            case 'h':
                    429:                COPY_STRING(abbrev_month_names[tm->tm_mon]);
                    430:                break;
                    431:
                    432:            case 'B':
                    433:                COPY_STRING(full_month_names[tm->tm_mon]);
                    434:                break;
                    435:
                    436:
                    437: #if 0
                    438:            /* %x not currently supported, so neither is c */
                    439:            case 'c':
                    440:                if (!xstrftime(s, bsz - l, "%x %X", tm))
                    441:                    return (0);
                    442:                break;
                    443: #endif
                    444:
                    445:            case 'd':
                    446:                FORMAT_STRING(1, 2, tm->tm_mday);       /* %02d */
                    447:                break;
                    448:
                    449:            case 'D':
                    450:                if (!xstrftime(s, bsz - l, "%m/%d/%y", tm))
                    451:                    return (0);
                    452:                break;
                    453:
                    454:            case 'H':
                    455:                FORMAT_STRING(1, 2, tm->tm_hour);       /* %02d */
                    456:                break;
                    457:
                    458:            case 'I':
                    459:                FORMAT_STRING(1, 2, tm->tm_hour % 12);  /* %02d */
                    460:                break;
                    461:
                    462:            case 'j':
                    463:                FORMAT_STRING(1, 3, tm->tm_yday + 1);   /* %03d */
                    464:                break;
                    465:
                    466:                /* not in linux strftime man page. Not really needed now */
                    467:            case 'k':
                    468:                FORMAT_STRING(0, 2, tm->tm_hour);       /* %2d */
                    469:                break;
                    470:
                    471:            case 'l':
                    472:                FORMAT_STRING(0, 2, tm->tm_hour % 12);  /* %2d */
                    473:                break;
                    474:
                    475:            case 'm':
                    476:                FORMAT_STRING(1, 2, tm->tm_mon + 1);    /* %02d */
                    477:                break;
                    478:
                    479:            case 'M':
                    480:                FORMAT_STRING(1, 2, tm->tm_min);        /* %02d */
                    481:                break;
                    482:
                    483:            case 'p':
                    484:                CHECK_SPACE(2);
                    485:                strcpy(s, (tm->tm_hour < 12) ? "am" : "pm");
                    486:                break;
                    487:
                    488:            case 'r':
                    489:                if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm))
                    490:                    return (0);
                    491:                break;
                    492:
                    493:            case 'R':
                    494:                if (!xstrftime(s, bsz - l, "%H:%M", tm))
                    495:                    return (0);
                    496:                break;
                    497:
                    498:            case 'S':
                    499:                FORMAT_STRING(1, 2, tm->tm_sec);        /* %02d */
                    500:                break;
                    501:
                    502:            case 'T':
                    503:                if (!xstrftime(s, bsz - l, "%H:%M:%S", tm))
                    504:                    return (0);
                    505:                break;
                    506:
                    507:            case 'W':           /* mon 1 day of week */
                    508:                {
                    509:                    int week;
                    510:                    if (tm->tm_yday <= tm->tm_wday) {
                    511:                        week = 1;
                    512:
                    513:                        if ((tm->tm_mday - tm->tm_yday) > 4) {
                    514:                            week = 52;
                    515:                        }
                    516:                        if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0)
                    517:                            week = 52;
                    518:
                    519:                    } else {
                    520:
                    521:                        /* sun prev week */
                    522:                        int bw = tm->tm_yday - tm->tm_wday;
                    523:
                    524:                        if (tm->tm_wday > 0)
                    525:                            bw += 7;    /* sun end of week */
                    526:
                    527:                        week = (int) bw / 7;
                    528:
                    529:                        if ((bw % 7) > 2)       /* jan 1 is before friday */
                    530:                            week++;
                    531:                    }
                    532:                    FORMAT_STRING(1, 2, week);  /* %02d */
                    533:                    break;
                    534:                }
                    535:
                    536:            case 'U':           /* sun 1 day of week */
                    537:                {
                    538:                    int week, bw;
                    539:
                    540:                    if (tm->tm_yday <= tm->tm_wday) {
                    541:                        week = 1;
                    542:                        if ((tm->tm_mday - tm->tm_yday) > 4) {
                    543:                            week = 52;
                    544:                        }
                    545:                    } else {
                    546:                        /* sat prev week */
                    547:                        bw = tm->tm_yday - tm->tm_wday - 1;
                    548:                        if (tm->tm_wday >= 0)
                    549:                            bw += 7;    /* sat end of week */
                    550:                        week = (int) bw / 7;
                    551:                        if ((bw % 7) > 1) {     /* jan 1 is before friday */
                    552:                            week++;
                    553:                        }
                    554:                    }
                    555:                    FORMAT_STRING(1, 2, week);  /* %02d */
                    556:                    break;
                    557:                }
                    558:
                    559:            case 'w':           /* day of week, sun=0 */
                    560:                FORMAT_STRING(1, 2, tm->tm_wday);       /* %02d */
                    561:                break;
                    562:
                    563:            case 'y':
                    564:                FORMAT_STRING(1, 2, tm->tm_year % 100);         /* %02d */
                    565:                break;
                    566:
                    567:            case 'Y':
                    568:                FORMAT_STRING(1, 4, tm->tm_year);       /* %04d */
                    569:                break;
                    570:
                    571: #if 0
                    572:            case 'Z':
                    573:                COPY_STRING(tm->tm_zone);
                    574:                break;
                    575: #endif
                    576:            }                   /* switch */
                    577:
                    578:            while (*s != '\0') {
                    579:                s++;
                    580:                l++;
                    581:            }
                    582:        }
                    583:     }
                    584:     return (l);
                    585: }
                    586:
                    587:
                    588:
                    589: /* time_t  */
                    590: double gtimegm(tm)
                    591: struct tm *tm;
                    592: {
                    593:     register int i;
                    594:     /* returns sec from year ZERO_YEAR, defined in plot.h */
                    595:     double dsec;
                    596:
                    597:     dsec = 0;
                    598:     if (tm->tm_year < ZERO_YEAR) {
                    599:        for (i = tm->tm_year; i < ZERO_YEAR; i++) {
                    600:            dsec -= (double) gdysize(i);
                    601:        }
                    602:     } else {
                    603:        for (i = ZERO_YEAR; i < tm->tm_year; i++) {
                    604:            dsec += (double) gdysize(i);
                    605:        }
                    606:     }
                    607:     if (tm->tm_mday > 0) {
                    608:        for (i = 0; i < tm->tm_mon; i++) {
                    609:            dsec += (double) mndday[i] + (i == 1 && (gdysize(tm->tm_year) > 365));
                    610:        }
                    611:        dsec += (double) tm->tm_mday - 1;
                    612:     } else {
                    613:        dsec += (double) tm->tm_yday;
                    614:     }
                    615:     dsec *= (double) 24;
                    616:
                    617:     dsec += tm->tm_hour;
                    618:     dsec *= 60.0;
                    619:     dsec += tm->tm_min;
                    620:     dsec *= 60.0;
                    621:     dsec += tm->tm_sec;
                    622:
                    623:     FPRINTF((stderr, "broken-down time : %d/%d/%d:%d:%d:%d = %g seconds\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec, dsec));
                    624:
                    625:     return (dsec);
                    626: }
                    627:
                    628: int ggmtime(tm, l_clock)
                    629: struct tm *tm;
                    630: /* time_t l_clock; */
                    631: double l_clock;
                    632: {
                    633:     /* l_clock is relative to ZERO_YEAR, jan 1, 00:00:00,defined in plot.h */
                    634:     int i, days;
                    635:
                    636:     /* dodgy way of doing wday - i hope it works ! */
                    637:
                    638:     int wday = JAN_FIRST_WDAY; /* eg 6 for 2000 */
                    639:
                    640:     FPRINTF((stderr, "%g seconds = ", l_clock));
                    641:
                    642:     tm->tm_year = ZERO_YEAR;
                    643:     tm->tm_mday = tm->tm_yday = tm->tm_mon = tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
                    644:     if (l_clock < 0) {
                    645:        while (l_clock < 0) {
                    646:            int days_in_year = gdysize(--tm->tm_year);
                    647:            l_clock += days_in_year * DAY_SEC;  /* 24*3600 */
                    648:            /* adding 371 is noop in modulo 7 arithmetic, but keeps wday +ve */
                    649:            wday += 371 - days_in_year;
                    650:        }
                    651:     } else {
                    652:        for (;;) {
                    653:            int days_in_year = gdysize(tm->tm_year);
                    654:            if (l_clock < days_in_year * DAY_SEC)
                    655:                break;
                    656:            l_clock -= days_in_year * DAY_SEC;
                    657:            tm->tm_year++;
                    658:            /* only interested in result modulo 7, but %7 is expensive */
                    659:            wday += (days_in_year - 364);
                    660:        }
                    661:     }
                    662:     tm->tm_yday = (int) (l_clock / DAY_SEC);
                    663:     l_clock -= tm->tm_yday * DAY_SEC;
                    664:     tm->tm_hour = (int) l_clock / 3600;
                    665:     l_clock -= tm->tm_hour * 3600;
                    666:     tm->tm_min = (int) l_clock / 60;
                    667:     l_clock -= tm->tm_min * 60;
                    668:     tm->tm_sec = (int) l_clock;
                    669:
                    670:     days = tm->tm_yday;
                    671:
                    672:     /* wday%7 should be day of week of first day of year */
                    673:     tm->tm_wday = (wday + days) % 7;
                    674:
                    675:     while (days >= (i = mndday[tm->tm_mon] + (tm->tm_mon == 1 && (gdysize(tm->tm_year) > 365)))) {
                    676:        days -= i;
                    677:        tm->tm_mon++;
                    678:     }
                    679:     tm->tm_mday = days + 1;
                    680:
                    681:     FPRINTF((stderr, "broken-down time : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
                    682:
                    683:     return (0);
                    684: }
                    685:
                    686:
                    687:
                    688:
                    689: #else /* USE_SYSTEM_TIME */
                    690:
                    691: /* define gnu time routines in terms of system time routines */
                    692:
                    693: int gstrftime(buf, bufsz, fmt, l_clock)
                    694: char *buf;
                    695: int bufsz;
                    696: char *fmt;
                    697: double l_clock;
                    698: {
                    699:     time_t t = (time_t) l_clock;
                    700:     return strftime(buf, bufsz, fmt, gmtime(&t));
                    701: }
                    702:
                    703: double gtimegm(tm)
                    704: struct tm *tm;
                    705: {
                    706:     return (double) mktime(tm);
                    707: }
                    708:
                    709: int ggmtime(tm, l_clock)
                    710: struct tm *tm;
                    711: double l_clock;
                    712: {
                    713:     time_t t = (time_t) l_clock;
                    714:     struct tm *m = gmtime(&t);
                    715:     *tm = *m;                  /* can any non-ansi compilers not do this ? */
                    716: }
                    717:
                    718: #define NOTHING
                    719: #define LETTER(L, width, field, extra) \
                    720:   case L: s=read_int(s,width,&tm->field); extra; continue
                    721:
                    722: /* supplemental routine gstrptime() to read a formatted time */
                    723:
                    724: char *
                    725:  gstrptime(s, fmt, tm)
                    726: char *s;
                    727: char *fmt;
                    728: struct tm *tm;
                    729: {
                    730:     FPRINTF((stderr, "gstrptime(\"%s\", \"%s\")\n", s, fmt));
                    731:
                    732:     /* linux does not appear to like years before 1902
                    733:      * NT complains if its before 1970
                    734:      * initialise fields to midnight, 1st Jan, 1970 (for relative times)
                    735:      */
                    736:     tm->tm_sec = tm->tm_min = tm->tm_hour = 0;
                    737:     tm->tm_mday = 1;
                    738:     tm->tm_mon = 0;
                    739:     tm->tm_year = 70;
                    740:     /* oops - it goes wrong without this */
                    741:     tm->tm_isdst = 0;
                    742:
                    743:     for (; *fmt && *s; ++fmt) {
                    744:        if (*fmt != '%') {
                    745:            if (*s != *fmt)
                    746:                return s;
                    747:            ++s;
                    748:            continue;
                    749:        }
                    750:        assert(*fmt == '%');
                    751:
                    752:        switch (*++fmt) {
                    753:        case 0:
                    754:            /* uh oh - % is last character in format */
                    755:            return s;
                    756:        case '%':
                    757:            /* literal % */
                    758:            if (*s++ != '%')
                    759:                return s - 1;
                    760:            continue;
                    761:
                    762:            LETTER('d', 2, tm_mday, NOTHING);
                    763:            LETTER('m', 2, tm_mon, NOTHING);
                    764:            LETTER('y', 2, tm_year, NOTHING);
                    765:            LETTER('Y', 4, tm_year, tm->tm_year -= 1900);
                    766:            LETTER('H', 2, tm_hour, NOTHING);
                    767:            LETTER('M', 2, tm_min, NOTHING);
                    768:            LETTER('S', 2, tm_sec, NOTHING);
                    769:
                    770:        default:
                    771:            int_error("incorrect time format character", NO_CARET);
                    772:        }
                    773:     }
                    774:
                    775:     FPRINTF((stderr, "Before mktime : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
                    776:     /* mktime range-checks the time */
                    777:
                    778:     if (mktime(tm) == -1) {
                    779:        FPRINTF((stderr, "mktime() was not happy\n"));
                    780:        int_error("Invalid date/time [mktime() did not like it]", NO_CARET);
                    781:     }
                    782:     FPRINTF((stderr, "After mktime : %d/%d/%d:%d:%d:%d\n", tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_hour, tm->tm_min, tm->tm_sec));
                    783:
                    784:     return s;
                    785: }
                    786:
                    787:
                    788: #endif /* USE_SYSTEM_TIME */
                    789:
                    790:
                    791: #ifdef TEST_TIME
                    792:
                    793: char *abbrev_month_names[] =
                    794: {"jan", "feb", "mar", "apr", "may", "jun", "jul",
                    795:  "aug", "sep", "oct", "nov", "dec"};
                    796: char *full_month_names[] =
                    797: {"January", "February", "March", "April", "May",
                    798: "June", "July", "August", "September", "October", "November", "December"};
                    799:
                    800: char *abbrev_day_names[] =
                    801: {"sun", "mon", "tue", "wed", "thu", "fri", "sat"};
                    802: char *full_day_names[] =
                    803: {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
                    804:
                    805:
                    806:
                    807: /* either print current time using supplied format, or read
                    808:  * supplied time using supplied format
                    809:  */
                    810:
                    811:
                    812: int main(argc,argv)
                    813: int argc;
                    814: char *argv[];
                    815: {
                    816:     char output[80];
                    817:
                    818:     if (argc < 2) {
                    819:        fputs("usage : test 'format' ['time']\n", stderr);
                    820:        exit(EXIT_FAILURE);
                    821:     }
                    822:     if (argc == 2) {
                    823:        struct timeb now;
                    824:        struct tm *tm;
                    825:        ftime(&now);
                    826:        tm = gmtime(&now.time);
                    827:        xstrftime(output, 80, argv[1], tm);
                    828:        puts(output);
                    829:     } else {
                    830:        struct tm tm;
                    831:        gstrptime(argv[2], argv[1], &tm);
                    832:        puts(asctime(&tm));
                    833:     }
                    834:     exit(EXIT_SUCCESS);
                    835: }
                    836:
                    837: #endif /* TEST_TIME */

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