OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [expect/] [exp_strf.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* exp_strp.c - functions for exp_timestamp */
2
/*
3
 * strftime.c
4
 *
5
 * Public-domain implementation of ANSI C library routine.
6
 *
7
 * It's written in old-style C for maximal portability.
8
 * However, since I'm used to prototypes, I've included them too.
9
 *
10
 * If you want stuff in the System V ascftime routine, add the SYSV_EXT define.
11
 * For extensions from SunOS, add SUNOS_EXT.
12
 * For stuff needed to implement the P1003.2 date command, add POSIX2_DATE.
13
 * For VMS dates, add VMS_EXT.
14
 * For complete POSIX semantics, add POSIX_SEMANTICS.
15
 *
16
 * The code for %c, %x, and %X now follows the 1003.2 specification for
17
 * the POSIX locale.
18
 * This version ignores LOCALE information.
19
 * It also doesn't worry about multi-byte characters.
20
 * So there.
21
 *
22
 * This file is also shipped with GAWK (GNU Awk), gawk specific bits of
23
 * code are included if GAWK is defined.
24
 *
25
 * Arnold Robbins <arnold@skeeve.atl.ga.us>
26
 * January, February, March, 1991
27
 * Updated March, April 1992
28
 * Updated April, 1993
29
 * Updated February, 1994
30
 * Updated May, 1994
31
 * Updated January 1995
32
 * Updated September 1995
33
 *
34
 * Fixes from ado@elsie.nci.nih.gov
35
 * February 1991, May 1992
36
 * Fixes from Tor Lillqvist tml@tik.vtt.fi
37
 * May, 1993
38
 * Further fixes from ado@elsie.nci.nih.gov
39
 * February 1994
40
 * %z code from chip@chinacat.unicom.com
41
 * Applied September 1995
42
 *
43
 *
44
 * Modified by Don Libes for Expect, 10/93 and 12/95.
45
 * Forced POSIX semantics.
46
 * Replaced inline/min/max stuff with a single range function.
47
 * Removed tzset stuff.
48
 * Commented out tzname stuff.
49
 *
50
 * According to Arnold, the current version of this code can ftp'd from
51
 * ftp.mathcs.emory.edu:/pub/arnold/strftime.shar.gz
52
 *
53
 */
54
 
55
#include "expect_cf.h"
56
#include "tcl.h"
57
 
58
#include <stdio.h>
59
#include <ctype.h>
60
#include "string.h"
61
 
62
/* according to Karl Vogel, time.h is insufficient on Pyramid */
63
/* following is recommended by autoconf */
64
 
65
#ifdef TIME_WITH_SYS_TIME
66
# include <sys/time.h>
67
# include <time.h>
68
#else
69
# ifdef HAVE_SYS_TIME_H
70
#  include <sys/time.h>
71
# else
72
#  include <time.h>
73
# endif
74
#endif
75
 
76
 
77
 
78
#include <sys/types.h>
79
 
80
#define SYSV_EXT        1       /* stuff in System V ascftime routine */
81
#define POSIX2_DATE     1       /* stuff in Posix 1003.2 date command */
82
 
83
#if defined(POSIX2_DATE) && ! defined(SYSV_EXT)
84
#define SYSV_EXT        1
85
#endif
86
 
87
#if defined(POSIX2_DATE)
88
#define adddecl(stuff)  stuff
89
#else
90
#define adddecl(stuff)
91
#endif
92
 
93
#ifndef __STDC__
94
#define const
95
 
96
extern char *getenv();
97
static int weeknumber();
98
adddecl(static int iso8601wknum();)
99
#else
100
 
101
#ifndef strchr
102
extern char *strchr(const char *str, int ch);
103
#endif
104
extern char *getenv(const char *v);
105
static int weeknumber(const struct tm *timeptr, int firstweekday);
106
adddecl(static int iso8601wknum(const struct tm *timeptr);)
107
#endif
108
 
109
/* attempt to use strftime to compute timezone, else fallback to */
110
/* less portable ways */
111
#if !defined(HAVE_STRFTIME)
112
# if defined(HAVE_SV_TIMEZONE)
113
extern char *tzname[2];
114
extern int daylight;
115
# else
116
#  if defined(HAVE_TIMEZONE)
117
 
118
char           *
119
zone_name (tp)
120
struct tm      *tp;
121
{
122
        char           *timezone ();
123
        struct timeval  tv;
124
        struct timezone tz;
125
 
126
        gettimeofday (&tv, &tz);
127
 
128
        return timezone (tz.tz_minuteswest, tp->tm_isdst);
129
}
130
 
131
#  endif /* HAVE_TIMEZONE */
132
# endif /* HAVE_SV_TIMEZONE */
133
#endif /* HAVE_STRFTIME */
134
 
135
static int
136
range(low,item,hi)
137
int low, item, hi;
138
{
139
        if (item < low) return low;
140
        if (item > hi) return hi;
141
        return item;
142
}
143
 
144
/* strftime --- produce formatted time */
145
 
146
void
147
/*size_t*/
148
#ifndef __STDC__
149
exp_strftime(/*s,*/ format, timeptr, dstring)
150
/*char *s;*/
151
char *format;
152
const struct tm *timeptr;
153
Tcl_DString *dstring;
154
#else
155
/*exp_strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)*/
156
exp_strftime(char *format, const struct tm *timeptr,Tcl_DString *dstring)
157
#endif
158
{
159
        int copied;     /* used to suppress copying when called recursively */
160
 
161
#if 0
162
        char *endp = s + maxsize;
163
        char *start = s;
164
#endif
165
        char *percentptr;
166
 
167
        char tbuf[100];
168
        int i;
169
 
170
        /* various tables, useful in North America */
171
        static char *days_a[] = {
172
                "Sun", "Mon", "Tue", "Wed",
173
                "Thu", "Fri", "Sat",
174
        };
175
        static char *days_l[] = {
176
                "Sunday", "Monday", "Tuesday", "Wednesday",
177
                "Thursday", "Friday", "Saturday",
178
        };
179
        static char *months_a[] = {
180
                "Jan", "Feb", "Mar", "Apr", "May", "Jun",
181
                "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
182
        };
183
        static char *months_l[] = {
184
                "January", "February", "March", "April",
185
                "May", "June", "July", "August", "September",
186
                "October", "November", "December",
187
        };
188
        static char *ampm[] = { "AM", "PM", };
189
 
190
/*      for (; *format && s < endp - 1; format++) {*/
191
        for (; *format ; format++) {
192
                tbuf[0] = '\0';
193
                copied = 0;              /* has not been copied yet */
194
                percentptr = strchr(format,'%');
195
                if (percentptr == 0) {
196
                        Tcl_DStringAppend(dstring,format,-1);
197
                        goto out;
198
                } else if (percentptr != format) {
199
                        Tcl_DStringAppend(dstring,format,percentptr - format);
200
                        format = percentptr;
201
                }
202
#if 0
203
                if (*format != '%') {
204
                        *s++ = *format;
205
                        continue;
206
                }
207
#endif
208
        again:
209
                switch (*++format) {
210
                case '\0':
211
                        Tcl_DStringAppend(dstring,"%",1);
212
#if 0
213
                        *s++ = '%';
214
#endif
215
                        goto out;
216
 
217
                case '%':
218
                        Tcl_DStringAppend(dstring,"%",1);
219
                        copied = 1;
220
                        break;
221
#if 0
222
                        *s++ = '%';
223
                        continue;
224
#endif
225
 
226
                case 'a':       /* abbreviated weekday name */
227
                        if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
228
                                strcpy(tbuf, "?");
229
                        else
230
                                strcpy(tbuf, days_a[timeptr->tm_wday]);
231
                        break;
232
 
233
                case 'A':       /* full weekday name */
234
                        if (timeptr->tm_wday < 0 || timeptr->tm_wday > 6)
235
                                strcpy(tbuf, "?");
236
                        else
237
                                strcpy(tbuf, days_l[timeptr->tm_wday]);
238
                        break;
239
 
240
#ifdef SYSV_EXT
241
                case 'h':       /* abbreviated month name */
242
#endif
243
                case 'b':       /* abbreviated month name */
244
                        if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
245
                                strcpy(tbuf, "?");
246
                        else
247
                                strcpy(tbuf, months_a[timeptr->tm_mon]);
248
                        break;
249
 
250
                case 'B':       /* full month name */
251
                        if (timeptr->tm_mon < 0 || timeptr->tm_mon > 11)
252
                                strcpy(tbuf, "?");
253
                        else
254
                                strcpy(tbuf, months_l[timeptr->tm_mon]);
255
                        break;
256
 
257
                case 'c':       /* appropriate date and time representation */
258
                        sprintf(tbuf, "%s %s %2d %02d:%02d:%02d %d",
259
                                days_a[range(0, timeptr->tm_wday, 6)],
260
                                months_a[range(0, timeptr->tm_mon, 11)],
261
                                range(1, timeptr->tm_mday, 31),
262
                                range(0, timeptr->tm_hour, 23),
263
                                range(0, timeptr->tm_min, 59),
264
                                range(0, timeptr->tm_sec, 61),
265
                                timeptr->tm_year + 1900);
266
                        break;
267
 
268
                case 'd':       /* day of the month, 01 - 31 */
269
                        i = range(1, timeptr->tm_mday, 31);
270
                        sprintf(tbuf, "%02d", i);
271
                        break;
272
 
273
                case 'H':       /* hour, 24-hour clock, 00 - 23 */
274
                        i = range(0, timeptr->tm_hour, 23);
275
                        sprintf(tbuf, "%02d", i);
276
                        break;
277
 
278
                case 'I':       /* hour, 12-hour clock, 01 - 12 */
279
                        i = range(0, timeptr->tm_hour, 23);
280
                        if (i == 0)
281
                                i = 12;
282
                        else if (i > 12)
283
                                i -= 12;
284
                        sprintf(tbuf, "%02d", i);
285
                        break;
286
 
287
                case 'j':       /* day of the year, 001 - 366 */
288
                        sprintf(tbuf, "%03d", timeptr->tm_yday + 1);
289
                        break;
290
 
291
                case 'm':       /* month, 01 - 12 */
292
                        i = range(0, timeptr->tm_mon, 11);
293
                        sprintf(tbuf, "%02d", i + 1);
294
                        break;
295
 
296
                case 'M':       /* minute, 00 - 59 */
297
                        i = range(0, timeptr->tm_min, 59);
298
                        sprintf(tbuf, "%02d", i);
299
                        break;
300
 
301
                case 'p':       /* am or pm based on 12-hour clock */
302
                        i = range(0, timeptr->tm_hour, 23);
303
                        if (i < 12)
304
                                strcpy(tbuf, ampm[0]);
305
                        else
306
                                strcpy(tbuf, ampm[1]);
307
                        break;
308
 
309
                case 'S':       /* second, 00 - 61 */
310
                        i = range(0, timeptr->tm_sec, 61);
311
                        sprintf(tbuf, "%02d", i);
312
                        break;
313
 
314
                case 'U':       /* week of year, Sunday is first day of week */
315
                        sprintf(tbuf, "%02d", weeknumber(timeptr, 0));
316
                        break;
317
 
318
                case 'w':       /* weekday, Sunday == 0, 0 - 6 */
319
                        i = range(0, timeptr->tm_wday, 6);
320
                        sprintf(tbuf, "%d", i);
321
                        break;
322
 
323
                case 'W':       /* week of year, Monday is first day of week */
324
                        sprintf(tbuf, "%02d", weeknumber(timeptr, 1));
325
                        break;
326
 
327
                case 'x':       /* appropriate date representation */
328
                        sprintf(tbuf, "%s %s %2d %d",
329
                                days_a[range(0, timeptr->tm_wday, 6)],
330
                                months_a[range(0, timeptr->tm_mon, 11)],
331
                                range(1, timeptr->tm_mday, 31),
332
                                timeptr->tm_year + 1900);
333
                        break;
334
 
335
                case 'X':       /* appropriate time representation */
336
                        sprintf(tbuf, "%02d:%02d:%02d",
337
                                range(0, timeptr->tm_hour, 23),
338
                                range(0, timeptr->tm_min, 59),
339
                                range(0, timeptr->tm_sec, 61));
340
                        break;
341
 
342
                case 'y':       /* year without a century, 00 - 99 */
343
                        i = timeptr->tm_year % 100;
344
                        sprintf(tbuf, "%02d", i);
345
                        break;
346
 
347
                case 'Y':       /* year with century */
348
                        sprintf(tbuf, "%d", 1900 + timeptr->tm_year);
349
                        break;
350
 
351
                case 'Z':       /* time zone name or abbrevation */
352
#if defined(HAVE_STRFTIME)
353
                        strftime(tbuf,sizeof tbuf,"%Z",timeptr);
354
#else
355
# if defined(HAVE_SV_TIMEZONE)
356
                        i = 0;
357
                        if (daylight && timeptr->tm_isdst)
358
                                i = 1;
359
                        strcpy(tbuf, tzname[i]);
360
# else
361
                        strcpy(tbuf, zone_name (timeptr));
362
#  if defined(HAVE_TIMEZONE)
363
#  endif /* HAVE_TIMEZONE */
364
                        /* no timezone available */
365
                        /* feel free to add others here */
366
# endif /* HAVE_SV_TIMEZONE */
367
#endif /* HAVE STRFTIME */
368
                        break;
369
 
370
#ifdef SYSV_EXT
371
                case 'n':       /* same as \n */
372
                        tbuf[0] = '\n';
373
                        tbuf[1] = '\0';
374
                        break;
375
 
376
                case 't':       /* same as \t */
377
                        tbuf[0] = '\t';
378
                        tbuf[1] = '\0';
379
                        break;
380
 
381
                case 'D':       /* date as %m/%d/%y */
382
                        exp_strftime("%m/%d/%y", timeptr, dstring);
383
                        copied = 1;
384
/*                      exp_strftime(tbuf, sizeof tbuf, "%m/%d/%y", timeptr);*/
385
                        break;
386
 
387
                case 'e':       /* day of month, blank padded */
388
                        sprintf(tbuf, "%2d", range(1, timeptr->tm_mday, 31));
389
                        break;
390
 
391
                case 'r':       /* time as %I:%M:%S %p */
392
                        exp_strftime("%I:%M:%S %p", timeptr, dstring);
393
                        copied = 1;
394
/*                      exp_strftime(tbuf, sizeof tbuf, "%I:%M:%S %p", timeptr);*/
395
                        break;
396
 
397
                case 'R':       /* time as %H:%M */
398
                        exp_strftime("%H:%M", timeptr, dstring);
399
                        copied = 1;
400
/*                      exp_strftime(tbuf, sizeof tbuf, "%H:%M", timeptr);*/
401
                        break;
402
 
403
                case 'T':       /* time as %H:%M:%S */
404
                        exp_strftime("%H:%M:%S", timeptr, dstring);
405
                        copied = 1;
406
/*                      exp_strftime(tbuf, sizeof tbuf, "%H:%M:%S", timeptr);*/
407
                        break;
408
#endif
409
 
410
#ifdef POSIX2_DATE
411
                case 'C':
412
                        sprintf(tbuf, "%02d", (timeptr->tm_year + 1900) / 100);
413
                        break;
414
 
415
 
416
                case 'E':
417
                case 'O':
418
                        /* POSIX locale extensions, ignored for now */
419
                        goto again;
420
                case 'V':       /* week of year according ISO 8601 */
421
                        sprintf(tbuf, "%02d", iso8601wknum(timeptr));
422
                        break;
423
 
424
                case 'u':
425
                /* ISO 8601: Weekday as a decimal number [1 (Monday) - 7] */
426
                        sprintf(tbuf, "%d", timeptr->tm_wday == 0 ? 7 :
427
                                        timeptr->tm_wday);
428
                        break;
429
#endif  /* POSIX2_DATE */
430
                default:
431
                        tbuf[0] = '%';
432
                        tbuf[1] = *format;
433
                        tbuf[2] = '\0';
434
                        break;
435
                }
436
                if (!copied)
437
                        Tcl_DStringAppend(dstring,tbuf,-1);
438
#if 0
439
                i = strlen(tbuf);
440
                if (i) {
441
                        if (s + i < endp - 1) {
442
                                strcpy(s, tbuf);
443
                                s += i;
444
                        } else
445
                                return 0;
446
#endif
447
        }
448
out:;
449
#if 0
450
        if (s < endp && *format == '\0') {
451
                *s = '\0';
452
                return (s - start);
453
        } else
454
                return 0;
455
#endif
456
}
457
 
458
/* isleap --- is a year a leap year? */
459
 
460
#ifndef __STDC__
461
static int
462
isleap(year)
463
int year;
464
#else
465
static int
466
isleap(int year)
467
#endif
468
{
469
        return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
470
}
471
 
472
#ifdef POSIX2_DATE
473
/* iso8601wknum --- compute week number according to ISO 8601 */
474
 
475
#ifndef __STDC__
476
static int
477
iso8601wknum(timeptr)
478
const struct tm *timeptr;
479
#else
480
static int
481
iso8601wknum(const struct tm *timeptr)
482
#endif
483
{
484
        /*
485
         * From 1003.2:
486
         *      If the week (Monday to Sunday) containing January 1
487
         *      has four or more days in the new year, then it is week 1;
488
         *      otherwise it is the highest numbered week of the previous
489
         *      (52 or 53) year, and the next week is week 1.
490
         *
491
         * ADR: This means if Jan 1 was Monday through Thursday,
492
         *      it was week 1, otherwise week 53.
493
         *
494
         * XPG4 erroneously included POSIX.2 rationale text in the
495
         * main body of the standard. Thus it requires week 53.
496
         */
497
 
498
        int weeknum, jan1day, diff;
499
 
500
        /* get week number, Monday as first day of the week */
501
        weeknum = weeknumber(timeptr, 1);
502
 
503
        /*
504
         * With thanks and tip of the hatlo to tml@tik.vtt.fi
505
         *
506
         * What day of the week does January 1 fall on?
507
         * We know that
508
         *      (timeptr->tm_yday - jan1.tm_yday) MOD 7 ==
509
         *              (timeptr->tm_wday - jan1.tm_wday) MOD 7
510
         * and that
511
         *      jan1.tm_yday == 0
512
         * and that
513
         *      timeptr->tm_wday MOD 7 == timeptr->tm_wday
514
         * from which it follows that. . .
515
         */
516
        jan1day = timeptr->tm_wday - (timeptr->tm_yday % 7);
517
        if (jan1day < 0)
518
                jan1day += 7;
519
 
520
        /*
521
         * If Jan 1 was a Monday through Thursday, it was in
522
         * week 1.  Otherwise it was last year's highest week, which is
523
         * this year's week 0.
524
         *
525
         * What does that mean?
526
         * If Jan 1 was Monday, the week number is exactly right, it can
527
         *      never be 0.
528
         * If it was Tuesday through Thursday, the weeknumber is one
529
         *      less than it should be, so we add one.
530
         * Otherwise, Friday, Saturday or Sunday, the week number is
531
         * OK, but if it is 0, it needs to be 52 or 53.
532
         */
533
        switch (jan1day) {
534
        case 1:         /* Monday */
535
                break;
536
        case 2:         /* Tuesday */
537
        case 3:         /* Wednesday */
538
        case 4:         /* Thursday */
539
                weeknum++;
540
                break;
541
        case 5:         /* Friday */
542
        case 6:         /* Saturday */
543
        case 0:          /* Sunday */
544
                if (weeknum == 0) {
545
#ifdef USE_BROKEN_XPG4
546
                        /* XPG4 (as of March 1994) says 53 unconditionally */
547
                        weeknum = 53;
548
#else
549
                        /* get week number of last week of last year */
550
                        struct tm dec31ly;      /* 12/31 last year */
551
                        dec31ly = *timeptr;
552
                        dec31ly.tm_year--;
553
                        dec31ly.tm_mon = 11;
554
                        dec31ly.tm_mday = 31;
555
                        dec31ly.tm_wday = (jan1day == 0) ? 6 : jan1day - 1;
556
                        dec31ly.tm_yday = 364 + isleap(dec31ly.tm_year + 1900);
557
                        weeknum = iso8601wknum(& dec31ly);
558
#endif
559
                }
560
                break;
561
        }
562
 
563
        if (timeptr->tm_mon == 11) {
564
                /*
565
                 * The last week of the year
566
                 * can be in week 1 of next year.
567
                 * Sigh.
568
                 *
569
                 * This can only happen if
570
                 *      M   T  W
571
                 *      29  30 31
572
                 *      30  31
573
                 *      31
574
                 */
575
                int wday, mday;
576
 
577
                wday = timeptr->tm_wday;
578
                mday = timeptr->tm_mday;
579
                if (   (wday == 1 && (mday >= 29 && mday <= 31))
580
                    || (wday == 2 && (mday == 30 || mday == 31))
581
                    || (wday == 3 &&  mday == 31))
582
                        weeknum = 1;
583
        }
584
 
585
        return weeknum;
586
}
587
#endif
588
 
589
/* weeknumber --- figure how many weeks into the year */
590
 
591
/* With thanks and tip of the hatlo to ado@elsie.nci.nih.gov */
592
 
593
#ifndef __STDC__
594
static int
595
weeknumber(timeptr, firstweekday)
596
const struct tm *timeptr;
597
int firstweekday;
598
#else
599
static int
600
weeknumber(const struct tm *timeptr, int firstweekday)
601
#endif
602
{
603
        int wday = timeptr->tm_wday;
604
        int ret;
605
 
606
        if (firstweekday == 1) {
607
                if (wday == 0)   /* sunday */
608
                        wday = 6;
609
                else
610
                        wday--;
611
        }
612
        ret = ((timeptr->tm_yday + 7 - wday) / 7);
613
        if (ret < 0)
614
                ret = 0;
615
        return ret;
616
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.