This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PING [gfortran] Fix date_and_time intrinsic procedure


On Mon, Jan 24, 2005 at 11:15:45AM -0800, Steve Kargl wrote:
> The attached patch fixes the date_and_time procedure for
> two case.
> 
> (1) If a clock is not available the standard requires that
>     date_and_time() return -HUGE(0) for all elements in
>     VALUES(1:8).   We currently return HUGE(0).
> 
> (2) If a clock is available, but it lacks millisecond
>     (or better) resolution we were setting VALUE(8) to
>     HUGE(0).  All other VALUES() are correctly, set so
>     we are return 2**31 milliseconds, which is out of
>     range.  A much better choice is 0.
> 
> 2005-01-24  Steven G. Kargl  <kargls@comcast.net>
> 
>       *  intrinsic/date_and_time.c: Fix conformance problems.
> 
> -- 
> Steve

> Index: date_and_time.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/libgfortran/intrinsics/date_and_time.c,v
> retrieving revision 1.5
> diff -u -r1.5 date_and_time.c
> --- date_and_time.c	12 Jan 2005 21:27:30 -0000	1.5
> +++ date_and_time.c	24 Jan 2005 18:48:27 -0000
> @@ -1,5 +1,5 @@
>  /* Implementation of the DATE_AND_TIME intrinsic.
> -   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
> +   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
>     Contributed by Steven Bosscher.
>  
>  This file is part of the GNU Fortran 95 runtime library (libgfortran).
> @@ -67,7 +67,7 @@
>  
>     DATE (optional) shall be scalar and of type default character, and
>     shall be of length at least 8 in order to contain the complete
> -   value. It is an INTENT (OUT) argument. Its leftmost 8 characters
> +   value. It is an INTENT(OUT) argument. Its leftmost 8 characters
>     are assigned a value of the form CCYYMMDD, where CC is the century,
>     YY the year within the century, MM the month within the year, and
>     DD the day within the month. If there is no date available, they
> @@ -75,7 +75,7 @@
>  
>     TIME (optional) shall be scalar and of type default character, and
>     shall be of length at least 10 in order to contain the complete
> -   value. It is an INTENT (OUT) argument. Its leftmost 10 characters
> +   value. It is an INTENT(OUT) argument. Its leftmost 10 characters
>     are assigned a value of the form hhmmss.sss, where hh is the hour
>     of the day, mm is the minutes of the hour, and ss.sss is the
>     seconds and milliseconds of the minute. If there is no clock
> @@ -83,40 +83,40 @@
>  
>     ZONE (optional) shall be scalar and of type default character, and
>     shall be of length at least 5 in order to contain the complete
> -   value. It is an INTENT (OUT) argument. Its leftmost 5 characters
> -   are assigned a value of the form ±hhmm, where hh and mm are the
> +   value. It is an INTENT(OUT) argument. Its leftmost 5 characters
> +   are assigned a value of the form ±hhmm, where hh and mm are the
>     time difference with respect to Coordinated Universal Time (UTC) in
>     hours and parts of an hour expressed in minutes, respectively. If
>     there is no clock available, they are assigned blanks.
>  
>     VALUES (optional) shall be of type default integer and of rank
> -   one. It is an INTENT (OUT) argument. Its size shall be at least
> +   one. It is an INTENT(OUT) argument. Its size shall be at least
>     8. The values returned in VALUES are as follows:
>  
> -      VALUES (1) the year (for example, 2003), or HUGE (0) if there is
> +      VALUES(1) the year (for example, 2003), or -HUGE(0) if there is
>        no date available;
>  
> -      VALUES (2) the month of the year, or HUGE (0) if there
> +      VALUES(2) the month of the year, or -HUGE(0) if there
>        is no date available;
>  
> -      VALUES (3) the day of the month, or HUGE (0) if there is no date
> +      VALUES(3) the day of the month, or -HUGE(0) if there is no date
>        available;
>  
> -      VALUES (4) the time difference with respect to Coordinated
> -      Universal Time (UTC) in minutes, or HUGE (0) if this information
> +      VALUES(4) the time difference with respect to Coordinated
> +      Universal Time (UTC) in minutes, or -HUGE(0) if this information
>        is not available;
>  
> -      VALUES (5) the hour of the day, in the range of 0 to 23, or HUGE
> -      (0) if there is no clock;
> +      VALUES(5) the hour of the day, in the range of 0 to 23, or
> +      -HUGE(0) if there is no clock;
>  
> -      VALUES (6) the minutes of the hour, in the range 0 to 59, or
> -      HUGE (0) if there is no clock;
> +      VALUES(6) the minutes of the hour, in the range 0 to 59, or
> +      -HUGE(0) if there is no clock;
>  
> -      VALUES (7) the seconds of the minute, in the range 0 to 60, or
> -      HUGE (0) if there is no clock;
> +      VALUES(7) the seconds of the minute, in the range 0 to 60, or
> +      -HUGE(0) if there is no clock;
>  
> -      VALUES (8) the milliseconds of the second, in the range 0 to
> -      999, or HUGE (0) if there is no clock.
> +      VALUES(8) the milliseconds of the second, in the range 0 to
> +      999, or -HUGE(0) if there is no clock.
>  
>     NULL pointer represent missing OPTIONAL arguments.  All arguments
>     have INTENT(OUT).  Because of the -i8 option, we must implement
> @@ -129,125 +129,131 @@
>     - There is no STDC/POSIX way to get VALUES(8).  A GNUish way may
>       be to use ftime.
>  */
> +#define DATE_LEN 8
> +#define TIME_LEN 10   
> +#define ZONE_LEN 5
> +#define VALUES_SIZE 8
>  
>  extern void date_and_time (char *, char *, char *, gfc_array_i4 *,
>  			   GFC_INTEGER_4, GFC_INTEGER_4, GFC_INTEGER_4);
>  export_proto(date_and_time);
>  
>  void
> -date_and_time (char *__date,
> -	       char *__time,
> -	       char *__zone,
> -	       gfc_array_i4 *__values,
> -	       GFC_INTEGER_4 __date_len,
> -	       GFC_INTEGER_4 __time_len,
> -	       GFC_INTEGER_4 __zone_len)
> +date_and_time (char *__date, char *__time, char *__zone,
> +	       gfc_array_i4 *__values, GFC_INTEGER_4 __date_len,
> +	       GFC_INTEGER_4 __time_len, GFC_INTEGER_4 __zone_len)
>  {
> -#define DATE_LEN 8
> -#define TIME_LEN 10   
> -#define ZONE_LEN 5
> -#define VALUES_SIZE 8
> +  int i;
>    char date[DATE_LEN + 1];
>    char timec[TIME_LEN + 1];
>    char zone[ZONE_LEN + 1];
>    GFC_INTEGER_4 values[VALUES_SIZE];
>  
>  #ifndef HAVE_NO_DATE_TIME
> -  time_t lt = time (NULL);
> -  struct tm local_time = *localtime (&lt);
> -  struct tm UTC_time = *gmtime (&lt);
> -
> -  /* All arguments can be derived from VALUES.  */
> -  values[0] = 1900 + local_time.tm_year;
> -  values[1] = 1 + local_time.tm_mon;
> -  values[2] = local_time.tm_mday;
> -  values[3] = (local_time.tm_min - UTC_time.tm_min +
> -	       60 * (local_time.tm_hour - UTC_time.tm_hour +
> +  time_t lt;
> +  struct tm local_time;
> +  struct tm UTC_time;
> +
> +  lt = time (NULL);
> +
> +  if (lt != (time_t) -1)
> +    {
> +      local_time = *localtime (&lt);
> +      UTC_time = *gmtime (&lt);
> +
> +      /* All arguments can be derived from VALUES.  */
> +      values[0] = 1900 + local_time.tm_year;
> +      values[1] = 1 + local_time.tm_mon;
> +      values[2] = local_time.tm_mday;
> +      values[3] = (local_time.tm_min - UTC_time.tm_min +
> +	           60 * (local_time.tm_hour - UTC_time.tm_hour +
>  		     24 * (local_time.tm_yday - UTC_time.tm_yday)));
> -  values[4] = local_time.tm_hour;
> -  values[5] = local_time.tm_min;
> -  values[6] = local_time.tm_sec;
> +      values[4] = local_time.tm_hour;
> +      values[5] = local_time.tm_min;
> +      values[6] = local_time.tm_sec;
> +      values[7] = 0;
> +
>  #if HAVE_GETTIMEOFDAY
> -    {
> -      struct timeval tp;
> +      {
> +	struct timeval tp;
>  #  if GETTIMEOFDAY_ONE_ARGUMENT
> -      if (!gettimeofday (&tp))
> +	if (!gettimeofday (&tp))
>  #  else
>  #    if HAVE_STRUCT_TIMEZONE
> -      struct timezone tzp;
> +	struct timezone tzp;
>  
>        /* Some systems such as HP-UX, do have struct timezone, but
>  	 gettimeofday takes void* as the 2nd arg.  However, the
>  	 effect of passing anything other than a null pointer is
> -	 unspecified on HPUX.  Configure checks if gettimeofday
> +	 unspecified on HP-UX.  Configure checks if gettimeofday
>  	 actually fails with a non-NULL arg and pretends that
>  	 struct timezone is missing if it does fail.  */
> -      if (!gettimeofday (&tp, &tzp))
> +	if (!gettimeofday (&tp, &tzp))
>  #    else
> -      if (!gettimeofday (&tp, (void *) 0))
> +	if (!gettimeofday (&tp, (void *) 0))
>  #    endif /* HAVE_STRUCT_TIMEZONE  */
>  #  endif /* GETTIMEOFDAY_ONE_ARGUMENT  */
>  	values[7] = tp.tv_usec / 1000;
> -    }
> -#else
> -   values[7] = GFC_INTEGER_4_HUGE;
> +      }
>  #endif /* HAVE_GETTIMEOFDAY */
>  
> -  if (__date)
> -    {
> -#if HAVE_SNPRINTF
> -      snprintf (date, DATE_LEN + 1, "%04d%02d%02d",
> -		values[0], values[1], values[2]);
> -#else
> -      sprintf (date, "%04d%02d%02d",
> -	       values[0], values[1], values[2]);
> -#endif
> -    }
> -
> -  if (__time)
> -    {
>  #if HAVE_SNPRINTF
> -      snprintf (timec, TIME_LEN + 1, "%02d%02d%02d.%03d",
> -		values[4], values[5], values[6], values[7]);
> +      if (__date)
> +	snprintf (date, DATE_LEN + 1, "%04d%02d%02d",
> +		  values[0], values[1], values[2]);
> +      if (__time)
> +	snprintf (timec, TIME_LEN + 1, "%02d%02d%02d.%03d",
> +		  values[4], values[5], values[6], values[7]);
> +
> +      if (__zone)
> +	snprintf (zone, ZONE_LEN + 1, "%+03d%02d",
> +		  values[3] / 60, abs (values[3] % 60));
>  #else
> -      sprintf (timec, "%02d%02d%02d.%03d",
> -	       values[4], values[5], values[6], values[7]);
> -#endif
> -    }
> +      if (__date)
> +	sprintf (date, "%04d%02d%02d", values[0], values[1], values[2]);
>  
> -  if (__zone)
> -    {
> -#if HAVE_SNPRINTF
> -      snprintf (zone, ZONE_LEN + 1, "%+03d%02d",
> -		values[3] / 60, abs (values[3] % 60));
> -#else
> -      sprintf (zone, "%+03d%02d",
> -	       values[3] / 60, abs (values[3] % 60));
> +      if (__time)
> +	sprintf (timec, "%02d%02d%02d.%03d",
> +		 values[4], values[5], values[6], values[7]);
> +
> +      if (__zone)
> +	sprintf (zone, "%+03d%02d",
> +		 values[3] / 60, abs (values[3] % 60));
>  #endif
>      }
> -#else /* if defined HAVE_NO_DATE_TIME  */
> -  /* We really have *nothing* to return, so return blanks and HUGE(0).  */
> +  else
>      {
> -      int i;
> -
>        memset (date, ' ', DATE_LEN);
>        date[DATE_LEN] = '\0';
>  
>        memset (timec, ' ', TIME_LEN);
> -      time[TIME_LEN] = '\0';
> +      timec[TIME_LEN] = '\0';
>  
>        memset (zone, ' ', ZONE_LEN);
>        zone[ZONE_LEN] = '\0';
>  
>        for (i = 0; i < VALUES_SIZE; i++)
> -        values[i] = GFC_INTEGER_4_HUGE;
> -    }
> +	values[i] = - GFC_INTEGER_4_HUGE;
> +    }   
> +#else /* if defined HAVE_NO_DATE_TIME  */
> +  /* We really have *nothing* to return, so return blanks and HUGE(0).  */
> +      
> +  memset (date, ' ', DATE_LEN);
> +  date[DATE_LEN] = '\0';
> +
> +  memset (timec, ' ', TIME_LEN);
> +  timec[TIME_LEN] = '\0';
> +
> +  memset (zone, ' ', ZONE_LEN);
> +  zone[ZONE_LEN] = '\0';
> +
> +  for (i = 0; i < VALUES_SIZE; i++)
> +    values[i] = - GFC_INTEGER_4_HUGE;
>  #endif  /* HAVE_NO_DATE_TIME  */
>  
>    /* Copy the values into the arguments.  */
>    if (__values)
>      {
> -      int i;
>        size_t len, delta, elt_size;
>  
>        elt_size = GFC_DESCRIPTOR_SIZE (__values);
> @@ -263,9 +269,7 @@
>  	  GFC_INTEGER_4 *vptr4 = __values->data;
>  
>  	  for (i = 0; i < VALUES_SIZE; i++, vptr4 += delta)
> -	    {
> -	      *vptr4 = values[i];
> -	    }
> +	    *vptr4 = values[i];
>  	}
>        else if (elt_size == 8)
>          {
> @@ -273,8 +277,8 @@
>  
>  	  for (i = 0; i < VALUES_SIZE; i++, vptr8 += delta)
>  	    {
> -	      if (values[i] == GFC_INTEGER_4_HUGE)
> -		*vptr8 = GFC_INTEGER_8_HUGE;
> +	      if (values[i] == - GFC_INTEGER_4_HUGE)
> +		*vptr8 = - GFC_INTEGER_8_HUGE;
>  	      else
>  		*vptr8 = values[i];
>  	    }
> @@ -300,8 +304,4 @@
>        assert (__date_len >= DATE_LEN);
>        fstrcpy (__date, DATE_LEN, date, DATE_LEN);
>      }
> -#undef DATE_LEN
> -#undef TIME_LEN   
> -#undef ZONE_LEN
> -#undef VALUES_SIZE
>  }


-- 
Steve


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]