Merged changes from Base-3.14, to revno 12613

This commit is contained in:
Andrew Johnson
2016-02-25 14:13:40 -06:00
15 changed files with 347 additions and 273 deletions

View File

@@ -14,6 +14,29 @@
<h2 align="center">Changes between 3.15.3 and 3.15.4</h2>
<!-- Insert new items immediately below here ... -->
<h3>CALC engine bitwise operator fixes</h3>
<p>The bitwise operators in the CALC engine have been modified to work properly
with values that have bit 31 (0x80000000) set. This modification involved
back-porting some earlier changes from the 3.15 branch, and fixes
<a href="https://code.launchpad.net/bugs/1514520">Launchpad bug
#1514520</a>.</p>
<h3>Fix <tt>ipAddrToAsciiAsync()</tt>: don't try to join the daemon thread</h3>
<p>On process exit, don't try to stop the worker thread that makes DNS lookups
asynchronous. Previously this would wait for any lookups still in progress,
delaying the exit unnecessarily. This was most obvious with catools (eg.
cainfo).
<a href="https://bugs.launchpad.net/epics-base/+bug/1527636">lp:1527636</a></p>
<h3>Fix epicsTime_localtime() on Windows</h3>
<p>Simpler versions of the epicsTime_gmtime() and epicsTime_localtime()
routines have been included in the Windows implementations, and a new test
program added. The original versions do not report DST status properly. Fixes
<a href="https://bugs.launchpad.net/bugs/1528284">Launchpad bug 1528284</a>.</p>
<h3>Moved <tt>mlockall()</tt> into its own epicsThread routine</h3>
<p>Since EPICS Base 3.15.0.2 on Posix OSs the initialization of the epicsThread

View File

@@ -264,19 +264,27 @@ void cast_server(void *pParm)
if(prsrv_cast_client->recv.cnt !=
prsrv_cast_client->recv.stk){
char buf[40];
ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));
epicsPrintf ("CAS: partial (damaged?) UDP msg of %d bytes from %s ?\n",
prsrv_cast_client->recv.cnt-prsrv_cast_client->recv.stk, buf);
epicsTimeToStrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
&prsrv_cast_client->time_at_last_recv);
epicsPrintf ("CAS: message received at %s\n", buf);
}
}
else {
char buf[40];
ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));
epicsPrintf ("CAS: invalid (damaged?) UDP request from %s ?\n", buf);
epicsTimeToStrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S",
&prsrv_cast_client->time_at_last_recv);
epicsPrintf ("CAS: message received at %s\n", buf);
}
if (CASDEBUG>2) {

View File

@@ -33,6 +33,10 @@ static int cond_search(const char **ppinst, int match);
#define PI 3.14159265358979323
#endif
/* Turn off global optimization for 64-bit MSVC builds */
#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
# pragma optimize("g", off)
#endif
/* calcPerform
*
@@ -45,6 +49,7 @@ epicsShareFunc long
double *ptop; /* stack pointer */
double top; /* value from top of stack */
epicsInt32 itop; /* integer from top of stack */
epicsUInt32 utop; /* unsigned integer from top of stack */
int op;
int nargs;
@@ -262,7 +267,7 @@ epicsShareFunc long
case NINT:
top = *ptop;
*ptop = (double)(epicsInt32)(top >= 0 ? top + 0.5 : top - 0.5);
*ptop = (epicsInt32) (top >= 0 ? top + 0.5 : top - 0.5);
break;
case RANDOM:
@@ -283,34 +288,45 @@ epicsShareFunc long
*ptop = ! *ptop;
break;
/* For bitwise operations on values with bit 31 set, double values
* must first be cast to unsigned to correctly set that bit; the
* double value must be negative in that case. The result must be
* cast to a signed integer before converting to the double result.
*/
case BIT_OR:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop | itop;
utop = *ptop--;
*ptop = (epicsInt32) ((epicsUInt32) *ptop | utop);
break;
case BIT_AND:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop & itop;
utop = *ptop--;
*ptop = (epicsInt32) ((epicsUInt32) *ptop & utop);
break;
case BIT_EXCL_OR:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop ^ itop;
utop = *ptop--;
*ptop = (epicsInt32) ((epicsUInt32) *ptop ^ utop);
break;
case BIT_NOT:
itop = (epicsInt32) *ptop;
*ptop = ~itop;
utop = *ptop;
*ptop = (epicsInt32) ~utop;
break;
/* The shift operators use signed integers, so a right-shift will
* extend the sign bit into the left-hand end of the value. The
* double-casting through unsigned here is important, see above.
*/
case RIGHT_SHIFT:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop >> itop;
utop = *ptop--;
*ptop = ((epicsInt32) (epicsUInt32) *ptop) >> (utop & 31);
break;
case LEFT_SHIFT:
itop = (epicsInt32) *ptop--;
*ptop = (epicsInt32) *ptop << itop;
utop = *ptop--;
*ptop = ((epicsInt32) (epicsUInt32) *ptop) << (utop & 31);
break;
case NOT_EQ:
@@ -367,6 +383,9 @@ epicsShareFunc long
*presult = *ptop;
return 0;
}
#if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
# pragma optimize("", on)
#endif
epicsShareFunc long

View File

@@ -251,7 +251,7 @@ epicsShareFunc long
goto bad;
}
psrc = pnext;
lit_i = (int) lit_d;
lit_i = (epicsInt32) lit_d;
if (lit_d != (double) lit_i) {
*pout++ = pel->code;
memcpy(pout, &lit_d, sizeof(double));
@@ -272,8 +272,8 @@ epicsShareFunc long
}
psrc = pnext;
*pout++ = LITERAL_INT;
memcpy(pout, &lit_ui, sizeof(epicsInt32));
pout += sizeof(epicsInt32);
memcpy(pout, &lit_ui, sizeof(epicsUInt32));
pout += sizeof(epicsUInt32);
}
operand_needed = FALSE;

View File

@@ -81,7 +81,6 @@ template class tsFreeList
extern "C" {
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
static void ipAddrToAsciiEngineShutdownRequest ( void * );
}
// - this class executes the synchronous DNS query
@@ -107,10 +106,7 @@ private:
unsigned cancelPendingCount;
bool exitFlag;
bool callbackInProgress;
static epicsMutex * pGlobalMutex;
static ipAddrToAsciiEnginePrivate * pEngine;
static unsigned numberOfReferences;
static bool shutdownRequest;
ipAddrToAsciiTransaction & createTransaction ();
void release ();
void run ();
@@ -118,15 +114,11 @@ private:
ipAddrToAsciiEnginePrivate & operator = ( const ipAddrToAsciiEngine & );
friend class ipAddrToAsciiEngine;
friend class ipAddrToAsciiTransactionPrivate;
friend void ipAddrToAsciiEngineShutdownRequest ( void * );
friend void ipAddrToAsciiEngineGlobalMutexConstruct ( void * );
};
epicsMutex * ipAddrToAsciiEnginePrivate :: pGlobalMutex = 0;
ipAddrToAsciiEnginePrivate * ipAddrToAsciiEnginePrivate :: pEngine = 0;
unsigned ipAddrToAsciiEnginePrivate :: numberOfReferences = 0u;
bool ipAddrToAsciiEnginePrivate :: shutdownRequest = false;
static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = 0;
static epicsThreadOnceId ipAddrToAsciiEngineGlobalMutexOnceFlag = EPICS_THREAD_ONCE_INIT;
// the users are not required to supply a show routine
// for there transaction callback class
@@ -137,26 +129,13 @@ ipAddrToAsciiCallBack::~ipAddrToAsciiCallBack () {}
ipAddrToAsciiTransaction::~ipAddrToAsciiTransaction () {}
ipAddrToAsciiEngine::~ipAddrToAsciiEngine () {}
static void ipAddrToAsciiEngineShutdownRequest ( void * )
{
bool deleteGlobalMutexCondDetected = false;
{
epicsGuard < epicsMutex >
guard ( * ipAddrToAsciiEnginePrivate :: pGlobalMutex );
ipAddrToAsciiEnginePrivate :: shutdownRequest = true;
deleteGlobalMutexCondDetected =
( ipAddrToAsciiEnginePrivate :: numberOfReferences == 0 );
}
if ( deleteGlobalMutexCondDetected ) {
delete ipAddrToAsciiEnginePrivate :: pGlobalMutex;
ipAddrToAsciiEnginePrivate :: pGlobalMutex = 0;
}
}
static void ipAddrToAsciiEngineGlobalMutexConstruct ( void * )
{
ipAddrToAsciiEnginePrivate :: pGlobalMutex = newEpicsMutex;
epicsAtExit ( ipAddrToAsciiEngineShutdownRequest, 0 );
try {
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiEnginePrivate ();
} catch (std::exception& e) {
errlogPrintf("ipAddrToAsciiEnginePrivate ctor fails with: %s\n", e.what());
}
}
// for now its probably sufficent to allocate one
@@ -168,21 +147,8 @@ ipAddrToAsciiEngine & ipAddrToAsciiEngine::allocate ()
epicsThreadOnce (
& ipAddrToAsciiEngineGlobalMutexOnceFlag,
ipAddrToAsciiEngineGlobalMutexConstruct, 0 );
// since we must not own lock when checking this flag
// this diagnostic has imperfect detection, but never
// incorrect detection
if ( ipAddrToAsciiEnginePrivate :: shutdownRequest ) {
throw std :: runtime_error (
"ipAddrToAsciiEngine::allocate (): "
"attempts to create an "
"ipAddrToAsciiEngine while the exit "
"handlers are running are rejected");
}
epicsGuard < epicsMutex > guard ( * ipAddrToAsciiEnginePrivate::pGlobalMutex );
if ( ! ipAddrToAsciiEnginePrivate::pEngine ) {
ipAddrToAsciiEnginePrivate::pEngine = new ipAddrToAsciiEnginePrivate ();
}
ipAddrToAsciiEnginePrivate::numberOfReferences++;
if(!ipAddrToAsciiEnginePrivate::pEngine)
throw std::runtime_error("ipAddrToAsciiEngine::allocate fails");
return * ipAddrToAsciiEnginePrivate::pEngine;
}
@@ -206,32 +172,8 @@ ipAddrToAsciiEnginePrivate::~ipAddrToAsciiEnginePrivate ()
this->thread.exitWait ();
}
// for now its probably sufficient to allocate one
// DNS transaction thread for all codes sharing
// the same process that need DNS services but we
// leave our options open for the future
void ipAddrToAsciiEnginePrivate::release ()
{
bool deleteGlobalMutexCondDetected = false;
epicsThreadOnce (
& ipAddrToAsciiEngineGlobalMutexOnceFlag,
ipAddrToAsciiEngineGlobalMutexConstruct, 0 );
{
epicsGuard < epicsMutex >
guard ( * ipAddrToAsciiEnginePrivate::pGlobalMutex );
assert ( ipAddrToAsciiEnginePrivate::numberOfReferences > 0u );
ipAddrToAsciiEnginePrivate::numberOfReferences--;
if ( ipAddrToAsciiEnginePrivate::numberOfReferences == 0u ) {
deleteGlobalMutexCondDetected =
ipAddrToAsciiEnginePrivate :: shutdownRequest;
delete ipAddrToAsciiEnginePrivate :: pEngine;
ipAddrToAsciiEnginePrivate :: pEngine = 0;
}
}
if ( deleteGlobalMutexCondDetected ) {
delete ipAddrToAsciiEnginePrivate :: pGlobalMutex;
ipAddrToAsciiEnginePrivate :: pGlobalMutex = 0;
}
}
void ipAddrToAsciiEnginePrivate::show ( unsigned level ) const
@@ -365,6 +307,8 @@ ipAddrToAsciiTransactionPrivate::~ipAddrToAsciiTransactionPrivate ()
if ( this->engine.pCurrent == this &&
this->engine.callbackInProgress &&
! this->engine.thread.isCurrentThread() ) {
// cancel from another thread while callback in progress
// waits for callback to complete
assert ( this->engine.cancelPendingCount < UINT_MAX );
this->engine.cancelPendingCount++;
{
@@ -382,9 +326,11 @@ ipAddrToAsciiTransactionPrivate::~ipAddrToAsciiTransactionPrivate ()
}
else {
if ( this->engine.pCurrent == this ) {
// cancel from callback, or while lookup in progress
this->engine.pCurrent = 0;
}
else {
// cancel before lookup starts
this->engine.labor.remove ( *this );
}
this->pending = false;

View File

@@ -124,148 +124,31 @@ static int osdTimeGetCurrent ( epicsTimeStamp *pDest )
return epicsTimeOK;
}
inline void UnixTimeToFileTime ( const time_t * pAnsiTime, LPFILETIME pft )
{
LONGLONG ll = Int32x32To64 ( *pAnsiTime, 10000000 ) + 116444736000000000LL;
pft->dwLowDateTime = static_cast < DWORD > ( ll );
pft->dwHighDateTime = static_cast < DWORD > ( ll >>32 );
}
static int daysInMonth[] = { 31, 28, 31, 30, 31, 30, 31,
31, 30, 31, 30, 31 };
static bool isLeapYear ( DWORD year )
{
if ( (year % 4) == 0 ) {
return ( ( year % 100 ) != 0 || ( year % 400 ) == 0 );
} else {
return false;
}
}
static int dayOfYear ( DWORD day, DWORD month, DWORD year )
{
DWORD nDays = 0;
for ( unsigned m = 1; m < month; m++ ) {
nDays += daysInMonth[m-1];
if ( m == 2 && isLeapYear(year) ) {
nDays++;
}
}
return nDays + day;
}
// synthesize a reentrant gmtime on WIN32
int epicsShareAPI epicsTime_gmtime ( const time_t *pAnsiTime, struct tm *pTM )
{
FILETIME ft;
UnixTimeToFileTime ( pAnsiTime, &ft );
SYSTEMTIME st;
BOOL status = FileTimeToSystemTime ( &ft, &st );
if ( ! status ) {
return epicsTimeERROR;
struct tm * pRet = gmtime ( pAnsiTime );
if ( pRet ) {
*pTM = *pRet;
return epicsTimeOK;
}
else {
return errno;
}
pTM->tm_sec = st.wSecond; // seconds after the minute - [0,59]
pTM->tm_min = st.wMinute; // minutes after the hour - [0,59]
pTM->tm_hour = st.wHour; // hours since midnight - [0,23]
assert ( st.wDay >= 1 && st.wDay <= 31 );
pTM->tm_mday = st.wDay; // day of the month - [1,31]
assert ( st.wMonth >= 1 && st.wMonth <= 12 );
pTM->tm_mon = st.wMonth - 1; // months since January - [0,11]
assert ( st.wYear >= 1900 );
pTM->tm_year = st.wYear - 1900; // years since 1900
pTM->tm_wday = st.wDayOfWeek; // days since Sunday - [0,6]
pTM->tm_yday = dayOfYear ( st.wDay, st.wMonth, st.wYear ) - 1;
pTM->tm_isdst = 0;
return epicsTimeOK;
}
// synthesize a reentrant localtime on WIN32
int epicsShareAPI epicsTime_localtime (
const time_t * pAnsiTime, struct tm * pTM )
{
FILETIME ft;
UnixTimeToFileTime ( pAnsiTime, & ft );
TIME_ZONE_INFORMATION tzInfo;
DWORD tzStatus = GetTimeZoneInformation ( & tzInfo );
if ( tzStatus == TIME_ZONE_ID_INVALID ) {
return epicsTimeERROR;
struct tm * pRet = localtime ( pAnsiTime );
if ( pRet ) {
*pTM = *pRet;
return epicsTimeOK;
}
//
// There are remarkable weaknesses in the FileTimeToLocalFileTime
// interface so we don't use it here. Unfortunately, there is no
// corresponding function that works on file time.
//
SYSTEMTIME st;
BOOL success = FileTimeToSystemTime ( & ft, & st );
if ( ! success ) {
return epicsTimeERROR;
else {
return errno;
}
SYSTEMTIME lst;
success = SystemTimeToTzSpecificLocalTime (
& tzInfo, & st, & lst );
if ( ! success ) {
return epicsTimeERROR;
}
//
// We must convert back to file time so that we can determine if DST
// is active...
//
FILETIME lft;
success = SystemTimeToFileTime ( & lst, & lft );
if ( ! success ) {
return epicsTimeERROR;
}
int is_dst = -1; // unknown state of dst
if ( tzStatus != TIME_ZONE_ID_UNKNOWN &&
tzInfo.StandardDate.wMonth != 0 &&
tzInfo.DaylightDate.wMonth != 0) {
// determine if the specified date is
// in daylight savings time
tzInfo.StandardDate.wYear = st.wYear;
FILETIME StandardDateFT;
success = SystemTimeToFileTime (
& tzInfo.StandardDate, & StandardDateFT );
if ( ! success ) {
return epicsTimeERROR;
}
tzInfo.DaylightDate.wYear = st.wYear;
FILETIME DaylightDateFT;
success = SystemTimeToFileTime (
& tzInfo.DaylightDate, & DaylightDateFT );
if ( ! success ) {
return epicsTimeERROR;
}
if ( CompareFileTime ( & lft, & DaylightDateFT ) >= 0
&& CompareFileTime ( & lft, & StandardDateFT ) < 0 ) {
is_dst = 1;
}
else {
is_dst = 0;
}
}
pTM->tm_sec = lst.wSecond; // seconds after the minute - [0,59]
pTM->tm_min = lst.wMinute; // minutes after the hour - [0,59]
pTM->tm_hour = lst.wHour; // hours since midnight - [0,23]
assert ( lst.wDay >= 1 && lst.wDay <= 31 );
pTM->tm_mday = lst.wDay; // day of the month - [1,31]
assert ( lst.wMonth >= 1 && lst.wMonth <= 12 );
pTM->tm_mon = lst.wMonth - 1; // months since January - [0,11]
assert ( lst.wYear >= 1900 );
pTM->tm_year = lst.wYear - 1900; // years since 1900
pTM->tm_wday = lst.wDayOfWeek; // days since Sunday - [0,6]
pTM->tm_yday = dayOfYear ( lst.wDay, lst.wMonth, lst.wYear ) - 1;
pTM->tm_isdst = is_dst;
return epicsTimeOK;
}
currentTime::currentTime () :

View File

@@ -96,6 +96,10 @@ epicsTimeTest_SRCS += epicsTimeTest.cpp
testHarness_SRCS += epicsTimeTest.cpp
TESTS += epicsTimeTest
TESTPROD_HOST += epicsTimeZoneTest
epicsTimeZoneTest_SRCS += epicsTimeZoneTest.c
TESTS += epicsTimeZoneTest
TESTPROD_HOST += epicsThreadTest
epicsThreadTest_SRCS += epicsThreadTest.cpp
testHarness_SRCS += epicsThreadTest.cpp

View File

@@ -8,6 +8,7 @@
// Author: Andrew Johnson
#include "epicsUnitTest.h"
#include "epicsTypes.h"
#include "epicsMath.h"
#include "epicsAlgorithm.h"
#include "postfix.h"
@@ -38,32 +39,59 @@ void testCalc(const char *expr, double expected) {
/* Evaluate expression, test against expected result */
bool pass = false;
double args[CALCPERFORM_NARGS] = {
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0
};
char rpn[MAX_POSTFIX_SIZE];
short err;
double result = 0.0;
result /= result; /* Start as NaN */
if (postfix(expr, rpn, &err)) {
testDiag("postfix: %s in expression '%s'", calcErrorStr(err), expr);
testDiag("postfix: %s in expression '%s'", calcErrorStr(err), expr);
} else
if (calcPerform(args, &result, rpn) && finite(result)) {
testDiag("calcPerform: error evaluating '%s'", expr);
}
if (calcPerform(args, &result, rpn) && finite(result)) {
testDiag("calcPerform: error evaluating '%s'", expr);
}
if (finite(expected) && finite(result)) {
pass = fabs(expected - result) < 1e-8;
pass = fabs(expected - result) < 1e-8;
} else if (isnan(expected)) {
pass = (bool) isnan(result);
pass = (bool) isnan(result);
} else {
pass = (result == expected);
pass = (result == expected);
}
if (!testOk(pass, "%s", expr)) {
testDiag("Expected result is %g, actually got %g", expected, result);
calcExprDump(rpn);
testDiag("Expected result is %g, actually got %g", expected, result);
calcExprDump(rpn);
}
}
void testUInt32Calc(const char *expr, epicsUInt32 expected) {
/* Evaluate expression, test against expected result */
bool pass = false;
double args[CALCPERFORM_NARGS] = {
1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0
};
char rpn[MAX_POSTFIX_SIZE];
short err;
epicsUInt32 uresult;
double result = 0.0;
result /= result; /* Start as NaN */
if (postfix(expr, rpn, &err)) {
testDiag("postfix: %s in expression '%s'", calcErrorStr(err), expr);
} else
if (calcPerform(args, &result, rpn) && finite(result)) {
testDiag("calcPerform: error evaluating '%s'", expr);
}
uresult = (epicsUInt32) result;
pass = (uresult == expected);
if (!testOk(pass, "%s", expr)) {
testDiag("Expected result is 0x%x (%u), actually got 0x%x (%u)",
expected, expected, uresult, uresult);
calcExprDump(rpn);
}
return;
}
void testArgs(const char *expr, unsigned long einp, unsigned long eout) {
@@ -238,8 +266,8 @@ MAIN(epicsCalcTest)
const double a=1.0, b=2.0, c=3.0, d=4.0, e=5.0, f=6.0,
g=7.0, h=8.0, i=9.0, j=10.0, k=11.0, l=12.0;
testPlan(577);
testPlan(613);
/* LITERAL_OPERAND elements */
testExpr(0);
testExpr(1);
@@ -883,7 +911,51 @@ MAIN(epicsCalcTest)
testBadExpr("1?", CALC_ERR_CONDITIONAL);
testBadExpr("1?1", CALC_ERR_CONDITIONAL);
testBadExpr(":1", CALC_ERR_SYNTAX);
// Bit manipulations wrt bit 31 (bug lp:1514520)
// using integer literals
testUInt32Calc("0xaaaaaaaa AND 0xffff0000", 0xaaaa0000u);
testUInt32Calc("0xaaaaaaaa OR 0xffff0000", 0xffffaaaau);
testUInt32Calc("0xaaaaaaaa XOR 0xffff0000", 0x5555aaaau);
testUInt32Calc("~0xaaaaaaaa", 0x55555555u);
testUInt32Calc("~~0xaaaaaaaa", 0xaaaaaaaau);
testUInt32Calc("0xaaaaaaaa >> 8", 0xffaaaaaau);
testUInt32Calc("0xaaaaaaaa << 8", 0xaaaaaa00u);
// using integer literals assigned to variables
testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a AND b", 0xaaaa0000u);
testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a OR b", 0xffffaaaau);
testUInt32Calc("a:=0xaaaaaaaa; b:=0xffff0000; a XOR b", 0x5555aaaau);
testUInt32Calc("a:=0xaaaaaaaa; ~a", 0x55555555u);
testUInt32Calc("a:=0xaaaaaaaa; ~~a", 0xaaaaaaaau);
testUInt32Calc("a:=0xaaaaaaaa; a >> 8", 0xffaaaaaau);
testUInt32Calc("a:=0xaaaaaaaa; a << 8", 0xaaaaaa00u);
// Test proper conversion of double values (+ 0.1 enforces double literal)
// when used as inputs to the bitwise operations.
// 0xaaaaaaaa = -1431655766 or 2863311530u
testUInt32Calc("-1431655766.1 OR 0", 0xaaaaaaaau);
testUInt32Calc("2863311530.1 OR 0", 0xaaaaaaaau);
testUInt32Calc("0 OR -1431655766.1", 0xaaaaaaaau);
testUInt32Calc("0 OR 2863311530.1", 0xaaaaaaaau);
testUInt32Calc("-1431655766.1 XOR 0", 0xaaaaaaaau);
testUInt32Calc("2863311530.1 XOR 0", 0xaaaaaaaau);
testUInt32Calc("0 XOR -1431655766.1", 0xaaaaaaaau);
testUInt32Calc("0 XOR 2863311530.1", 0xaaaaaaaau);
testUInt32Calc("-1431655766.1 AND 0xffffffff", 0xaaaaaaaau);
testUInt32Calc("2863311530.1 AND 0xffffffff", 0xaaaaaaaau);
testUInt32Calc("0xffffffff AND -1431655766.1", 0xaaaaaaaau);
testUInt32Calc("0xffffffff AND 2863311530.1", 0xaaaaaaaau);
testUInt32Calc("~ -1431655766.1", 0x55555555u);
testUInt32Calc("~ 2863311530.1", 0x55555555u);
testUInt32Calc("-1431655766.1 >> 0", 0xaaaaaaaau);
testUInt32Calc("2863311530.1 >> 0", 0xaaaaaaaau);
testUInt32Calc("-1431655766.1 >> 0.1", 0xaaaaaaaau);
testUInt32Calc("2863311530.1 >> 0.1", 0xaaaaaaaau);
testUInt32Calc("-1431655766.1 << 0", 0xaaaaaaaau);
testUInt32Calc("2863311530.1 << 0", 0xaaaaaaaau);
testUInt32Calc("-1431655766.1 << 0.1", 0xaaaaaaaau);
testUInt32Calc("2863311530.1 << 0.1", 0xaaaaaaaau);
return testDone();
}

View File

@@ -0,0 +1,117 @@
/*************************************************************************\
* Copyright (c) 2015 Michael Davidsaver
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include <stdio.h>
#include "envDefs.h"
#include "epicsTime.h"
#include "epicsUnitTest.h"
#include "testMain.h"
#if defined(_WIN32)
# define tzset _tzset
#endif
static
void setTZ(const char *base, const char *dst, int offset)
{
char tz[20];
if(offset!=0 || dst)
sprintf(tz, "%s%d%s", base, offset/3600, dst);
else
sprintf(tz, "%s", base);
testDiag("TZ=\"%s\"", tz);
epicsEnvSet("TZ", tz);
tzset();
}
static
void test_localtime(time_t T, int sec, int min, int hour,
int mday, int mon, int year,
int wday, int yday, int isdst)
{
struct tm B;
testDiag("test_localtime(%ld, ...)", (long)T);
if(epicsTime_localtime(&T, &B)!=epicsTimeOK) {
testFail("epicsTime_localtime() error");
testSkip(9, "epicsTime_localtime() failed");
} else {
B.tm_year += 1900; /* for readability */
testPass("epicsTime_localtime() success");
#define TEST(FLD) testOk(B.tm_##FLD==FLD, "%s %d==%d", #FLD, B.tm_##FLD, FLD)
TEST(sec);
TEST(min);
TEST(hour);
TEST(mday);
TEST(mon);
TEST(year);
TEST(wday);
TEST(yday);
TEST(isdst);
#undef TEST
}
}
static
void test_gmtime(time_t T, int sec, int min, int hour,
int mday, int mon, int year,
int wday, int yday, int isdst)
{
struct tm B;
testDiag("test_gmtime(%ld, ...)", (long)T);
if(epicsTime_gmtime(&T, &B)!=epicsTimeOK) {
testFail("epicsTime_localtime() error");
testSkip(9, "epicsTime_localtime() failed");
} else {
B.tm_year += 1900; /* for readability */
testPass("epicsTime_localtime() success");
#define TEST(FLD) testOk(B.tm_##FLD==FLD, "%s %d==%d", #FLD, B.tm_##FLD, FLD)
TEST(sec);
TEST(min);
TEST(hour);
TEST(mday);
TEST(mon);
TEST(year);
TEST(wday);
TEST(yday);
TEST(isdst);
#undef TEST
}
}
MAIN(epicsTimeZoneTest)
{
testPlan(80);
/* 1445259616
* Mon Oct 19 09:00:16 2015 EDT
* Mon Oct 19 08:00:16 2015 CDT
* Mon Oct 19 13:00:16 2015 UTC
*/
testDiag("POSIX 1445259616");
setTZ("EST", "EDT", 5*3600);
test_localtime(1445259616ul, 16, 0, 9, 19, 9, 2015, 1, 291, 1);
setTZ("CST", "CDT", 6*3600);
test_localtime(1445259616ul, 16, 0, 8, 19, 9, 2015, 1, 291, 1);
setTZ("UTC", NULL, 0);
test_localtime(1445259616ul, 16, 0, 13, 19, 9, 2015, 1, 291, 0);
test_gmtime(1445259616ul, 16, 0, 13, 19, 9, 2015, 1, 291, 0);
/* 1421244931
* Wed Jan 14 09:15:31 2015 EST
* Wed Jan 14 08:15:31 2015 CST
* Wed Jan 14 14:15:31 2015 UTC
*/
testDiag("POSIX 1421244931");
setTZ("EST", "EDT", 5*3600);
test_localtime(1421244931ul, 31, 15, 9, 14, 0, 2015, 3, 13, 0);
setTZ("CST", "CDT", 6*3600);
test_localtime(1421244931ul, 31, 15, 8, 14, 0, 2015, 3, 13, 0);
setTZ("UTC", NULL, 0);
test_localtime(1421244931ul, 31, 15, 14, 14, 0, 2015, 3, 13, 0);
test_gmtime(1421244931ul, 31, 15, 14, 14, 0, 2015, 3, 13, 0);
return testDone();
}

View File

@@ -17,5 +17,5 @@ softMain$(DEP): epicsInstallDir.h
epicsInstallDir.h:
$(ECHO) "FINAL_LOCATION=$(FINAL_LOCATION)"
$(PERL) $(STDDIR)/softIoc/makeInstallDir.pl '$(FINAL_LOCATION)' > $@
$(PERL) $(STDDIR)/softIoc/makeInstallDir.pl "$(FINAL_LOCATION)" > $@

View File

@@ -9,7 +9,8 @@ eval 'exec perl -S $0 ${1+"$@"}' # -*- Mode: perl -*-
use strict;
die "Path to INSTALL_LOCATION missing\n" unless @ARGV == 1;
die "$0: Argument missing, INSTALL_LOCATION\n" if @ARGV == 0;
die "$0: Too many arguments, expecting one\n" unless @ARGV == 1;
my $path = shift;

View File

@@ -1,48 +1,43 @@
# $Revision-Id$
# CONFIG - Load build configuration data
#
# Do not make changes in this file, any site-specific
# overrides should be given in a CONFIG_SITE file.
# You might want to change this to some shared set of rules, e.g.
# RULES=/path/to/epics/support/modules/rules/x-y
RULES=$(EPICS_BASE)
# Where the build rules come from
RULES = $(EPICS_BASE)
INSTALL_IDLFILE = $(INSTALL)
include $(TOP)/configure/RELEASE
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
ifdef T_A
-include $(TOP)/configure/RELEASE.Common.$(T_A)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
-include $(TOP)/configure/RELEASE.Common.$(T_A)
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
endif
CONFIG=$(RULES)/configure
CONFIG = $(RULES)/configure
include $(CONFIG)/CONFIG
# Override for definition in base
# Override some Base definitions
INSTALL_LOCATION = $(TOP)
# CONFIG_SITE files contain build configuration overrides
include $(TOP)/configure/CONFIG_SITE
ifdef INSTALL_LOCATION_EXTENSIONS
INSTALL_LOCATION = $(INSTALL_LOCATION_EXTENSIONS)
endif
# Site specific host architecture definitions
# Host-arch specific settings
-include $(TOP)/configure/os/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
ifdef INSTALL_LOCATION_EXTENSIONS
INSTALL_LOCATION = $(INSTALL_LOCATION_EXTENSIONS)
endif
ifdef T_A
# Target-arch specific settings
-include $(TOP)/configure/os/CONFIG_SITE.Common.$(T_A)
# Site specific target architecture definitions
-include $(TOP)/configure/os/CONFIG_SITE.Common.$(T_A)
# Cross compile specific definitions
ifneq ($(EPICS_HOST_ARCH),$(T_A))
-include $(TOP)/configure/CONFIG.CrossCommon
endif
# Site specific host-target combination definitions
-include $(TOP)/configure/os/CONFIG.$(EPICS_HOST_ARCH).$(T_A)
-include $(TOP)/configure/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
-include $(TOP)/configure/O.$(T_A)/CONFIG_APP_INCLUDE
# Host & target specific combination settings
-include $(TOP)/configure/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
endif

View File

@@ -1,22 +1,23 @@
#RELEASE Location of external products
# RELEASE Locations of external modules
#
# NOTE: The build does not check dependancies on files
# external to this application. Thus you should run
# "gnumake clean uninstall install" in the top directory
# each time EPICS_BASE, SNCSEQ, or any other external
# module defined in a RELEASE* file is rebuilt.
# each time EPICS_BASE or any other external module that
# is defined in a RELEASE* file gets rebuilt.
#
# Host/target specific settings can be specified in files named
# RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(T_A)
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
# Host/target specific paths can be specified in files named
# RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(T_A)
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
# Define INSTALL_LOCATION in CONFIG_SITE
# Location of external products
EPICS_BASE=_EPICS_BASE_
EPICS_EXTENSIONS = $(TOP)
# OAG_APPS may be needed by extension SDDS
#OAG_APPS=$(TOP)/../../oag/apps
# Locations of external modules
# OAG_APPS may be needed by the SDDS extension
#OAG_APPS = $(TOP)/../../oag/apps
EPICS_BASE = _EPICS_BASE_

View File

@@ -1,8 +1,9 @@
# $Revision-Id$
include $(CONFIG)/RULES
include $(TOP)/configure/RULES_PYTHON
include $(TOP)/configure/RULES_IDL
-include $(TOP)/configure/RULES_PYTHON
-include $(TOP)/configure/RULES_IDL
ifdef BASE_3_15
include $(TOP)/configure/RULES_JAVA
-include $(TOP)/configure/RULES_JAVA
endif

View File

@@ -43,7 +43,11 @@ $(PYTHON_PACKAGE_PTH):
%_wrap.c: ../%.i
$(SWIG) -python -o $@ $<
ifdef BASE_3_15
clean:
else
clean::
endif
@$(RM) *.py *.so *.pth
endif