]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR 61310 Rewrite implementation of CTIME and FDATE intrinsics.
authorJanne Blomqvist <jb@gcc.gnu.org>
Mon, 26 May 2014 19:44:24 +0000 (22:44 +0300)
committerJanne Blomqvist <jb@gcc.gnu.org>
Mon, 26 May 2014 19:44:24 +0000 (22:44 +0300)
2014-05-26  Janne Blomqvist  <jb@gcc.gnu.org>

Backport from mainline
PR libfortran/61310
* intrinsics.texi (CTIME): Remove mention of locale-dependent
behavior.

2014-05-26  Janne Blomqvist  <jb@gcc.gnu.org>

Backport from mainline
PR libfortran/61310
* intrinsics/ctime.c (strctime): Rename to gf_ctime, use snprintf
instead of strftime.
(fdate): Use gf_ctime.
(fdate_sub): Likewise.
(ctime): Likewise.
(ctime_sub): Likewise.

From-SVN: r210947

gcc/fortran/ChangeLog
gcc/fortran/intrinsic.texi
libgfortran/ChangeLog
libgfortran/intrinsics/ctime.c

index 6694c59553346d80cdf2f5bdb09adca42c2c06c9..a66d0c9aad95b4daa6b1936e8568ed854beaedf1 100644 (file)
@@ -1,3 +1,10 @@
+2014-05-26  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       Backport from mainline
+       PR libfortran/61310
+       * intrinsics.texi (CTIME): Remove mention of locale-dependent
+       behavior.
+
 2014-05-24  Dominique d'Humieres <dominiq@lps.ens.fr>
 
        Backport r195492 and r195815
index d0a29cc25ea4b72769dd260aefd889a1422f82f1..327bce74305238c2174b68d5c274f19716e42fd9 100644 (file)
@@ -3314,10 +3314,8 @@ end program test_cshift
 @table @asis
 @item @emph{Description}:
 @code{CTIME} converts a system time value, such as returned by
-@code{TIME8}, to a string. Unless the application has called
-@code{setlocale}, the output will be in the default locale, of length
-24 and of the form @samp{Sat Aug 19 18:13:14 1995}. In other locales,
-a longer string may result.
+@code{TIME8}, to a string. The output will be of the form @samp{Sat
+Aug 19 18:13:14 1995}.
 
 This intrinsic is provided in both subroutine and function forms; however,
 only one form can be used in any given program unit.
index 75805d2bbcf4f31b2f2942b47429259afb8a18bd..f013b298614cf74ad848ee1330853b78a185d0af 100644 (file)
@@ -1,3 +1,14 @@
+2014-05-26  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       Backport from mainline
+       PR libfortran/61310
+       * intrinsics/ctime.c (strctime): Rename to gf_ctime, use snprintf
+       instead of strftime.
+       (fdate): Use gf_ctime.
+       (fdate_sub): Likewise.
+       (ctime): Likewise.
+       (ctime_sub): Likewise.
+
 2014-05-16  Janne Blomqvist  <jb@gcc.gnu.org>
 
        Backport from trunk:
index 05bf31fc779d77859646400a3e63ea23348aac4e..86e8e565cb4748244f1d9ab742e2fe834234df54 100644 (file)
@@ -1,5 +1,5 @@
 /* Implementation of the CTIME and FDATE g77 intrinsics.
-   Copyright (C) 2005, 2007, 2009, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2005-2013 Free Software Foundation, Inc.
    Contributed by François-Xavier Coudert <coudert@clipper.ens.fr>
 
 This file is part of the GNU Fortran runtime library (libgfortran).
@@ -31,31 +31,53 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include <string.h>
 
 
-/* strftime-like function that fills a C string with %c format which
-   is identical to ctime in the default locale. As ctime and ctime_r
-   are poorly specified and their usage not recommended, the
-   implementation instead uses strftime.  */
+/* Maximum space a ctime-like string might need. A "normal" ctime
+   string is 26 bytes, and in our case 24 bytes as we don't include
+   the trailing newline and null. However, the longest possible year
+   number is -2,147,481,748 (1900 - 2,147,483,648, since tm_year is a
+   32-bit signed integer) so an extra 7 bytes are needed. */
+#define CTIME_BUFSZ 31
 
-static size_t
-strctime (char *s, size_t max, const time_t *timep)
+
+/* Thread-safe ctime-like function that fills a Fortran
+   string. ctime_r is a portability headache and marked as obsolescent
+   in POSIX 2008, which recommends strftime in its place. However,
+   strftime(..., "%c",...)  doesn't produce ctime-like output on
+   MinGW, so do it manually with snprintf.  */
+
+static int
+gf_ctime (char *s, size_t max, const time_t timev)
 {
   struct tm ltm;
   int failed;
+  char buf[CTIME_BUFSZ + 1];
   /* Some targets provide a localtime_r based on a draft of the POSIX
      standard where the return type is int rather than the
      standardized struct tm*.  */
-  __builtin_choose_expr (__builtin_classify_type (localtime_r (timep, &ltm)) 
+  __builtin_choose_expr (__builtin_classify_type (localtime_r (&timev, &ltm)) 
                         == 5,
-                        failed = localtime_r (timep, &ltm) == NULL,
-                        failed = localtime_r (timep, &ltm) != 0);
+                        failed = localtime_r (&timev, &ltm) == NULL,
+                        failed = localtime_r (&timev, &ltm) != 0);
   if (failed)
-    return 0;
-  return strftime (s, max, "%c", &ltm);
+    goto blank;
+  int n = snprintf (buf, sizeof (buf), 
+                   "%3.3s %3.3s%3d %.2d:%.2d:%.2d %d",
+                   "SunMonTueWedThuFriSat" + ltm.tm_wday * 3,
+                   "JanFebMarAprMayJunJulAugSepOctNovDec" + ltm.tm_mon * 3,
+                   ltm.tm_mday, ltm.tm_hour, ltm.tm_min, ltm.tm_sec, 
+                   1900 + ltm.tm_year);
+  if (n < 0)
+    goto blank;
+  if ((size_t) n <= max)
+    {
+      cf_strcpy (s, max, buf);
+      return n;
+    }
+ blank:
+  memset (s, ' ', max);
+  return 0;
 }
 
-/* In the default locale, the date and time representation fits in 26
-   bytes. However, other locales might need more space.  */
-#define CSZ 100
 
 extern void fdate (char **, gfc_charlen_type *);
 export_proto(fdate);
@@ -64,8 +86,8 @@ void
 fdate (char ** date, gfc_charlen_type * date_len)
 {
   time_t now = time(NULL);
-  *date = get_mem (CSZ);
-  *date_len = strctime (*date, CSZ, &now);
+  *date = get_mem (CTIME_BUFSZ);
+  *date_len = gf_ctime (*date, CTIME_BUFSZ, now);
 }
 
 
@@ -76,10 +98,7 @@ void
 fdate_sub (char * date, gfc_charlen_type date_len)
 {
   time_t now = time(NULL);
-  char *s = get_mem (date_len + 1);
-  size_t n = strctime (s, date_len + 1, &now);
-  fstrcpy (date, date_len, s, n);
-  free (s);
+  gf_ctime (date, date_len, now);
 }
 
 
@@ -91,8 +110,8 @@ void
 PREFIX(ctime) (char ** date, gfc_charlen_type * date_len, GFC_INTEGER_8 t)
 {
   time_t now = t;
-  *date = get_mem (CSZ);
-  *date_len = strctime (*date, CSZ, &now);
+  *date = get_mem (CTIME_BUFSZ);
+  *date_len = gf_ctime (*date, CTIME_BUFSZ, now);
 }
 
 
@@ -103,8 +122,5 @@ void
 ctime_sub (GFC_INTEGER_8 * t, char * date, gfc_charlen_type date_len)
 {
   time_t now = *t;
-  char *s = get_mem (date_len + 1);
-  size_t n = strctime (s, date_len + 1, &now);
-  fstrcpy (date, date_len, s, n);
-  free (s);
+  gf_ctime (date, date_len, now);
 }