The notion would be to rely on strftime only to handle the year (along the lines below); this would avoid some of the problems folks have noted. (There's still the business of zero padding of the year to consider). --ado ------- asctime.c ------- *** /tmp/geta26648 Tue Oct 12 09:41:36 2004 --- /tmp/getb26648 Tue Oct 12 09:41:36 2004 *************** *** 5,11 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)asctime.c 7.22"; #endif /* !defined NOID */ #endif /* !defined lint */ --- 5,11 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)asctime.c 7.25"; #endif /* !defined NOID */ #endif /* !defined lint */ *************** *** 15,21 **** #include "tzfile.h" #if STRICTLY_STANDARD_ASCTIME ! #define ASCTIME_FMT "%.3s %.3s%3d %.2d:%.2d:%.2d %ld\n" #define ASCTIME_FMT_B ASCTIME_FMT #else /* !STRICTLY_STANDARD_ASCTIME */ /* --- 15,21 ---- #include "tzfile.h" #if STRICTLY_STANDARD_ASCTIME ! #define ASCTIME_FMT "%.3s %.3s%3d %.2d:%.2d:%.2d %s\n" #define ASCTIME_FMT_B ASCTIME_FMT #else /* !STRICTLY_STANDARD_ASCTIME */ /* *************** *** 31,37 **** ** For years that are less than four digits, we pad the output with ** spaces before the newline to get the newline in the traditional place. */ ! #define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4ld\n" /* ** For years that are more than four digits we put extra spaces before the year ** so that code trying to overwrite the newline won't end up overwriting --- 31,37 ---- ** For years that are less than four digits, we pad the output with ** spaces before the newline to get the newline in the traditional place. */ ! #define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n" /* ** For years that are more than four digits we put extra spaces before the year ** so that code trying to overwrite the newline won't end up overwriting *************** *** 38,44 **** ** a digit within a year and truncating the year (operating on the assumption ** that no output is better than wrong output). */ ! #define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %ld\n" #endif /* !STRICTLY_STANDARD_ASCTIME */ #define STD_ASCTIME_BUF_SIZE 26 --- 38,44 ---- ** a digit within a year and truncating the year (operating on the assumption ** that no output is better than wrong output). */ ! #define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n" #endif /* !STRICTLY_STANDARD_ASCTIME */ #define STD_ASCTIME_BUF_SIZE 26 *************** *** 74,80 **** }; register const char * wn; register const char * mn; ! long year; char result[MAX_ASCTIME_BUF_SIZE]; if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK) --- 74,80 ---- }; register const char * wn; register const char * mn; ! char year[INT_STRLEN_MAXIMUM(int) + 2]; char result[MAX_ASCTIME_BUF_SIZE]; if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK) *************** *** 83,94 **** if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR) mn = "???"; else mn = mon_name[timeptr->tm_mon]; ! year = timeptr->tm_year + (long) TM_YEAR_BASE; /* ** We avoid using snprintf since it's not available on all systems. */ ! (void) sprintf(result, ! ((year >= -999 && year <= 9999) ? ASCTIME_FMT : ASCTIME_FMT_B), wn, mn, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec, --- 83,94 ---- if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR) mn = "???"; else mn = mon_name[timeptr->tm_mon]; ! (void) strftime(year, sizeof year, "%Y", timeptr); /* ** We avoid using snprintf since it's not available on all systems. */ ! (void) sprintf(result, ! ((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B), wn, mn, timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec,
"Olson, Arthur David (NIH/NCI)" <olsona@dc37a.nci.nih.gov> writes:
The notion would be to rely on strftime only to handle the year (along the lines below); this would avoid some of the problems folks have noted.
The main remaining problem is that asctime.c is no longer decoupled from the rest of the tz code, as that change would cause it to assume that it is invoking tz's strftime, not some other (conforming) strftime. This is because conforming strftime implementations are allowed to dump core if you give them (say) tm_mday out of range, even if they don't need to access tm_mday to do their job. If we make it clear that asctime.c cannot invoke just any conforming strftime, but must invoke one that acts like our strftime, then we should be OK. That could be done in a comment, I think. Something like this: /* ** Use strftime to convert %Y, to avoid overflow problems when ** computing timeptr->tm_year + TM_YEAR_BASE. Assume that strftime ** behaves like the tz strftime, in that it is unaffected by other ** out-of-range members (e.g., timeptr->tm_mday) when processing "%Y". */ (void) strftime(year, sizeof year, "%Y", timeptr);
participants (2)
-
Olson, Arthur David (NIH/NCI) -
Paul Eggert