From 76118dd9a35eb1516aee287d3aaa8f3824a712fb Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Mon, 29 Sep 2014 15:39:19 -0400 Subject: Better way to avoid glibc dependency. Returns us to something amost identical to the original code. Sigh. Timezones are a swamp. All regression tests pass. --- driver_garmin_txt.c | 2 +- driver_oncore.c | 2 +- driver_sirf.c | 6 +++--- driver_superstar2.c | 4 ++-- driver_zodiac.c | 2 +- gps.h | 1 + gpsutils.c | 30 ++++++++++++++++++++++++++++++ timebase.c | 2 +- 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/driver_garmin_txt.c b/driver_garmin_txt.c index ad69578c..5d249909 100644 --- a/driver_garmin_txt.c +++ b/driver_garmin_txt.c @@ -322,7 +322,7 @@ gps_mask_t garmintxt_parse(struct gps_device_t * session) session->driver.garmintxt.date.tm_sec = (int)result; session->driver.garmintxt.subseconds = 0; session->newdata.time = - (timestamp_t)timegm(&session->driver.garmintxt.date) + + (timestamp_t)mkgmtime(&session->driver.garmintxt.date) + session->driver.garmintxt.subseconds; mask |= TIME_SET; } while (0); diff --git a/driver_oncore.c b/driver_oncore.c index a0a53fe4..9a2808a5 100644 --- a/driver_oncore.c +++ b/driver_oncore.c @@ -111,7 +111,7 @@ oncore_msg_navsol(struct gps_device_t *session, unsigned char *buf, nsec = (uint) getbeu32(buf, 11); /*@ -unrecog */ - session->newdata.time = (timestamp_t)timegm(&unpacked_date) + nsec * 1e-9; + session->newdata.time = (timestamp_t)mkgmtime(&unpacked_date) + nsec * 1e-9; /*@ +unrecog */ mask |= TIME_SET; gpsd_report(&session->context->errout, LOG_DATA, diff --git a/driver_sirf.c b/driver_sirf.c index cd81b8a4..a893ef51 100644 --- a/driver_sirf.c +++ b/driver_sirf.c @@ -887,7 +887,7 @@ static gps_mask_t sirf_msg_geodetic(struct gps_device_t *session, unpacked_date.tm_sec = 0; subseconds = getbeu16(buf, 17) * 1e-3; /*@ -compdef -unrecog */ - session->newdata.time = (timestamp_t)timegm(&unpacked_date) + subseconds; + session->newdata.time = (timestamp_t)mkgmtime(&unpacked_date) + subseconds; /*@ +compdef +unrecog */ gpsd_report(&session->context->errout, LOG_PROG, "SiRF: GND 0x29 UTC: %lf\n", @@ -1016,7 +1016,7 @@ static gps_mask_t sirf_msg_ublox(struct gps_device_t *session, unpacked_date.tm_sec = 0; subseconds = ((unsigned short)getbeu16(buf, 32)) * 1e-3; /*@ -compdef */ - session->newdata.time = (timestamp_t)timegm(&unpacked_date) + subseconds; + session->newdata.time = (timestamp_t)mkgmtime(&unpacked_date) + subseconds; /*@ +compdef */ #ifdef TIMEHINT_ENABLE if (0 == (session->driver.sirf.time_seen & TIME_SEEN_UTC_2)) { @@ -1069,7 +1069,7 @@ static gps_mask_t sirf_msg_ppstime(struct gps_device_t *session, unpacked_date.tm_mon = (int)getub(buf, 5) - 1; unpacked_date.tm_year = (int)getbeu16(buf, 6) - 1900; /*@ -compdef */ - session->newdata.time = (timestamp_t)timegm(&unpacked_date); + session->newdata.time = (timestamp_t)mkgmtime(&unpacked_date); /*@ +compdef */ session->context->leap_seconds = (int)getbeu16(buf, 8); session->context->valid |= LEAP_SECOND_VALID; diff --git a/driver_superstar2.c b/driver_superstar2.c index c5893afc..743d2133 100644 --- a/driver_superstar2.c +++ b/driver_superstar2.c @@ -99,7 +99,7 @@ superstar2_msg_navsol_lla(struct gps_device_t *session, tm.tm_mday = (int)getub(buf, 14); tm.tm_mon = (int)getub(buf, 15) - 1; tm.tm_year = (int)getleu16(buf, 16) - 1900; - session->newdata.time = (timestamp_t)timegm(&tm) + (d - tm.tm_sec); + session->newdata.time = (timestamp_t)mkgmtime(&tm) + (d - tm.tm_sec); mask |= TIME_SET | PPSTIME_IS; /* extract the local tangential plane (ENU) solution */ @@ -269,7 +269,7 @@ superstar2_msg_timing(struct gps_device_t *session, unsigned char *buf, tm.tm_min = (int)getsb(buf, 42); d = getled64((char *)buf, 43); tm.tm_sec = (int)d; - session->newdata.time = (timestamp_t)timegm(&tm); + session->newdata.time = (timestamp_t)mkgmtime(&tm); session->context->leap_seconds = (int)getsb(buf, 20); mask = TIME_SET | PPSTIME_IS; } diff --git a/driver_zodiac.c b/driver_zodiac.c index c961a963..6ff24efe 100644 --- a/driver_zodiac.c +++ b/driver_zodiac.c @@ -167,7 +167,7 @@ static gps_mask_t handle1000(struct gps_device_t *session) unpacked_date.tm_sec = (int)getzword(24); subseconds = (int)getzlong(25) / 1e9; /*@ -compdef */ - session->newdata.time = (timestamp_t)timegm(&unpacked_date) + subseconds; + session->newdata.time = (timestamp_t)mkgmtime(&unpacked_date) + subseconds; /*@ +compdef */ /*@ -type @*/ session->newdata.latitude = ((long)getzlong(27)) * RAD_2_DEG * 1e-8; diff --git a/gps.h b/gps.h index 29e0d291..16955bc3 100644 --- a/gps.h +++ b/gps.h @@ -2052,6 +2052,7 @@ extern void gps_enable_debug(int, FILE *); extern /*@observer@*/const char *gps_maskdump(gps_mask_t); extern double safe_atof(const char *); +extern time_t mkgmtime(register struct tm *); extern timestamp_t timestamp(void); extern timestamp_t iso8601_to_unix(char *); extern /*@observer@*/char *unix_to_iso8601(timestamp_t t, /*@ out @*/char[], size_t len); diff --git a/gpsutils.c b/gpsutils.c index 6b72776f..b02975fe 100644 --- a/gpsutils.c +++ b/gpsutils.c @@ -308,6 +308,36 @@ timestamp_t timestamp(void) #endif } +time_t mkgmtime(register struct tm * t) +/* struct tm to seconds since Unix epoch */ +{ + register int year; + register time_t result; + static const int cumdays[MONTHSPERYEAR] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + + /*@ +matchanyintegral @*/ + year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR; + result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR]; + result += (year - 1968) / 4; + result -= (year - 1900) / 100; + result += (year - 1600) / 400; + if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) && + (t->tm_mon % MONTHSPERYEAR) < 2) + result--; + result += t->tm_mday - 1; + result *= 24; + result += t->tm_hour; + result *= 60; + result += t->tm_min; + result *= 60; + result += t->tm_sec; + if (t->tm_isdst == 1) + result -= 3600; + /*@ -matchanyintegral @*/ + return (result); +} + timestamp_t iso8601_to_unix( /*@in@*/ char *isotime) /* ISO8601 UTC to Unix UTC */ { diff --git a/timebase.c b/timebase.c index 2aff11cc..7c790c06 100644 --- a/timebase.c +++ b/timebase.c @@ -272,7 +272,7 @@ timestamp_t gpsd_utc_resolve(/*@in@*/struct gps_device_t *session) */ timestamp_t t; - t = (timestamp_t)timegm(&session->nmea.date) + + t = (timestamp_t)mkgmtime(&session->nmea.date) + session->nmea.subseconds; session->context->valid &=~ GPS_TIME_VALID; -- cgit v1.2.1