Initial commit to the PapyrusRT repository.

This is the initial commit as submitted to CQ 9646.

The repository contains two top-level folders:

- codegen: the code-generator
- rts: the run-time system

Also-by: Andrew Eidsness, Zeligsoft contractor, andrewe@jfront.com,
Barry Maher, Zeligsoft contractor, bmaher@gpinc.ca, Ernesto Posse,
Zeligsoft, eposse@zeligsoft.com, Tim McGuire, Zeligsoft,
tmcguire@zeligsoft.com, Young-Soo Roh, Zeligsoft, ysroh@zeligsoft.com,
Toby McClean, Zeligsoft, toby@zeligsoft.com, Charles Rivet, Zeligsoft,
charles@zeligsoft.com, Andreas Henriksson, Ericsson,
andreas.henriksson@ericsson.com, Akos Horvath, IncQuery Labs,
akos.horvath@incquerylabs.com, Gabor Batori, Ericsson,
Gabor.Batori@ericsson.com, Abel Hegedus, IncQuery Labs,
abel.hegedus@incquerylabs.com, Denes Harmath, IncQuery Labs,
harmathdenes@gmail.com
Signed-off-by: Ernesto Posse <eposse@gmail.com>
diff --git a/rts/umlrt/umlrttimespec.cc b/rts/umlrt/umlrttimespec.cc
new file mode 100644
index 0000000..9589b82
--- /dev/null
+++ b/rts/umlrt/umlrttimespec.cc
@@ -0,0 +1,205 @@
+// umlrttimerspec.cc
+
+/*******************************************************************************
+* Copyright (c) 2014-2015 Zeligsoft (2009) Limited  and others.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/legal/epl-v10.html
+*******************************************************************************/
+
+#include "umlrttimespec.hh"
+#include "basefatal.hh"
+#include <sys/time.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+UMLRTTimespec::UMLRTTimespec( const UMLRTTimespec & tm ) : tv_sec(tm.tv_sec), tv_nsec(tm.tv_nsec) { }
+
+UMLRTTimespec::UMLRTTimespec( long seconds, long nanoseconds ): tv_sec(seconds), tv_nsec(nanoseconds)
+{
+    timespecAdjust(this);
+}
+
+UMLRTTimespec::UMLRTTimespec() { UMLRTTimespec::getClock(this); }
+
+UMLRTTimespec & UMLRTTimespec::operator=( const UMLRTTimespec & tm )
+{
+    tv_sec = tm.tv_sec;
+    tv_nsec = tm.tv_nsec;
+
+    return *this;
+}
+
+bool UMLRTTimespec::operator==( const UMLRTTimespec & tm ) const
+{
+    return (tv_sec == tm.tv_sec) && (tv_nsec == tm.tv_nsec);
+}
+
+bool UMLRTTimespec::operator!=( const UMLRTTimespec & tm ) const
+{
+    return (tv_sec != tm.tv_sec) || (tv_nsec != tm.tv_nsec);
+}
+
+bool UMLRTTimespec::operator<( const UMLRTTimespec & tm ) const
+{
+    if (tv_sec < tm.tv_sec)
+        return true;
+
+    else if (tv_sec == tm.tv_sec)
+        return (tv_nsec < tm.tv_nsec);
+
+    return false;
+}
+
+bool UMLRTTimespec::operator<=( const UMLRTTimespec & tm ) const
+{
+    if (tv_sec < tm.tv_sec)
+        return true;
+
+    else if (tv_sec == tm.tv_sec)
+        return (tv_nsec <= tm.tv_nsec);
+
+    return false;
+}
+
+bool UMLRTTimespec::operator>( const UMLRTTimespec & tm ) const
+{
+    if (tv_sec > tm.tv_sec)
+            return true;
+
+        else if (tv_sec == tm.tv_sec)
+            return (tv_nsec > tm.tv_nsec);
+
+        return false;
+}
+
+bool UMLRTTimespec::operator>=( const UMLRTTimespec & tm ) const
+{
+    if (tv_sec > tm.tv_sec)
+        return true;
+
+    else if (tv_sec == tm.tv_sec)
+        return (tv_nsec >= tm.tv_nsec);
+
+    return false;
+}
+
+// Ensure tv_nsec is always 0..999999999.
+/*static*/ void UMLRTTimespec::timespecAdjust( UMLRTTimespec * tm )
+{
+    // Times must be adjusted after a single add/subtract, so tv_nsec is assumed to be
+    // between -999999999 and 2*999999999 before it is adjusted.
+    // We do a sanity check after the adjustment to confirm our assumptions are correct.
+    if (tm->tv_nsec > ONE_BILLION)
+    {
+        tm->tv_sec += 1;
+        tm->tv_nsec -= ONE_BILLION;
+    }
+    if (tm->tv_nsec < 0)
+    {
+        tm->tv_sec -= 1;
+        tm->tv_nsec += ONE_BILLION;
+    }
+    // For now, we FATAL() if tm->tv_nsec was not sufficiently adjusted.
+    if (tm->tv_nsec > ONE_BILLION)
+    {
+        FATAL("time tv_nsec(%ld) > ONE_BILLION", tm->tv_nsec);
+    }
+    if (tm->tv_nsec < 0)
+    {
+        FATAL("time tv_nsec(%ld) < 0", tm->tv_nsec);
+    }
+}
+
+UMLRTTimespec UMLRTTimespec::operator+( const UMLRTTimespec & tm ) const
+{
+    return UMLRTTimespec(tv_sec + tm.tv_sec, tv_nsec + tm.tv_nsec);
+}
+
+UMLRTTimespec UMLRTTimespec::operator-( const UMLRTTimespec & tm ) const
+{
+    return UMLRTTimespec(tv_sec - tm.tv_sec, tv_nsec - tm.tv_nsec);
+}
+
+UMLRTTimespec & UMLRTTimespec::operator+=( const UMLRTTimespec & tm )
+{
+    tv_sec += tm.tv_sec;
+    tv_nsec += tm.tv_nsec;
+
+    timespecAdjust(this);
+
+    return *this;
+}
+
+UMLRTTimespec & UMLRTTimespec::operator-=( const UMLRTTimespec & tm )
+{
+    tv_sec -= tm.tv_sec;
+    tv_nsec -= tm.tv_nsec;
+
+    timespecAdjust(this);
+
+    return *this;
+}
+
+/*static*/ void UMLRTTimespec::getClock( UMLRTTimespec * tm )
+{
+    // Linux-specific for now.
+    struct timeval tv;
+
+    if (gettimeofday(&tv, NULL) < 0)
+    {
+        FATAL_ERRNO("gettimeofday");
+    }
+    tm->tv_sec = tv.tv_sec;
+    tm->tv_nsec = tv.tv_usec * 1000;
+}
+
+bool UMLRTTimespec::isZeroOrNegative() const
+{
+    return (tv_sec < 0) || ((tv_sec == 0) && (tv_nsec == 0));
+}
+
+char * UMLRTTimespec::toString( char * buffer, int size ) const
+{
+    struct tm from_localtime;
+    const time_t seconds = tv_sec;
+
+    localtime_r( &seconds, &from_localtime );
+
+    size_t length = strftime(buffer, size, "%Y-%m-%d:%H:%M:%S", &from_localtime);
+    long msec = tv_nsec / NANOSECONDS_PER_MILLISECOND;
+    snprintf( &buffer[length], size-length, ".%03ld", msec );
+
+    return buffer;
+}
+
+char * UMLRTTimespec::toStringRelative( char * buffer, int size ) const
+{
+    long int seconds = tv_sec;
+    long int days = seconds / SECONDS_PER_DAY;
+    seconds -= (days * SECONDS_PER_DAY);
+    long int hours = seconds / SECONDS_PER_HOUR;
+    seconds -= (hours * SECONDS_PER_HOUR);
+    long int minutes = seconds / SECONDS_PER_MINUTE;
+    seconds -= (minutes * SECONDS_PER_MINUTE);
+
+    long int msec = tv_nsec / NANOSECONDS_PER_MILLISECOND;
+
+    snprintf( buffer, size, "%ld:%02ld:%02ld:%02ld.%03ld", days, hours, minutes, seconds, msec );
+
+    return buffer;
+}
+
+/*static*/ void UMLRTTimespec::timespecAbsAddMsec( struct timespec * timeout, long msec )
+{
+    clock_gettime(CLOCK_REALTIME, timeout);
+    timeout->tv_sec += (msec / 1000);
+    timeout->tv_nsec += (msec % 1000) * ONE_BILLION;
+    if (timeout->tv_nsec >= ONE_BILLION)
+    {
+        timeout->tv_sec += 1;
+        timeout->tv_nsec -= ONE_BILLION;
+    }
+}