From 0826ebd633e38bd55abd161c15deb431420f82a3 Mon Sep 17 00:00:00 2001 From: Gaius Mulley Date: Sat, 5 Aug 2023 17:35:12 +0100 Subject: 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 --- 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(-) create mode 100644 gcc/m2/gm2-libs-iso/wrapclock.def create mode 100644 gcc/testsuite/gm2/iso/run/pass/m2date.mod create mode 100644 gcc/testsuite/gm2/iso/run/pass/testclock.mod create mode 100644 gcc/testsuite/gm2/iso/run/pass/testclock2.mod create mode 100644 libgm2/libm2iso/wrapclock.cc diff --git a/gcc/m2/gm2-libs-iso/SysClock.mod b/gcc/m2/gm2-libs-iso/SysClock.mod index e894489..60261f2 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 0000000..9e1644b --- /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 . + +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 +. *) + +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 0000000..1d8b595 --- /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 0000000..a546eaf --- /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 0000000..c80faff --- /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 443008e..8372055 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 da3d3bd..488055b 100755 --- a/libgm2/configure +++ b/libgm2/configure @@ -16074,6 +16074,15 @@ _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 c78c833..d64a8ee 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 8c70f5c..1386f15 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 6787a5a..b939581 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 0000000..7ee1f25 --- /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 . + +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 +. */ + +#include "config.h" +#include + +#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 ffe85f1..f1158ae 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, -- cgit v1.1