Code

do not mess with dst status after running localtime, the system gets confused otherwh...
[rrdtool-all.git] / program / src / parsetime.c
index e5a297c979f8f4fa4c1d6bfdb1401f1828180dc8..74063b200a876aa4a44e797d55ca0ac09a5c8261 100644 (file)
@@ -234,25 +234,24 @@ static struct SpecialToken TimeMultipliers[] = {
  */
 static struct SpecialToken *Specials;
 
-static char **scp;     /* scanner - pointer at arglist */
+static const char **scp;       /* scanner - pointer at arglist */
 static char scc;       /* scanner - count of remaining arguments */
-static char *sct;      /* scanner - next char pointer in current argument */
+static const char *sct;        /* scanner - next char pointer in current argument */
 static int need;       /* scanner - need to advance to next argument */
 
 static char *sc_token=NULL;    /* scanner - token buffer */
 static size_t sc_len;   /* scanner - length of token buffer */
 static int sc_tokid;   /* scanner - token id */
 
-static int need_to_free = 0; /* means that we need deallocating memory */
-
 /* Local functions */
+static void EnsureMemFree (void);
 
-void EnsureMemFree ()
+static void EnsureMemFree (void)
 {
-  if( need_to_free )
+  if( sc_token )
     {
     free(sc_token);
-    need_to_free = 0;
+    sc_token = NULL;
     }
 }
 
@@ -368,7 +367,7 @@ parse_token(char *arg)
  * init_scanner() sets up the scanner to eat arguments
  */
 static char *
-init_scanner(int argc, char **argv)
+init_scanner(int argc, const char **argv)
 {
     scp = argv;
     scc = argc;
@@ -380,7 +379,6 @@ init_scanner(int argc, char **argv)
     sc_token = (char *) malloc(sc_len*sizeof(char));
     if( sc_token == NULL )
       return "Failed to allocate memory";
-    need_to_free = 1;
     return TIME_OK;
 } /* init_scanner */
 
@@ -561,7 +559,7 @@ tod(struct rrd_time_value *ptv)
     int tlen;
     /* save token status in  case we must abort */
     int scc_sv = scc; 
-    char *sct_sv = sct; 
+    const char *sct_sv = sct; 
     int sc_tokid_sv = sc_tokid;
 
     tlen = strlen(sc_token);
@@ -661,7 +659,8 @@ assign_date(struct rrd_time_value *ptv, long mday, long mon, long year)
 static char *
 day(struct rrd_time_value *ptv)
 {
-    long mday=0, wday, mon, year = ptv->tm.tm_year;
+    /* using time_t seems to help portability with 64bit oses */    
+    time_t mday=0, wday, mon, year = ptv->tm.tm_year;
     int tlen;
 
     switch (sc_tokid) {
@@ -722,7 +721,7 @@ day(struct rrd_time_value *ptv)
                break;
            }
 
-           if (mon > 19700101 && mon < 24000101){ /*works between 1900 and 2400 */
+           if (mon > 19700101 && mon < 24000101){ /*works between 1970 and 2400 */
                char  cmon[3],cmday[3],cyear[5];
                strncpy(cyear,sc_token,4);cyear[4]='\0';              
                year = atol(cyear);           
@@ -785,7 +784,7 @@ day(struct rrd_time_value *ptv)
  * the pointer to the error message in the case of problems
  */
 char *
-parsetime(char *tspec, struct rrd_time_value *ptv)
+parsetime(const char *tspec, struct rrd_time_value *ptv)
 {
     time_t now = time(NULL);
     int hr = 0;
@@ -799,7 +798,8 @@ parsetime(char *tspec, struct rrd_time_value *ptv)
     ptv->type = ABSOLUTE_TIME;
     ptv->offset = 0;
     ptv->tm = *localtime(&now);
-    ptv->tm.tm_isdst = -1; /* mk time can figure this out for us ... */
+    ptv->tm.tm_isdst = -1; /* by default lets mk time guess dst status ... */
+
 
     token();
     switch (sc_tokid) {
@@ -838,8 +838,23 @@ parsetime(char *tspec, struct rrd_time_value *ptv)
 
     /* Only absolute time specifications below */
     case NUMBER:
-           try(tod(ptv))
-            try(day(ptv))
+           {
+             long hour_sv = ptv->tm.tm_hour;
+             long year_sv = ptv->tm.tm_year;
+              ptv->tm.tm_hour = 30;
+              ptv->tm.tm_year = 30000;
+             try(tod(ptv))
+             try(day(ptv))
+             if ( ptv->tm.tm_hour == 30 &&  ptv->tm.tm_year != 30000 ){
+               try(tod(ptv))
+              }
+             if ( ptv->tm.tm_hour == 30 ){
+               ptv->tm.tm_hour = hour_sv;
+              }
+             if ( ptv->tm.tm_year == 30000 ){
+               ptv->tm.tm_year = year_sv;
+              }
+           };      
             break;
     /* fix month parsing */
     case JAN: case FEB: case MAR: case APR: case MAY: case JUN:
@@ -901,7 +916,6 @@ parsetime(char *tspec, struct rrd_time_value *ptv)
       panic(e("unparsable trailing text: '...%s%s'", sc_token, sct));
     }
 
-    ptv->tm.tm_isdst = -1; /* for mktime to guess DST status */
     if( ptv->type == ABSOLUTE_TIME )
       if( mktime( &ptv->tm ) == -1 ) { /* normalize & check */
         /* can happen for "nonexistent" times, e.g. around 3am */