public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-3006] PR modula2/110779 SysClock can not read the clock
@ 2023-08-05 16:39 Gaius Mulley
  0 siblings, 0 replies; only message in thread
From: Gaius Mulley @ 2023-08-05 16:39 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:0826ebd633e38bd55abd161c15deb431420f82a3

commit r14-3006-g0826ebd633e38bd55abd161c15deb431420f82a3
Author: Gaius Mulley <gaiusmod2@gmail.com>
Date:   Sat Aug 5 17:35:12 2023 +0100

    PR modula2/110779 SysClock can not read the clock
    
    This patch completes the implementation of the ISO module
    SysClock.mod.  Three new testcases are provided.  wrapclock.{cc,def}
    are new support files providing access to clock_settime, clock_gettime
    and glibc timezone variables.
    
    gcc/m2/ChangeLog:
    
            PR modula2/110779
            * gm2-libs-iso/SysClock.mod: Re-implement using wrapclock.
            * gm2-libs-iso/wrapclock.def: New file.
    
    libgm2/ChangeLog:
    
            PR modula2/110779
            * config.h.in: Regenerate.
            * configure: Regenerate.
            * configure.ac (GM2_CHECK_LIB): Check for clock_gettime
            and clock_settime.
            * libm2iso/Makefile.am (M2DEFS): Add wrapclock.def.
            * libm2iso/Makefile.in: Regenerate.
            * libm2iso/wraptime.cc: Replace HAVE_TIMEVAL with
            HAVE_STRUCT_TIMEVAL.
            * libm2iso/wrapclock.cc: New file.
    
    gcc/testsuite/ChangeLog:
    
            PR modula2/110779
            * gm2/iso/run/pass/m2date.mod: New test.
            * gm2/iso/run/pass/testclock.mod: New test.
            * gm2/iso/run/pass/testclock2.mod: New test.
    
    Signed-off-by: Gaius Mulley <gaiusmod2@gmail.com>

Diff:
---
 gcc/m2/gm2-libs-iso/SysClock.mod              | 256 ++++++++++++++++----------
 gcc/m2/gm2-libs-iso/wrapclock.def             | 125 +++++++++++++
 gcc/testsuite/gm2/iso/run/pass/m2date.mod     | 101 ++++++++++
 gcc/testsuite/gm2/iso/run/pass/testclock.mod  |  15 ++
 gcc/testsuite/gm2/iso/run/pass/testclock2.mod |  22 +++
 libgm2/config.h.in                            |   9 +
 libgm2/configure                              | 147 +++++++++++++++
 libgm2/configure.ac                           |   4 +-
 libgm2/libm2iso/Makefile.am                   |   6 +-
 libgm2/libm2iso/Makefile.in                   |  11 +-
 libgm2/libm2iso/wrapclock.cc                  | 220 ++++++++++++++++++++++
 libgm2/libm2iso/wraptime.cc                   |   9 +-
 12 files changed, 812 insertions(+), 113 deletions(-)

diff --git a/gcc/m2/gm2-libs-iso/SysClock.mod b/gcc/m2/gm2-libs-iso/SysClock.mod
index e89448927e2..60261f2fd74 100644
--- a/gcc/m2/gm2-libs-iso/SysClock.mod
+++ b/gcc/m2/gm2-libs-iso/SysClock.mod
@@ -26,17 +26,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 IMPLEMENTATION MODULE SysClock ;
 
-FROM wraptime IMPORT timeval, timezone, tm,
-                     InitTimezone, InitTimeval,
-                     InitTM, KillTM,
-                     gettimeofday, settimeofday, GetFractions,
-                     localtime_r, GetSummerTime, GetDST,
-                     KillTimezone, KillTimeval, GetYear,
-                     GetMonth, GetDay, GetHour, GetMinute,
-                     GetSecond, SetTimeval, SetTimezone ;
+FROM wrapclock IMPORT timespec, timezone, isdst, InitTimespec, KillTimespec,
+                      GetTimespec, SetTimespec, GetTimeRealtime, SetTimeRealtime ;
+
+FROM libc IMPORT printf ;
 
 IMPORT Args ;
 
+CONST
+   Debugging = FALSE ;
+
 VAR
    canget,
    canset,
@@ -50,25 +49,23 @@ VAR
 
 PROCEDURE determineAccess ;
 VAR
-   tv: timeval ;
-   tz: timezone ;
+   ts: timespec ;
 BEGIN
-   tz := InitTimezone () ;
-   tv := InitTimeval () ;
-   canget := gettimeofday (tv, tz) = 0 ;
-   canset := canget AND (settimeofday (tv, tz) = 0) ;
-   tz := KillTimezone (tz) ;
-   tv := KillTimeval (tv)
+   IF NOT known
+   THEN
+      ts := InitTimespec () ;
+      canget := GetTimeRealtime (ts) = 0 ;
+      canset := canget AND (SetTimeRealtime (ts) = 0) ;
+      ts := KillTimespec (ts) ;
+      known := TRUE
+   END
 END determineAccess ;
 
 
 PROCEDURE CanGetClock () : BOOLEAN ;
 (* Tests if the clock can be read *)
 BEGIN
-   IF NOT known
-   THEN
-      determineAccess
-   END ;
+   determineAccess ;
    RETURN canget
 END CanGetClock ;
 
@@ -76,10 +73,7 @@ END CanGetClock ;
 PROCEDURE CanSetClock () : BOOLEAN ;
 (* Tests if the clock can be set *)
 BEGIN
-   IF NOT known
-   THEN
-      determineAccess
-   END ;
+   determineAccess ;
    RETURN canset
 END CanSetClock ;
 
@@ -114,42 +108,107 @@ BEGIN
 END IsValidDateTime ;
 
 
+(*
+   DivMod - returns seconds MOD modulus.  It also divides seconds by modulus.
+*)
+
+PROCEDURE DivMod (VAR seconds: LONGCARD; modulus: LONGCARD) : LONGCARD ;
+VAR
+   result: LONGCARD ;
+BEGIN
+   result := seconds MOD modulus ;
+   seconds := seconds DIV modulus ;
+   RETURN result
+END DivMod ;
+
+
+(*
+   daysInYear - return the number of days in year up to month/day.
+*)
+
+PROCEDURE daysInYear (day, month, year: LONGCARD) : LONGCARD ;
+BEGIN
+   WHILE month > 1 DO
+      INC (day, daysInMonth (year, month)) ;
+      DEC (month)
+   END ;
+   RETURN day
+END daysInYear ;
+
+
+(*
+   ExtractDate - extracts the year, month, day from days.
+*)
+
+PROCEDURE ExtractDate (days: LONGCARD;
+                       VAR year: CARDINAL; VAR month: Month; VAR day: Day) ;
+VAR
+   testMonth,
+   testYear : CARDINAL ;
+   testDays : LONGCARD ;
+BEGIN
+   testYear := 1970 ;
+   LOOP
+      testDays := daysInYear (31, 12, testYear) ;
+      IF days < testDays
+      THEN
+         year := testYear ;
+         testMonth := 1 ;
+         LOOP
+            testDays := daysInMonth (year, testMonth) ;
+            IF days < testDays
+            THEN
+               day := VAL (Day, days) + MIN (Day) ;
+               month := VAL (Month, testMonth) ;
+               RETURN
+            END ;
+            DEC (days, testDays) ;
+            INC (testMonth)
+         END
+      ELSE
+         DEC (days, testDays) ;
+         INC (testYear)
+      END
+   END
+END ExtractDate ;
+
+
 PROCEDURE GetClock (VAR userData: DateTime) ;
 (* Assigns local date and time of the day to userData *)
 VAR
-   m : tm ;
-   tv: timeval ;
-   tz: timezone ;
+   ts       : timespec ;
+   nano, sec: LONGCARD ;
+   offset   : LONGINT ;
 BEGIN
    IF CanGetClock ()
    THEN
-      tv := InitTimeval () ;
-      tz := InitTimezone () ;
-      IF gettimeofday (tv, tz)=0
+      ts := InitTimespec () ;
+      IF GetTimeRealtime (ts) = 0
       THEN
-         m := InitTM () ;
-         (* m := localtime_r (tv, m) ; *)
-         WITH userData DO
-         (*
-            year := GetYear (m) ;
-         *)
-            month := Args.Narg () (* GetMonth (m) *) (* + 1 *) ;
-            (*
-            day := GetDay (m) ;
-            hour := GetHour (m) ;
-            minute := GetMinute (m) ;
-            second := GetSecond (m) ;
-            fractions := GetFractions (tv) ;
-            zone := GetDST (tz) ;
-            summerTimeFlag := GetSummerTime (tz)
-            *)
+         GetTimespec (ts, sec, nano) ;
+         offset := timezone () ;
+         IF Debugging
+         THEN
+            printf ("getclock = %ld\n", sec)
+         END ;
+         sec := VAL (LONGINT, sec) + offset ;
+         IF Debugging
+         THEN
+            printf ("getclock = %ld\n", sec)
          END ;
-         m := KillTM (m)
+         WITH userData DO
+            second := VAL (Sec, DivMod (sec, MAX (Sec) + 1)) ;
+            minute := VAL (Min, DivMod (sec, MAX (Min) + 1)) ;
+            hour := VAL (Hour, DivMod (sec, MAX (Hour) + 1)) ;
+            ExtractDate (sec, year, month, day) ;
+            fractions := nano DIV ((1000 * 1000 * 1000) DIV maxSecondParts) ;
+            zone := - (offset DIV 60) ;
+            summerTimeFlag := (isdst () = 1)
+         END
       ELSE
          HALT
       END ;
-      tv := KillTimeval (tv) ;
-      tz := KillTimezone (tz)
+      ts := KillTimespec (ts)
    END
 END GetClock ;
 
@@ -158,7 +217,7 @@ END GetClock ;
    daysInMonth - returns how many days there are in a month.
 *)
 
-PROCEDURE daysInMonth (year, month: CARDINAL) : CARDINAL ;
+PROCEDURE daysInMonth (year, month: CARDINAL) : LONGCARD ;
 BEGIN
    CASE month OF
 
@@ -186,76 +245,73 @@ END daysInMonth ;
 
 
 (*
-   dayInYear -
+   totalYear - return the sum of all days prior to year from the epoch.
 *)
 
-PROCEDURE dayInYear (day, month, year: CARDINAL) : CARDINAL ;
+PROCEDURE totalYear (year: LONGCARD) : LONGCARD ;
+VAR
+   lastYear,
+   result  : LONGCARD ;
 BEGIN
-   WHILE month > 1 DO
-      INC (day, daysInMonth (year, month)) ;
-      DEC (month)
+   lastYear := 1970 ;
+   result := 0 ;
+   WHILE lastYear < year DO
+      INC (result, daysInYear (31, 12, lastYear)) ;
+      INC (lastYear)
    END ;
-   RETURN day
-END dayInYear ;
+   RETURN result
+END totalYear ;
 
 
 (*
-   dayInWeek -
+   totalSeconds - returns the total seconds
 *)
 
-PROCEDURE dayInWeek (day, month, year: CARDINAL) : CARDINAL ;
-CONST
-   janFirst1970 = 5 ;   (* thursday *)
+PROCEDURE totalSeconds (second, minute, hour,
+                        day, month, year: LONGCARD) : LONGCARD ;
 VAR
-   yearOffset: CARDINAL ;  (* days since Jan 1st 1970 *)
+   result: LONGCARD ;
 BEGIN
-   yearOffset := janFirst1970 ;
-   WHILE year > 1970 DO
-      DEC (year) ;
-      INC (yearOffset, dayInYear (31, 12, year))
-   END ;
-   INC (yearOffset, dayInYear (day, month, year)) ;
-   RETURN yearOffset MOD 7
-END dayInWeek ;
+   result := second
+             + minute * (MAX (Sec) + 1)
+             + hour * ((MAX (Min) + 1) * (MAX (Sec) + 1))
+             + ((daysInYear (day, month, year) + totalYear (year))
+                * ((MAX (Hour) + 1) * ((MAX (Min) + 1) * (MAX (Sec) + 1)))) ;
+   RETURN result
+END totalSeconds ;
 
 
 PROCEDURE SetClock (userData: DateTime);
-(* Sets the system time clock to the given local date and
-   time *)
 VAR
-   tv: timeval ;
-   tz: timezone ;
+   ts       : timespec ;
+   nano, sec: LONGCARD ;
+   offset   : LONGINT ;
 BEGIN
+   IF Debugging
+   THEN
+      sec := totalSeconds (userData.second, userData.minute, userData.hour,
+                           VAL (CARDINAL, userData.day) - MIN (Day),
+                           userData.month, userData.year) ;
+      printf ("setclock = %ld\n", sec);
+      offset := timezone () ;
+      sec := VAL (LONGINT, sec) - offset ;
+      printf ("setclock = %ld\n", sec);
+   END ;
    IF CanSetClock ()
    THEN
-      tv := InitTimeval () ;
-      tz := InitTimezone () ;
-      IF gettimeofday (tv, tz) = 0
+      ts := InitTimespec () ;
+      nano := VAL (LONGCARD, userData.fractions * 1000) ;
+      sec := totalSeconds (userData.second, userData.minute, userData.hour,
+                           VAL (CARDINAL, userData.day) - MIN (Day),
+                           userData.month, userData.year) ;
+      offset := timezone () ;
+      sec := VAL (LONGINT, sec) - offset ;
+      SetTimespec (ts, sec, nano) ;
+      IF SetTimeRealtime (ts) # 0
       THEN
-         (* fill in as many of tv, tz fields from userData as we can *)
-         WITH userData DO
-            IF summerTimeFlag
-            THEN
-               SetTimeval (tv, second, minute, hour, day, month, year,
-                           dayInYear(day, month, year),
-                           dayInWeek(day, month, year),
-                           1) ;
-               SetTimezone (tz, 1, zone)
-            ELSE
-               SetTimeval (tv, second, minute, hour, day, month, year,
-                           dayInYear(day, month, year),
-                           dayInWeek(day, month, year),
-                           0) ;
-               SetTimezone (tz, 0, zone)
-            END ;
-            IF settimeofday (tv, tz)#0
-            THEN
-               (* error, which we ignore *)
-            END
-         END
+         HALT
       END ;
-      tv := KillTimeval (tv) ;
-      tz := KillTimezone (tz)
+      ts := KillTimespec (ts)
    END
 END SetClock ;
 
diff --git a/gcc/m2/gm2-libs-iso/wrapclock.def b/gcc/m2/gm2-libs-iso/wrapclock.def
new file mode 100644
index 00000000000..9e1644b3992
--- /dev/null
+++ b/gcc/m2/gm2-libs-iso/wrapclock.def
@@ -0,0 +1,125 @@
+(* wrapclock.def provides access to clock primitives.
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+Contributed by Gaius Mulley <gaiusmod2@gmail.com>.
+
+This file is part of GNU Modula-2.
+
+GNU Modula-2 is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GNU Modula-2 is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  *)
+
+DEFINITION MODULE wrapclock ;
+
+FROM SYSTEM IMPORT ADDRESS ;
+
+TYPE
+   timespec = ADDRESS ;
+
+
+(*
+   timezone - return the glibc timezone value.
+              This contains the difference between UTC and the latest
+              local standard time, in seconds west of UTC.
+*)
+
+PROCEDURE timezone () : LONGINT ;
+
+
+(*
+   daylight - return the glibc daylight value.
+              This variable has a nonzero value if Daylight Saving
+              Time rules apply.
+              A nonzero value does not necessarily mean that Daylight
+              Saving Time is now in effect; it means only that Daylight
+              Saving Time is sometimes in effect.
+*)
+
+PROCEDURE daylight () : INTEGER ;
+
+
+(*
+   isdst - returns 1 if daylight saving time is currently in effect and
+           returns 0 if it is not.
+*)
+
+PROCEDURE isdst () : INTEGER ;
+
+
+(*
+   tzname - returns the string associated with the local timezone.
+            The daylight value is 0 or 1.  The value 0 returns the non
+            daylight saving timezone string and the value of 1 returns
+            the daylight saving timezone string.
+*)
+
+PROCEDURE tzname (daylight: INTEGER) : ADDRESS ;
+
+
+(*
+   InitTimespec - returns a newly created opaque type.
+*)
+
+PROCEDURE InitTimespec () : timespec ;
+
+
+(*
+   KillTimespec - deallocates the memory associated with an
+                  opaque type.
+*)
+
+PROCEDURE KillTimespec (tv: timespec) : timespec ;
+
+
+(*
+   GetTimespec - retrieves the number of seconds and nanoseconds
+                 from the timespec.
+*)
+
+PROCEDURE GetTimespec (ts: timespec; VAR sec, nano: LONGCARD) ;
+
+
+(*
+   SetTimespec - sets the number of seconds and nanoseconds
+                 into timespec.
+*)
+
+PROCEDURE SetTimespec (ts: timespec; sec, nano: LONGCARD) ;
+
+
+(*
+   GetTimeRealtime - performs return gettime (CLOCK_REALTIME, ts).
+                     gettime returns 0 on success and -1 on failure.
+                     If the underlying system does not have gettime
+                     then GetTimeRealtime returns 1.
+*)
+
+PROCEDURE GetTimeRealtime (ts: timespec) : INTEGER ;
+
+
+(*
+   SetTimeRealtime - performs return settime (CLOCK_REALTIME, ts).
+                     gettime returns 0 on success and -1 on failure.
+                     If the underlying system does not have gettime
+                     then SetTimeRealtime returns 1.
+*)
+
+PROCEDURE SetTimeRealtime (ts: timespec) : INTEGER ;
+
+
+END wrapclock.
diff --git a/gcc/testsuite/gm2/iso/run/pass/m2date.mod b/gcc/testsuite/gm2/iso/run/pass/m2date.mod
new file mode 100644
index 00000000000..1d8b595fc81
--- /dev/null
+++ b/gcc/testsuite/gm2/iso/run/pass/m2date.mod
@@ -0,0 +1,101 @@
+MODULE m2date ;
+
+IMPORT SysClock, STextIO, SWholeIO ;
+FROM SysClock IMPORT DateTime, GetClock ;
+FROM wrapclock IMPORT tzname ;
+FROM ASCII IMPORT nul ;
+
+
+TYPE
+   Name = ARRAY [0..3] OF CHAR ;
+   DayArray = ARRAY [0..6] OF Name ;
+   MonthArray = ARRAY [0..11] OF Name ;
+
+CONST
+   Debugging = FALSE ;
+   DayName = DayArray { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" } ;
+   MonthName = MonthArray { "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov" } ;
+
+
+
+PROCEDURE WriteTZ (daylight: CARDINAL) ;
+VAR
+   tz : ARRAY [0..10] OF CHAR ;
+   ptr: POINTER TO CHAR ;
+   i  : CARDINAL ;
+BEGIN
+   ptr := tzname (daylight) ;
+   i := 0 ;
+   WHILE (i <= HIGH (tz)) AND (ptr^ # nul) DO
+      tz[i] := ptr^ ;
+      INC (ptr) ;
+      INC (i)
+   END ;
+   IF i < HIGH (tz)
+   THEN
+      tz[i] := nul
+   END ;
+   STextIO.WriteString (tz)
+END WriteTZ ;
+
+
+PROCEDURE WriteNum (num: CARDINAL) ;
+BEGIN
+   IF num < 10
+   THEN
+      STextIO.WriteString ("0")
+   END ;
+   SWholeIO.WriteCard (num, 0)
+END WriteNum ;
+
+
+VAR
+   dt: DateTime ;
+BEGIN
+   IF SysClock.CanGetClock ()
+   THEN
+      GetClock (dt) ;
+      IF Debugging
+      THEN
+         STextIO.WriteString ("success we can get the clock") ; STextIO.WriteLn ;
+         STextIO.WriteString (" year     : ") ; SWholeIO.WriteCard (dt.year, 4) ;
+         STextIO.WriteLn ;
+         STextIO.WriteString (" month    : ") ; SWholeIO.WriteCard (dt.month, 4) ;
+         STextIO.WriteLn ;
+         STextIO.WriteString (" day      : ") ; SWholeIO.WriteCard (dt.day, 4) ;
+         STextIO.WriteLn ;
+         STextIO.WriteString (" hour     : ") ; SWholeIO.WriteCard (dt.hour, 4) ;
+         STextIO.WriteLn ;
+         STextIO.WriteString (" minute   : ") ; SWholeIO.WriteCard (dt.minute, 4) ;
+         STextIO.WriteLn ;
+         STextIO.WriteString (" second   : ") ; SWholeIO.WriteCard (dt.second, 4) ;
+         STextIO.WriteLn ;
+         STextIO.WriteString (" fractions: ") ; SWholeIO.WriteCard (dt.fractions, 10) ;
+         STextIO.WriteLn ;
+         STextIO.WriteString (" zone     : ") ; SWholeIO.WriteCard (dt.zone, 10) ;
+         STextIO.WriteLn
+      END ;
+      STextIO.WriteString (DayName[dt.day MOD 7]) ;
+      STextIO.WriteString (" ") ;
+      SWholeIO.WriteCard (dt.day, 2) ;
+      STextIO.WriteString (" ") ;
+      STextIO.WriteString (MonthName[dt.month MOD 12]) ;
+      STextIO.WriteString (" ") ;
+      WriteNum (dt.hour) ; STextIO.WriteString (":") ;
+      WriteNum (dt.minute) ; STextIO.WriteString (":") ;
+      WriteNum (dt.second) ; STextIO.WriteString (" ") ;
+      IF dt.summerTimeFlag
+      THEN
+         WriteTZ (1)
+      ELSE
+         WriteTZ (0)
+      END ;
+      STextIO.WriteString (" ") ;
+      SWholeIO.WriteCard (dt.year, 0) ;
+      STextIO.WriteLn
+   ELSE
+      STextIO.WriteString ("unable to get the clock") ;
+      STextIO.WriteLn ;
+      HALT (1)
+   END
+END m2date.
diff --git a/gcc/testsuite/gm2/iso/run/pass/testclock.mod b/gcc/testsuite/gm2/iso/run/pass/testclock.mod
new file mode 100644
index 00000000000..a546eafdf28
--- /dev/null
+++ b/gcc/testsuite/gm2/iso/run/pass/testclock.mod
@@ -0,0 +1,15 @@
+MODULE testclock ;
+
+IMPORT SysClock, STextIO ;
+
+BEGIN
+   IF SysClock.CanGetClock ()
+   THEN
+      STextIO.WriteString ("success we can get the clock") ;
+      STextIO.WriteLn
+   ELSE
+      STextIO.WriteString ("unable to get the clock") ;
+      STextIO.WriteLn ;
+      HALT (1)
+   END
+END testclock.
diff --git a/gcc/testsuite/gm2/iso/run/pass/testclock2.mod b/gcc/testsuite/gm2/iso/run/pass/testclock2.mod
new file mode 100644
index 00000000000..c80faff8aef
--- /dev/null
+++ b/gcc/testsuite/gm2/iso/run/pass/testclock2.mod
@@ -0,0 +1,22 @@
+MODULE testclock2 ;
+
+IMPORT SysClock, STextIO ;
+
+VAR
+   dt: SysClock.DateTime ;
+BEGIN
+   IF SysClock.CanGetClock ()
+   THEN
+      SysClock.GetClock (dt) ;
+      IF SysClock.CanSetClock ()
+      THEN
+         STextIO.WriteString ("success we can set the clock") ; STextIO.WriteLn ;
+         SysClock.SetClock (dt)
+      ELSE
+         STextIO.WriteString ("unable to set the clock") ; STextIO.WriteLn
+      END
+      ; SysClock.SetClock (dt)
+   ELSE
+      STextIO.WriteString ("unable to get the clock") ; STextIO.WriteLn
+   END
+END testclock2.
diff --git a/libgm2/config.h.in b/libgm2/config.h.in
index 443008ebe75..8372055a47a 100644
--- a/libgm2/config.h.in
+++ b/libgm2/config.h.in
@@ -9,6 +9,12 @@
 /* function cfmakeraw exists */
 #undef HAVE_CFMAKERAW
 
+/* function clock_gettime exists */
+#undef HAVE_CLOCK_GETTIME
+
+/* function clock_settime exists */
+#undef HAVE_CLOCK_SETTIME
+
 /* function close exists */
 #undef HAVE_CLOSE
 
@@ -180,6 +186,9 @@
 /* Define to 1 if the system has the type `struct stat'. */
 #undef HAVE_STRUCT_STAT
 
+/* Define to 1 if the system has the type `struct timespec'. */
+#undef HAVE_STRUCT_TIMESPEC
+
 /* Define to 1 if the system has the type `struct timeval'. */
 #undef HAVE_STRUCT_TIMEVAL
 
diff --git a/libgm2/configure b/libgm2/configure
index da3d3bd4391..488055b0a28 100755
--- a/libgm2/configure
+++ b/libgm2/configure
@@ -16073,6 +16073,15 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+fi
+ac_fn_c_check_type "$LINENO" "struct timespec" "ac_cv_type_struct_timespec" "$ac_includes_default"
+if test "x$ac_cv_type_struct_timespec" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TIMESPEC 1
+_ACEOF
+
+
 fi
 ac_fn_c_check_type "$LINENO" "struct timeval" "ac_cv_type_struct_timeval" "$ac_includes_default"
 if test "x$ac_cv_type_struct_timeval" = xyes; then :
@@ -16913,6 +16922,144 @@ $as_echo "#define HAVE_CFMAKERAW 1" >>confdefs.h
   fi
 
 
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking m2 front end checking c library for clock_gettime" >&5
+$as_echo_n "checking m2 front end checking c library for clock_gettime... " >&6; }
+  if test x$gcc_no_link != xyes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lc" >&5
+$as_echo_n "checking for clock_gettime in -lc... " >&6; }
+if ${ac_cv_lib_c_clock_gettime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+if test x$gcc_no_link = xyes; then
+  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_c_clock_gettime=yes
+else
+  ac_cv_lib_c_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_clock_gettime" >&5
+$as_echo "$ac_cv_lib_c_clock_gettime" >&6; }
+if test "x$ac_cv_lib_c_clock_gettime" = xyes; then :
+
+$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+else
+
+  $as_echo "#undef HAVE_CLOCK_GETTIME" >>confdefs.h
+
+fi
+
+  else
+    if test "x$ac_cv_lib_c_clock_gettime" = xyes; then
+
+$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+    elif test "x$ac_cv_func_clock_gettime" = xyes; then
+
+$as_echo "#define HAVE_CLOCK_GETTIME 1" >>confdefs.h
+
+    else
+
+  $as_echo "#undef HAVE_CLOCK_GETTIME" >>confdefs.h
+
+    fi
+  fi
+
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking m2 front end checking c library for clock_settime" >&5
+$as_echo_n "checking m2 front end checking c library for clock_settime... " >&6; }
+  if test x$gcc_no_link != xyes; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_settime in -lc" >&5
+$as_echo_n "checking for clock_settime in -lc... " >&6; }
+if ${ac_cv_lib_c_clock_settime+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc  $LIBS"
+if test x$gcc_no_link = xyes; then
+  as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_settime ();
+int
+main ()
+{
+return clock_settime ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_c_clock_settime=yes
+else
+  ac_cv_lib_c_clock_settime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_clock_settime" >&5
+$as_echo "$ac_cv_lib_c_clock_settime" >&6; }
+if test "x$ac_cv_lib_c_clock_settime" = xyes; then :
+
+$as_echo "#define HAVE_CLOCK_SETTIME 1" >>confdefs.h
+
+else
+
+  $as_echo "#undef HAVE_CLOCK_SETTIME" >>confdefs.h
+
+fi
+
+  else
+    if test "x$ac_cv_lib_c_clock_settime" = xyes; then
+
+$as_echo "#define HAVE_CLOCK_SETTIME 1" >>confdefs.h
+
+    elif test "x$ac_cv_func_clock_settime" = xyes; then
+
+$as_echo "#define HAVE_CLOCK_SETTIME 1" >>confdefs.h
+
+    else
+
+  $as_echo "#undef HAVE_CLOCK_SETTIME" >>confdefs.h
+
+    fi
+  fi
+
+
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking m2 front end checking c library for close" >&5
 $as_echo_n "checking m2 front end checking c library for close... " >&6; }
   if test x$gcc_no_link != xyes; then
diff --git a/libgm2/configure.ac b/libgm2/configure.ac
index c78c8335cef..d64a8ee80a9 100644
--- a/libgm2/configure.ac
+++ b/libgm2/configure.ac
@@ -187,7 +187,7 @@ else
   multilib_arg=
 fi
 
-AC_CHECK_TYPES([struct timezone, struct stat, struct timeval])
+AC_CHECK_TYPES([struct timezone, struct stat, struct timespec, struct timeval])
 
 AC_LANG_C
 # Check the compiler.
@@ -225,6 +225,8 @@ AC_DEFUN([GM2_CHECK_LIB],[
 GM2_CHECK_LIB([c],[access],[ACCESS])
 GM2_CHECK_LIB([c],[brk],[BRK])
 GM2_CHECK_LIB([c],[cfmakeraw],[CFMAKERAW])
+GM2_CHECK_LIB([c],[clock_gettime],[CLOCK_GETTIME])
+GM2_CHECK_LIB([c],[clock_settime],[CLOCK_SETTIME])
 GM2_CHECK_LIB([c],[close],[CLOSE])
 GM2_CHECK_LIB([c],[ctime],[CTIME])
 GM2_CHECK_LIB([c],[creat],[CREAT])
diff --git a/libgm2/libm2iso/Makefile.am b/libgm2/libm2iso/Makefile.am
index 8c70f5c5ee0..1386f156cab 100644
--- a/libgm2/libm2iso/Makefile.am
+++ b/libgm2/libm2iso/Makefile.am
@@ -136,8 +136,8 @@ M2DEFS = ChanConsts.def  CharClass.def \
          TERMINATION.def  TextIO.def \
          TextUtil.def \
          WholeConv.def  WholeIO.def \
-         WholeStr.def  wrapsock.def \
-         wraptime.def
+         WholeStr.def  wrapclock.def \
+         wrapsock.def wraptime.def
 
 M2MODS = ChanConsts.mod  CharClass.mod \
          ClientSocket.mod  ComplexMath.mod \
@@ -180,7 +180,7 @@ M2MODS = ChanConsts.mod  CharClass.mod \
 
 toolexeclib_LTLIBRARIES = libm2iso.la
 libm2iso_la_SOURCES =  $(M2MODS) \
-                     ErrnoCategory.cc wraptime.cc RTco.cc wrapsock.c
+                     ErrnoCategory.cc RTco.cc wrapclock.cc wraptime.cc wrapsock.c
 #  wrapsock.cc
 
 C_INCLUDES = -I.. -I$(toplevel_srcdir)/libiberty -I$(toplevel_srcdir)/include
diff --git a/libgm2/libm2iso/Makefile.in b/libgm2/libm2iso/Makefile.in
index 6787a5a9d96..b939581b7c1 100644
--- a/libgm2/libm2iso/Makefile.in
+++ b/libgm2/libm2iso/Makefile.in
@@ -179,8 +179,8 @@ libm2iso_la_LIBADD =
 @BUILD_ISOLIB_TRUE@	TextIO.lo TextUtil.lo WholeConv.lo \
 @BUILD_ISOLIB_TRUE@	WholeIO.lo WholeStr.lo
 @BUILD_ISOLIB_TRUE@am_libm2iso_la_OBJECTS = $(am__objects_1) \
-@BUILD_ISOLIB_TRUE@	ErrnoCategory.lo wraptime.lo RTco.lo \
-@BUILD_ISOLIB_TRUE@	libm2iso_la-wrapsock.lo
+@BUILD_ISOLIB_TRUE@	ErrnoCategory.lo RTco.lo wrapclock.lo \
+@BUILD_ISOLIB_TRUE@	wraptime.lo libm2iso_la-wrapsock.lo
 libm2iso_la_OBJECTS = $(am_libm2iso_la_OBJECTS)
 @BUILD_ISOLIB_TRUE@am_libm2iso_la_rpath = -rpath $(toolexeclibdir)
 AM_V_P = $(am__v_P_@AM_V@)
@@ -513,8 +513,8 @@ FLAGS_TO_PASS = $(AM_MAKEFLAGS)
 @BUILD_ISOLIB_TRUE@         TERMINATION.def  TextIO.def \
 @BUILD_ISOLIB_TRUE@         TextUtil.def \
 @BUILD_ISOLIB_TRUE@         WholeConv.def  WholeIO.def \
-@BUILD_ISOLIB_TRUE@         WholeStr.def  wrapsock.def \
-@BUILD_ISOLIB_TRUE@         wraptime.def
+@BUILD_ISOLIB_TRUE@         WholeStr.def  wrapclock.def \
+@BUILD_ISOLIB_TRUE@         wrapsock.def wraptime.def
 
 @BUILD_ISOLIB_TRUE@M2MODS = ChanConsts.mod  CharClass.mod \
 @BUILD_ISOLIB_TRUE@         ClientSocket.mod  ComplexMath.mod \
@@ -557,7 +557,7 @@ FLAGS_TO_PASS = $(AM_MAKEFLAGS)
 
 @BUILD_ISOLIB_TRUE@toolexeclib_LTLIBRARIES = libm2iso.la
 @BUILD_ISOLIB_TRUE@libm2iso_la_SOURCES = $(M2MODS) \
-@BUILD_ISOLIB_TRUE@                     ErrnoCategory.cc wraptime.cc RTco.cc wrapsock.c
+@BUILD_ISOLIB_TRUE@                     ErrnoCategory.cc RTco.cc wrapclock.cc wraptime.cc wrapsock.c
 
 #  wrapsock.cc
 @BUILD_ISOLIB_TRUE@C_INCLUDES = -I.. -I$(toplevel_srcdir)/libiberty -I$(toplevel_srcdir)/include
@@ -658,6 +658,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ErrnoCategory.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/RTco.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libm2iso_la-wrapsock.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrapclock.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wraptime.Plo@am__quote@
 
 .c.o:
diff --git a/libgm2/libm2iso/wrapclock.cc b/libgm2/libm2iso/wrapclock.cc
new file mode 100644
index 00000000000..7ee1f25c2fb
--- /dev/null
+++ b/libgm2/libm2iso/wrapclock.cc
@@ -0,0 +1,220 @@
+/* wrapclock.cc provides access to time related system calls.
+
+Copyright (C) 2009-2022 Free Software Foundation, Inc.
+Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
+
+This file is part of GNU Modula-2.
+
+GNU Modula-2 is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GNU Modula-2 is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include <m2rts.h>
+
+#define EXPORT(FUNC) m2iso ## _wrapclock_ ## FUNC
+#define M2EXPORT(FUNC) m2iso ## _M2_wrapclock_ ## FUNC
+#define M2LIBNAME "m2iso"
+
+#if defined(HAVE_STDLIB_H)
+#include "stdlib.h"
+#endif
+
+#if defined(HAVE_UNISTD_H)
+#include "unistd.h"
+#endif
+
+#if defined(HAVE_SYS_TYPES_H)
+#include "sys/types.h"
+#endif
+
+#if defined(HAVE_SYS_TIME_H)
+#include "sys/time.h"
+#endif
+
+#if defined(HAVE_TIME_H)
+#include "time.h"
+#endif
+
+#if defined(HAVE_MALLOC_H)
+#include "malloc.h"
+#endif
+
+#if defined(HAVE_LIMITS_H)
+#include "limits.h"
+#endif
+
+#if !defined(NULL)
+#define NULL (void *)0
+#endif
+
+
+extern "C" long int
+EXPORT(timezone) (void)
+{
+  struct tm result;
+  struct timespec ts;
+
+  if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
+    {
+      time_t time = ts.tv_sec;
+      localtime_r (&time, &result);
+      return result.tm_gmtoff;
+    }
+  else
+    return timezone;
+}
+
+
+extern "C" int
+EXPORT(daylight) (void)
+{
+  return daylight;
+}
+
+
+/* isdst returns 1 if daylight saving time is currently in effect and
+   returns 0 if it is not.  */
+
+extern "C" int
+EXPORT(isdst) (void)
+{
+  struct tm result;
+  struct timespec ts;
+
+  if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
+    {
+      time_t time = ts.tv_sec;
+      localtime_r (&time, &result);
+      return result.tm_isdst;
+    }
+  else
+    return 0;
+}
+
+
+/* tzname returns the string associated with the local timezone.
+   The daylight value is 0 or 1.  The value 0 returns the non
+   daylight saving timezone string and the value of 1 returns the
+   daylight saving timezone string.  */
+
+extern "C" char *
+EXPORT(tzname) (int daylight)
+{
+  return tzname[daylight];
+}
+
+
+/* GetTimeRealtime performs return gettime (CLOCK_REALTIME, ts).
+   gettime returns 0 on success and -1 on failure.  If the underlying
+   system does not have gettime then GetTimeRealtime returns 1.  */
+
+extern "C" int
+EXPORT(GetTimeRealtime) (struct timespec *ts)
+{
+#if defined(HAVE_CLOCK_GETTIME)
+  return clock_gettime (CLOCK_REALTIME, ts);
+#else
+  return 1;
+#endif
+}
+
+
+/* SetTimeRealtime performs return settime (CLOCK_REALTIME, ts).
+   gettime returns 0 on success and -1 on failure.  If the underlying
+   system does not have gettime then GetTimeRealtime returns 1.  */
+
+extern "C" int
+EXPORT(SetTimeRealtime) (struct timespec *ts)
+{
+#if defined(HAVE_CLOCK_GETTIME)
+  return clock_settime (CLOCK_REALTIME, ts);
+#else
+  return 1;
+#endif
+}
+
+
+/* InitTimespec returns a newly created opaque type.  */
+
+extern "C" struct timespec *
+EXPORT(InitTimespec) (void)
+{
+  return (struct timespec *)malloc (sizeof (struct timespec));
+}
+
+
+/* KillTimeval deallocates the memory associated with an opaque type.  */
+
+extern "C" struct timespec *
+EXPORT(KillTimespec) (void *ts)
+{
+#if defined(HAVE_MALLOC_H)
+  free (ts);
+#endif
+  return NULL;
+}
+
+
+/* GetTimespec retrieves the number of seconds and nanoseconds from the
+   timespec.  */
+
+extern "C" void
+EXPORT(GetTimespec) (timespec *ts, unsigned long *sec, unsigned long *nano)
+{
+  *sec = ts->tv_sec;
+  *nano = ts->tv_nsec;
+}
+
+
+/* SetTimespec sets the number of seconds and nanoseconds into timespec.  */
+
+extern "C" void
+EXPORT(SetTimespec) (timespec *ts, unsigned long sec, unsigned long nano)
+{
+  ts->tv_sec = sec;
+  ts->tv_nsec = nano;
+}
+
+
+/* init - init/finish functions for the module */
+
+/* GNU Modula-2 linking hooks.  */
+
+extern "C" void
+M2EXPORT(init) (int, char **, char **)
+{
+}
+
+extern "C" void
+M2EXPORT(fini) (int, char **, char **)
+{
+}
+
+extern "C" void
+M2EXPORT(dep) (void)
+{
+}
+
+extern "C" void __attribute__((__constructor__))
+M2EXPORT(ctor) (void)
+{
+  m2iso_M2RTS_RegisterModule ("wrapclock", M2LIBNAME,
+			      M2EXPORT(init), M2EXPORT(fini),
+			      M2EXPORT(dep));
+}
diff --git a/libgm2/libm2iso/wraptime.cc b/libgm2/libm2iso/wraptime.cc
index ffe85f17dca..f1158ae7d38 100644
--- a/libgm2/libm2iso/wraptime.cc
+++ b/libgm2/libm2iso/wraptime.cc
@@ -55,9 +55,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define NULL (void *)0
 #endif
 
+
 /* InitTimeval returns a newly created opaque type.  */
 
-#if defined(HAVE_TIMEVAL) && defined(HAVE_MALLOC_H)
+#if defined(HAVE_STRUCT_TIMEVAL) && defined(HAVE_MALLOC_H)
 extern "C" struct timeval *
 EXPORT(InitTimeval) (void)
 {
@@ -174,7 +175,7 @@ EXPORT(settimeofday) (void *tv, void *tz)
 /* wraptime_GetFractions - returns the tv_usec field inside the
    timeval structure.  */
 
-#if defined(HAVE_TIMEVAL)
+#if defined(HAVE_STRUCT_TIMEVAL)
 extern "C" unsigned int
 EXPORT(GetFractions) (struct timeval *tv)
 {
@@ -193,7 +194,7 @@ EXPORT(GetFractions) (void *tv)
    this procedure function expects, timeval, as its first parameter
    and not a time_t (as expected by the posix equivalent).  */
 
-#if defined(HAVE_TIMEVAL)
+#if defined(HAVE_STRUCT_TIMEVAL)
 extern "C" struct tm *
 EXPORT(localtime_r) (struct timeval *tv, struct tm *m)
 {
@@ -366,7 +367,7 @@ EXPORT(SetTimezone) (void *tz, int zone, int minuteswest)
 /* SetTimeval - sets the fields in tm, t, with: second, minute, hour,
    day, month, year, fractions.  */
 
-#if defined(HAVE_TIMEVAL)
+#if defined(HAVE_STRUCT_TIMEVAL)
 extern "C" void
 EXPORT(SetTimeval) (struct tm *t, unsigned int second, unsigned int minute,
 		    unsigned int hour, unsigned int day, unsigned int month,

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-08-05 16:39 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-05 16:39 [gcc r14-3006] PR modula2/110779 SysClock can not read the clock Gaius Mulley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).