Below find proposed changes, all (I hope) noncontroversial: 1. The addition of a comment to asctime.c warning against relying completely on strftime. 2. Changes to zdump.c to improve the output when gmtime() returns NULL and time_t is a strange type. 3. A fix to the declaration of wildabbr in localtime.c 4. Changes to some localtime.c internal functions from returning voids to returning struct tm *s. The last above is in preparation for doing a better job of handling the situation where a time_t value is fed to localtime or gmtime but the year associated with the time_t value won't fit in an int (as can happen if, for example, time_t is double). --ado ------- asctime.c ------- *** /tmp/geta3717 Mon Dec 27 09:18:15 2004 --- /tmp/getb3717 Mon Dec 27 09:18:15 2004 *************** *** 3,11 **** ** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). */ #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)asctime.c 7.29"; #endif /* !defined NOID */ #endif /* !defined lint */ --- 3,17 ---- ** 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). */ + /* + ** Avoid the temptation to punt entirely to strftime; + ** the output of strftime is supposed to be locale specific + ** whereas the output of asctime is supposed to be constant. + */ + #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)asctime.c 7.30"; #endif /* !defined NOID */ #endif /* !defined lint */ ------- zdump.c ------- *** /tmp/geta3736 Mon Dec 27 09:18:15 2004 --- /tmp/getb3736 Mon Dec 27 09:18:15 2004 *************** *** 1,4 **** ! static char elsieid[] = "@(#)zdump.c 7.57"; /* ** This code has been made independent of the rest of the time --- 1,4 ---- ! static char elsieid[] = "@(#)zdump.c 7.58"; /* ** This code has been made independent of the rest of the time *************** *** 151,156 **** --- 151,157 ---- static time_t hunt P((char * name, time_t lot, time_t hit)); static void setabsolutes(); static void show P((char * zone, time_t t, int v)); + static char * tformat P((void)); static time_t yeartot P((long y)); int *************** *** 469,475 **** if (v) { tmp = gmtime(&t); if (tmp == NULL) { ! (void) printf("%g", (double) t); } else { dumptime(tmp); (void) printf(" UTC"); --- 470,476 ---- if (v) { tmp = gmtime(&t); if (tmp == NULL) { ! (void) printf(tformat(), t); } else { dumptime(tmp); (void) printf(" UTC"); *************** *** 504,509 **** --- 505,529 ---- return (result == NULL) ? &nada : result; } + static char * + tformat() + { + if (0.5 == (time_t) 0.5) /* floating */ + return "%g"; + if (0 > (time_t) -1) { /* signed */ + if (sizeof (time_t) > sizeof (long)) + return "%lld"; + if (sizeof (time_t) == sizeof (long)) + return "%ld"; + return "%d"; + } + if (sizeof (time_t) > sizeof (unsigned long)) + return "%llu"; + if (sizeof (time_t) == sizeof (unsigned long)) + return "%lu"; + return "%u"; + } + static void dumptime(timeptr) register const struct tm * timeptr; ------- localtime.c ------- *** /tmp/geta3754 Mon Dec 27 09:18:15 2004 --- /tmp/getb3754 Mon Dec 27 09:18:15 2004 *************** *** 2,7 **** --- 2,8 ---- ** XXX--do the right thing if time_t is double and ** the value fed to gmtime or localtime is very very negative or ** very very positive (which causes problems with the days-and-rem logic). + ** Also: do the right thing in mktime if time_t is double. */ /* *************** *** 11,17 **** #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 7.83"; #endif /* !defined NOID */ #endif /* !defined lint */ --- 12,18 ---- #ifndef lint #ifndef NOID ! static char elsieid[] = "@(#)localtime.c 7.85"; #endif /* !defined NOID */ #endif /* !defined lint */ *************** *** 61,67 **** #define WILDABBR " " #endif /* !defined WILDABBR */ ! static char wildabbr[] = "WILDABBR"; static const char gmt[] = "GMT"; --- 62,68 ---- #define WILDABBR " " #endif /* !defined WILDABBR */ ! static char wildabbr[] = WILDABBR; static const char gmt[] = "GMT"; *************** *** 135,143 **** static const char * getoffset P((const char * strp, long * offsetp)); static const char * getrule P((const char * strp, struct rule * rulep)); static void gmtload P((struct state * sp)); ! static void gmtsub P((const time_t * timep, long offset, struct tm * tmp)); ! static void localsub P((const time_t * timep, long offset, struct tm * tmp)); static int increment_overflow P((int * number, int delta)); static int long_increment_overflow P((long * number, int delta)); --- 136,144 ---- static const char * getoffset P((const char * strp, long * offsetp)); static const char * getrule P((const char * strp, struct rule * rulep)); static void gmtload P((struct state * sp)); ! static struct tm * gmtsub P((const time_t * timep, long offset, struct tm * tmp)); ! static struct tm * localsub P((const time_t * timep, long offset, struct tm * tmp)); static int increment_overflow P((int * number, int delta)); static int long_increment_overflow P((long * number, int delta)); *************** *** 147,164 **** int base)); static void settzname P((void)); static time_t time1 P((struct tm * tmp, ! void(*funcp) P((const time_t *, long, struct tm *)), long offset)); static time_t time2 P((struct tm *tmp, ! void(*funcp) P((const time_t *, long, struct tm*)), long offset, int * okayp)); static time_t time2sub P((struct tm *tmp, ! void(*funcp) P((const time_t *, long, struct tm*)), long offset, int * okayp, int do_norm_secs)); ! static void timesub P((const time_t * timep, long offset, const struct state * sp, struct tm * tmp)); static int tmcomp P((const struct tm * atmp, const struct tm * btmp)); --- 148,165 ---- int base)); static void settzname P((void)); static time_t time1 P((struct tm * tmp, ! struct tm * (*funcp) P((const time_t *, long, struct tm *)), long offset)); static time_t time2 P((struct tm *tmp, ! struct tm * (*funcp) P((const time_t *, long, struct tm*)), long offset, int * okayp)); static time_t time2sub P((struct tm *tmp, ! struct tm * (*funcp) P((const time_t *, long, struct tm*)), long offset, int * okayp, int do_norm_secs)); ! static struct tm * timesub P((const time_t * timep, long offset, const struct state * sp, struct tm * tmp)); static int tmcomp P((const struct tm * atmp, const struct tm * btmp)); *************** *** 1033,1039 **** */ /*ARGSUSED*/ ! static void localsub(timep, offset, tmp) const time_t * const timep; const long offset; --- 1034,1040 ---- */ /*ARGSUSED*/ ! static struct tm * localsub(timep, offset, tmp) const time_t * const timep; const long offset; *************** *** 1042,1055 **** register struct state * sp; register const struct ttinfo * ttisp; register int i; const time_t t = *timep; sp = lclptr; #ifdef ALL_STATE ! if (sp == NULL) { ! gmtsub(timep, offset, tmp); ! return; ! } #endif /* defined ALL_STATE */ if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; --- 1043,1055 ---- register struct state * sp; register const struct ttinfo * ttisp; register int i; + register struct tm * result; const time_t t = *timep; sp = lclptr; #ifdef ALL_STATE ! if (sp == NULL) ! return gmtsub(timep, offset, tmp); #endif /* defined ALL_STATE */ if (sp->timecnt == 0 || t < sp->ats[0]) { i = 0; *************** *** 1071,1082 **** ** t += ttisp->tt_gmtoff; ** timesub(&t, 0L, sp, tmp); */ ! timesub(&t, ttisp->tt_gmtoff, sp, tmp); tmp->tm_isdst = ttisp->tt_isdst; tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; #ifdef TM_ZONE tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; #endif /* defined TM_ZONE */ } struct tm * --- 1071,1083 ---- ** t += ttisp->tt_gmtoff; ** timesub(&t, 0L, sp, tmp); */ ! result = timesub(&t, ttisp->tt_gmtoff, sp, tmp); tmp->tm_isdst = ttisp->tt_isdst; tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind]; #ifdef TM_ZONE tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind]; #endif /* defined TM_ZONE */ + return result; } struct tm * *************** *** 1084,1091 **** const time_t * const timep; { tzset(); ! localsub(timep, 0L, &tm); ! return &tm; } /* --- 1085,1091 ---- const time_t * const timep; { tzset(); ! return localsub(timep, 0L, &tm); } /* *************** *** 1097,1104 **** const time_t * const timep; struct tm * tm; { ! localsub(timep, 0L, tm); ! return tm; } /* --- 1097,1103 ---- const time_t * const timep; struct tm * tm; { ! return localsub(timep, 0L, tm); } /* *************** *** 1105,1116 **** ** gmtsub is to gmtime as localsub is to localtime. */ ! static void gmtsub(timep, offset, tmp) const time_t * const timep; const long offset; struct tm * const tmp; { if (!gmt_is_set) { gmt_is_set = TRUE; #ifdef ALL_STATE --- 1104,1117 ---- ** gmtsub is to gmtime as localsub is to localtime. */ ! static struct tm * gmtsub(timep, offset, tmp) const time_t * const timep; const long offset; struct tm * const tmp; { + register struct tm * result; + if (!gmt_is_set) { gmt_is_set = TRUE; #ifdef ALL_STATE *************** *** 1119,1125 **** #endif /* defined ALL_STATE */ gmtload(gmtptr); } ! timesub(timep, offset, gmtptr, tmp); #ifdef TM_ZONE /* ** Could get fancy here and deliver something such as --- 1120,1126 ---- #endif /* defined ALL_STATE */ gmtload(gmtptr); } ! result = timesub(timep, offset, gmtptr, tmp); #ifdef TM_ZONE /* ** Could get fancy here and deliver something such as *************** *** 1139,1144 **** --- 1140,1146 ---- #endif /* State Farm */ } #endif /* defined TM_ZONE */ + return result; } struct tm * *************** *** 1145,1152 **** gmtime(timep) const time_t * const timep; { ! gmtsub(timep, 0L, &tm); ! return &tm; } /* --- 1147,1153 ---- gmtime(timep) const time_t * const timep; { ! return gmtsub(timep, 0L, &tm); } /* *************** *** 1158,1165 **** const time_t * const timep; struct tm * tm; { ! gmtsub(timep, 0L, tm); ! return tm; } #ifdef STD_INSPIRED --- 1159,1165 ---- const time_t * const timep; struct tm * tm; { ! return gmtsub(timep, 0L, tm); } #ifdef STD_INSPIRED *************** *** 1169,1181 **** const time_t * const timep; const long offset; { ! gmtsub(timep, offset, &tm); ! return &tm; } #endif /* defined STD_INSPIRED */ ! static void timesub(timep, offset, sp, tmp) const time_t * const timep; const long offset; --- 1169,1180 ---- const time_t * const timep; const long offset; { ! return gmtsub(timep, offset, &tm); } #endif /* defined STD_INSPIRED */ ! static struct tm * timesub(timep, offset, sp, tmp) const time_t * const timep; const long offset; *************** *** 1275,1280 **** --- 1274,1280 ---- #ifdef TM_GMTOFF tmp->TM_GMTOFF = offset; #endif /* defined TM_GMTOFF */ + return tmp; } char * *************** *** 1391,1397 **** static time_t time2sub(tmp, funcp, offset, okayp, do_norm_secs) struct tm * const tmp; ! void (* const funcp) P((const time_t*, long, struct tm*)); const long offset; int * const okayp; const int do_norm_secs; --- 1391,1397 ---- static time_t time2sub(tmp, funcp, offset, okayp, do_norm_secs) struct tm * const tmp; ! struct tm * (* const funcp) P((const time_t*, long, struct tm*)); const long offset; int * const okayp; const int do_norm_secs; *************** *** 1486,1492 **** */ t = TYPE_SIGNED(time_t) ? 0 : (((unsigned long) 1) << bits); for ( ; ; ) { ! (*funcp)(&t, offset, &mytm); dir = tmcomp(&mytm, &yourtm); if (dir != 0) { if (bits-- < 0) --- 1486,1492 ---- */ t = TYPE_SIGNED(time_t) ? 0 : (((unsigned long) 1) << bits); for ( ; ; ) { ! /* XXX */ (void) (*funcp)(&t, offset, &mytm); dir = tmcomp(&mytm, &yourtm); if (dir != 0) { if (bits-- < 0) *************** *** 1524,1530 **** continue; newt = t + sp->ttis[j].tt_gmtoff - sp->ttis[i].tt_gmtoff; ! (*funcp)(&newt, offset, &mytm); if (tmcomp(&mytm, &yourtm) != 0) continue; if (mytm.tm_isdst != yourtm.tm_isdst) --- 1524,1530 ---- continue; newt = t + sp->ttis[j].tt_gmtoff - sp->ttis[i].tt_gmtoff; ! /* XXX */ (void) (*funcp)(&newt, offset, &mytm); if (tmcomp(&mytm, &yourtm) != 0) continue; if (mytm.tm_isdst != yourtm.tm_isdst) *************** *** 1543,1550 **** if ((newt < t) != (saved_seconds < 0)) return WRONG; t = newt; ! (*funcp)(&t, offset, tmp); ! *okayp = TRUE; return t; } --- 1543,1550 ---- if ((newt < t) != (saved_seconds < 0)) return WRONG; t = newt; ! if ((*funcp)(&t, offset, tmp)) ! *okayp = TRUE; return t; } *************** *** 1551,1557 **** static time_t time2(tmp, funcp, offset, okayp) struct tm * const tmp; ! void (* const funcp) P((const time_t*, long, struct tm*)); const long offset; int * const okayp; { --- 1551,1557 ---- static time_t time2(tmp, funcp, offset, okayp) struct tm * const tmp; ! struct tm * (* const funcp) P((const time_t*, long, struct tm*)); const long offset; int * const okayp; { *************** *** 1569,1575 **** static time_t time1(tmp, funcp, offset) struct tm * const tmp; ! void (* const funcp) P((const time_t *, long, struct tm *)); const long offset; { register time_t t; --- 1569,1575 ---- static time_t time1(tmp, funcp, offset) struct tm * const tmp; ! struct tm * (* const funcp) P((const time_t *, long, struct tm *)); const long offset; { register time_t t;