0

I have the following Ada function

function Get_GPS_Epoch(Time : Standard_Types.Integer_Type)
return Global_Types.Long_GPS_Time_Type;
pragma import(C, get_GPS_Epoch, "getGpsEpoch");

On the C side

unsigned long long
getGpsEpoch(time_t startTime)
{
    time_t gpsEpoch;

    // Get current time
    time_t curTime;
    if (startTime == -1)
        curTime = time(NULL);
    else
        curTime = startTime;

    // Get gmtime broken down into parts
    struct tm utcTime
    if (curTime >=0 && gmtime_r(&curTime, &utcTime))
    {
        // Calculate the number of seconds from the Linux epoch
        // to the GPS epoch which is midnight Jan 1st of the current year
        gpsEpoch = curtime - (utcTime.tm_yday * 86400 +
                              utcTime.tm_hour *  3600 +
                              utcTime.tm_min  *    60 +
                              utcTime.tm_sec);
    }
    // Convert to micro seconds
    return (unsigned long long)gpsEpoch * 1000000;
}

My issue is on Ada I call the following

Get_GPS_Epoch(-1);

and then when it gets into the C function (using the debugger) the -1 becomes 4294967295.

(Both are 1111 1111 1111 1111 when the binary is printed by the debugger, making me think they are using different word sizes (QWORD vs DWORD) but I'm not experienced with issues like this.

This makes me think that time_t is an unsigned int but I'm not sure if it would act this way if it was. Would it just break? or am I just spoiled by Ada Range Check Exceptions?

In previous baselines, this worked. They were also on a different RHEL version.

Student
  • 805
  • 1
  • 8
  • 11
JDiGz
  • 23
  • 5
  • You might want to see https://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to – Richard Chambers Jul 26 '18 at 20:53
  • I already looked at that and unless I read it too fast what I got from it was time_t isn't defined. It didn't tell me how to find out what it equivalent to on my system though. – JDiGz Jul 26 '18 at 20:56
  • Did you look at this answer from that question: https://stackoverflow.com/a/36096104/8513665 Has a nice one-liner that should tell you `time_t`'s definition. – Christian Gibbons Jul 26 '18 at 21:03
  • Transform the `time_t` value into a more standard value to pass over the interface and then if needed transform it back to a `time_t` value once the standard value is across the interface. Since it is undefined by the standard, best not to try to use it across interfaces the way you are doing. – Richard Chambers Jul 26 '18 at 21:04
  • don't use `Time : Standard_Types.Integer_Type` use `Interfaces.C.Integer` – Jean-François Fabre Jul 26 '18 at 21:05
  • All of these are awesome suggestions. I will try then ASAP. @Christian Gibbons, Thanks! I checked and __time_t is a long int, which confuses me even more because that would mean that it doesn't go up to 4,294,967,295. Shouldn't be from -2,147,483,648 to 2,147,483,647?? – JDiGz Jul 26 '18 at 21:19
  • @JDiGz Unfortunately, `time_t` is very weakly defined by the standard. It could even be a float. Makes it very difficult to write a portable library that uses `time_t` and checks for overflow. – Christian Gibbons Jul 27 '18 at 18:26
  • @DavidC.Rankin: `time_t` is not equivalent to `size_t` (did you omit a "not"?). `time_t` is most commonly a signed type; `size_t` is always unsigned. – Keith Thompson Jul 27 '18 at 20:31
  • @JDiGz: How wide is `long int` on your system? If it's 64 bits, then `time_t` has enough range to last for hundreds of billions of years. If it's 32 bits, then it has a problem in the year 2038, but making it unsigned would mean it can't represent times before the epoch (1970). (I'm assuming some things about `time_t` that aren't guaranteed by the C standard, particularly that it represents seconds since 1970-01-01 00:00:00 GMT.) – Keith Thompson Jul 27 '18 at 20:33
  • @KeithThompson - right you are -- I'm not sure how I gleaned that from a misread of the standard -- in fact, it's implementation defined -- if at all, so `time_t` is not the same a `size_t` [What is ultimately a time_t typedef to?](https://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to) – David C. Rankin Jul 27 '18 at 20:49

2 Answers2

0

Assuming you are using GCC, you could use gcc -fdump-ada-spec to generate an Ada binding to your C function. That should generate a binding guaranteed to work (with that version of GCC used for compiling both C and Ada).

Jacob Sparre Andersen
  • 6,733
  • 17
  • 22
0

So here is how I "solved" this issue.

After a TON of great feedback, (thank you everyone who posted).

I changed the functionality so that it didn't use -1 as the criteria to get current time.(see "if (startTime == -1) curTime=time(NULL);

So in the cases where I needed to pass a negative number to signal to get the current time, it now just gets the current time. It was a bad initial design.

Thanks everyone for the help!

JDiGz
  • 23
  • 5